diff --git a/.gitignore b/.gitignore index 9f581680..b4a52775 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,3 @@ -*/target/ -!.mvn/wrapper/maven-wrapper.jar -/logs -.svn - -### IntelliJ IDEA ### -.idea -*.iws +.idea/ +target/ *.iml -*.ipr -*.class -/out/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..8dada3ed --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed 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. diff --git a/README.md b/README.md index e385b7e9..e9df21cd 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,18 @@ ``` ├─algorithms 算法 -│ -├─database 数据库 -│ -├─distributed 分布式 -│ +├─database 数据库 +├─distributed 分布式系统 +├─framework 一些常用类库 ├─java-advance 高级类库和jsr规范等 -│ ├─java-basic Java基础 -│ +├─lesson-code 一些课程代码 ├─mvc mvc框架 -│ ├─orm orm框架 -│ ├─spring-annotation spring注解驱动开发 -│ +├─spring-batch ├─springboot-aop springaop使用以及aop应用 │ -└─springboot-integration-examples spring以及springboot的demo +└─ ``` diff --git a/algorithms/README.MD b/algorithms/README.MD index 9c5e61dc..23e4b53e 100644 --- a/algorithms/README.MD +++ b/algorithms/README.MD @@ -52,3 +52,4 @@ └─interview ``` + diff --git a/algorithms/algorithm-common/pom.xml b/algorithms/algorithm-common/pom.xml new file mode 100644 index 00000000..3afe2696 --- /dev/null +++ b/algorithms/algorithm-common/pom.xml @@ -0,0 +1,15 @@ + + + + algorithms + cn.lastwhisper + 1.0-SNAPSHOT + + 4.0.0 + + algorithm-common + + + \ No newline at end of file diff --git a/algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/array/ArrayUtils.java b/algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/array/ArrayUtils.java new file mode 100644 index 00000000..893e41f3 --- /dev/null +++ b/algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/array/ArrayUtils.java @@ -0,0 +1,97 @@ +package cn.lastwhisper.leetcode.common.array; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author lastwhisper + * @date 2020/2/4 + */ +public class ArrayUtils { + + /** + * {"ab","cd"}=> + * 创建二维字符数组 + */ + public static char[][] createCharArrays(String[] arr) { + int m = arr.length, n = arr[0].length(); + char[][] chars = new char[m][n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + chars[i][j] = arr[i].charAt(j); + } + } + return chars; + } + + /** + * {{"a","b","c","d"}}=> + * 创建二维字符数组 + */ + public static char[][] createCharArrays(String[][] arr) { + int m = arr.length, n = arr[0].length; + char[][] chars = new char[m][n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + chars[i][j] = arr[i][j].charAt(0); + } + } + return chars; + } + + /** + * 创建二维数组 + */ + public static int[][] createIntArrays(String[] arr) { + int m = arr.length, n = arr[0].length(); + int[][] ints = new int[m][n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + ints[i][j] = arr[i].charAt(j) - '0'; + } + } + return ints; + } + + + /** + * 创建list + */ + public static List> createList(int[][] arrays) { + List> lists = new ArrayList<>(arrays.length); + for (int[] array : arrays) { + List list = new ArrayList<>(array.length); + for (int num : array) { + list.add(num); + } + lists.add(list); + } + return lists; + } + + + /** + * 生成无序数组 + * @param length 生成数组的长度 + * @param region 生成数字的范围 + */ + public static int[] generateArrByRandom(int length, int region) { + int[] arr = new int[length]; + for (int i = 0; i < length; i++) { + arr[i] = (int) (Math.random() * region); // region=8000000 生成一个[0,8000000) 的一个数 + } + return arr; + } + + /** + * 生成n~0倒序数组 + */ + public static int[] generateArrByOrder(int n) { + int[] arr = new int[n]; + for (int i = n - 1; i > 0; i--) { + arr[i] = i + 1; + } + return arr; + } +} diff --git a/algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/LinkedListUtils.java b/algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/LinkedListUtils.java new file mode 100644 index 00000000..01c2d3ce --- /dev/null +++ b/algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/LinkedListUtils.java @@ -0,0 +1,289 @@ +package cn.lastwhisper.leetcode.common.linkedlist; + + +import java.util.ArrayList; +import java.util.List; + +/** + * 操作链表工具类 + * @author lastwhisper + * @date 1/7/2020 + */ +public class LinkedListUtils { + + /** + * 创建单链表 + */ + public static ListNode createListNode(int... arr) { + if (arr == null) { + return null; + } + ListNode head = new ListNode(arr[0]); + ListNode current = head; + + for (int i = 1; i < arr.length; i++) { + current.next = new ListNode(arr[i]); + current = current.next; + } + return head; + } + + /** + * 创建环形链表 + * 应用题目:https://leetcode-cn.com/problems/linked-list-cycle/ + * @param pos 成环位置 + * @param arr 链表元素 + */ + public static ListNode createLoopListNode(int pos, int... arr) { + if (arr == null) { + return null; + } + ListNode head = new ListNode(arr[0]); + ListNode current = head; + // 锚点,记录成环的位置 + ListNode anchor = null; + if (pos == 0) { + anchor = head; + } + for (int i = 1; i < arr.length; i++) { + current.next = new ListNode(arr[i]); + // 记录成环位置 + if (pos == i) { + if (pos == arr.length - 1) { + anchor = current; + } else { + anchor = current.next; + } + } + current = current.next; + } + current.next = anchor; + return head; + } + + /** + * 创建两个相交链表 + * 应用题目:https://leetcode-cn.com/problems/intersection-of-two-linked-lists/ + * @param intersectVal 相交点的值 + * @param listA 链表A元素数组 + * @param listB 链表B元素数组 + * @param skipA 链表A相交前节点数 + * @param skipB 链表B相交前节点数 + */ + public static List createIntersectListNode( + int intersectVal, int[] listA, int[] listB, int skipA, int skipB) { + List listNodes = new ArrayList<>(2); + + ListNode listNodeA = new ListNode(listA[0]); + ListNode currentA = listNodeA; + ListNode listNodeB = new ListNode(listB[0]); + ListNode currentB = listNodeB; + + for (int i = 1; i < skipA; i++) { + currentA.next = new ListNode(listA[i]); + currentA = currentA.next; + } + + for (int i = 1; i < skipB; i++) { + currentB.next = new ListNode(listB[i]); + currentB = currentB.next; + } + + ListNode intersectListNode = new ListNode(listA[skipA]); + ListNode currentIntersect = intersectListNode; + + for (int i = skipA + 1; i < listA.length; i++) { + currentIntersect.next = new ListNode(listA[i]); + currentIntersect = currentIntersect.next; + } + + currentA.next = intersectListNode; + currentB.next = intersectListNode; + + listNodes.add(listNodeA); + listNodes.add(listNodeB); + + return listNodes; + } + + private static ListNode createListNode(String arr) { + if (arr == null) { + return null; + } + ListNode head = new ListNode(arr.charAt(0) - '0'); + ListNode current = head; + + for (int i = 1; i < arr.length(); i++) { + current.next = new ListNode(arr.charAt(i) - '0'); + current = current.next; + } + return head; + } + + /** + * 反序创建链表 + */ + private static ListNode createReverseListNode(String arr) { + if (arr == null) { + return null; + } + + ListNode head = new ListNode(arr.charAt(arr.length() - 1) - '0'); + ListNode current = head; + + for (int i = arr.length() - 2; i >= 0; i--) { + current.next = new ListNode(arr.charAt(i) - '0'); + current = current.next; + } + return head; + } + + /** + * 两个字符串整数相加 + */ + public String add(String a, String b) { + StringBuilder sb = new StringBuilder(); + // 进位 + int carry = 0; + int aIndex = a.length() - 1, bIndex = b.length() - 1; + + while (aIndex >= 0 || bIndex >= 0) { + int x, y, sum; + x = aIndex >= 0 ? a.charAt(aIndex) - '0' : 0; + y = bIndex >= 0 ? b.charAt(bIndex) - '0' : 0; + + sum = carry + x + y; + carry = sum / 10; + sb.append(sum % 10); + + aIndex--; + bIndex--; + } + + if (carry > 0) { + sb.append(carry); + } + return sb.toString(); + } + + /** + * 打印单链表 + */ + public static void printListNode(String msg, ListNode head) { + System.out.println(msg + appendVal(head)); + } + + /** + * 打印单链表 + */ + public static void printListNode(ListNode head) { + System.out.println(appendVal(head)); + } + + private static String appendVal(ListNode head) { + StringBuilder sb = new StringBuilder(); + ListNode current = head; + while (current != null) { + sb.append(current.val); + sb.append("->"); + current = current.next; + } + sb.append("NULL"); + return sb.toString(); + } + + /** + * 反转链表 + */ + public static ListNode reverseListNode(ListNode head) { + ListNode prev = null; + ListNode current = head; + ListNode next = null; + + while (current != null) { + next = current.next; + + current.next = prev; + prev = current; + current = next; + } + return prev; + } + + /** + * 交替合并两个链表,返回新的链表 + */ + public static ListNode alterNoteMerge(ListNode l1, ListNode l2) { + + return null; + } + + /** + * 交替合并两个链表,到第一个链表 + * https://leetcode-cn.com/problems/reorder-list + */ + public static void alterNoteMergeOne(ListNode firstHead, ListNode secondHead) { + ListNode firstNext; + ListNode secondNext; + + while (secondHead != null) { + // 1.记录两个链表的next节点 + firstNext = firstHead.next; + secondNext = secondHead.next; + // 2.将链表1的当前节点指向链表2的当前节点,链表2的当前节点指向链表1的下一个节点 + // 左链表:1->2->3 右链表:5->4 + // 合并后的链表1:1->5->2 + firstHead.next = secondHead; + secondHead.next = firstNext; + // 3.将之前保存的next更新为当前节点,继续循环 + firstHead = firstNext; + secondHead = secondNext; + // 防止奇数节点链表成环 https://leetcode-cn.com/problems/reorder-list/ + if (secondHead == null) { + firstHead.next = null; + } + } + } + + /** + * 找到链表中间的前一个节点 + */ + public static ListNode middleBeforeNode(ListNode head) { + ListNode fast = head; + ListNode slow = head; + while (fast.next != null && fast.next.next != null) { + fast = fast.next.next; + slow = slow.next; + } + return slow; + } + + /** + * 找到链表中间的一个节点 + * https://leetcode-cn.com/problems/middle-of-the-linked-list/ + */ + public static ListNode middleNode(ListNode head) { + ListNode fast = head; + ListNode slow = head; + while (fast != null && fast.next != null) { + fast = fast.next.next; + slow = slow.next; + } + return slow; + } + + public static void main(String[] args) { + //printListNode(createListNode(1, 2, 3, 4, 5, 6, 7)); + //ListNode headLoop = createLoopListNode(0, 4, 5, 6); + //ListNode centerLoop = createLoopListNode(1, 4, 5, 6); + + int intersectVal = 8, skipA = 2, skipB = 3; + int[] listA = {4, 1, 8, 4, 5}; + int[] listB = {5, 0, 1, 8, 4, 5}; + List intersectListNode = createIntersectListNode(intersectVal, listA, listB, skipA, skipB); + for (ListNode listNode : intersectListNode) { + printListNode(listNode); + } + + } +} diff --git a/algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/ListNode.java b/algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/ListNode.java new file mode 100644 index 00000000..4d78a4b2 --- /dev/null +++ b/algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/ListNode.java @@ -0,0 +1,11 @@ +package cn.lastwhisper.leetcode.common.linkedlist; + +public class ListNode { + public int val; + public ListNode next; + + public ListNode(int x) { + val = x; + } + +} \ No newline at end of file diff --git a/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/print/PrintUtils.java b/algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/print/PrintUtils.java similarity index 100% rename from algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/print/PrintUtils.java rename to algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/print/PrintUtils.java diff --git a/algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/tree/TreeNode.java b/algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/tree/TreeNode.java new file mode 100644 index 00000000..273e04b9 --- /dev/null +++ b/algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/tree/TreeNode.java @@ -0,0 +1,11 @@ +package cn.lastwhisper.leetcode.common.tree; + +public class TreeNode { + public int val; + public TreeNode left; + public TreeNode right; + + public TreeNode(int x) { + val = x; + } +} \ No newline at end of file diff --git a/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/tree/TreeUtils.java b/algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/tree/TreeUtils.java similarity index 99% rename from algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/tree/TreeUtils.java rename to algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/tree/TreeUtils.java index 678afc66..89ec67f7 100644 --- a/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/tree/TreeUtils.java +++ b/algorithms/algorithm-common/src/main/java/cn/lastwhisper/leetcode/common/tree/TreeUtils.java @@ -6,6 +6,7 @@ import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; + /** * 树相关工具类 * @author lastwhisper diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/graph/Graph.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/graph/Graph.java similarity index 99% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/graph/Graph.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/graph/Graph.java index 5f891f31..4f69cc9f 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/graph/Graph.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/graph/Graph.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.graph; +package cn.lastwhisper.atguigu.graph; import java.util.ArrayList; import java.util.Arrays; diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/hashtab/HashTabDemo.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/hashtab/HashTabDemo.java similarity index 99% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/hashtab/HashTabDemo.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/hashtab/HashTabDemo.java index 5e0f9384..8eb6eee7 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/hashtab/HashTabDemo.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/hashtab/HashTabDemo.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.hashtab; +package cn.lastwhisper.atguigu.hashtab; /** * diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/DoubleLinkedListDemo.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/DoubleLinkedListDemo.java similarity index 99% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/DoubleLinkedListDemo.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/DoubleLinkedListDemo.java index 8fed1d04..8d725b43 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/DoubleLinkedListDemo.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/DoubleLinkedListDemo.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.linkedlist; +package cn.lastwhisper.atguigu.linkedlist; /** * 双向链表 diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/Josepfu.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/Josepfu.java similarity index 98% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/Josepfu.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/Josepfu.java index f8c35b1c..05df13fc 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/Josepfu.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/Josepfu.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.linkedlist; +package cn.lastwhisper.atguigu.linkedlist; /** * 约瑟夫环 diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/SingleLinkedListDemo.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/SingleLinkedListDemo.java similarity index 99% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/SingleLinkedListDemo.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/SingleLinkedListDemo.java index 527e215a..6f915a4d 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/SingleLinkedListDemo.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/SingleLinkedListDemo.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.linkedlist; +package cn.lastwhisper.atguigu.linkedlist; import org.junit.Test; diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/skiplist/v1/SkipSet.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/skiplist/v1/SkipSet.java similarity index 98% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/skiplist/v1/SkipSet.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/skiplist/v1/SkipSet.java index 72f9f2e1..014114ee 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/skiplist/v1/SkipSet.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/skiplist/v1/SkipSet.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.linkedlist.skiplist.v1; +package cn.lastwhisper.atguigu.linkedlist.skiplist.v1; /** * https://www.iteye.com/blog/imtinx-1291165 diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/skiplist/v2/SkipList.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/skiplist/v2/SkipList.java similarity index 98% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/skiplist/v2/SkipList.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/skiplist/v2/SkipList.java index 5796292e..999ca80a 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/skiplist/v2/SkipList.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/skiplist/v2/SkipList.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.linkedlist.skiplist.v2; +package cn.lastwhisper.atguigu.linkedlist.skiplist.v2; /** * 跳表的一种实现方法。 diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/skiplist/v3/SkipList2.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/skiplist/v3/SkipList2.java similarity index 99% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/skiplist/v3/SkipList2.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/skiplist/v3/SkipList2.java index 7c5fe429..acc518bb 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/linkedlist/skiplist/v3/SkipList2.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/linkedlist/skiplist/v3/SkipList2.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.linkedlist.skiplist.v3; +package cn.lastwhisper.atguigu.linkedlist.skiplist.v3; import java.util.Random; diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/queue/ArrayQueueDemo.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/queue/ArrayQueueDemo.java similarity index 98% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/queue/ArrayQueueDemo.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/queue/ArrayQueueDemo.java index f7566525..5e924141 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/queue/ArrayQueueDemo.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/queue/ArrayQueueDemo.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.queue; +package cn.lastwhisper.atguigu.queue; /** * 数组实现队列 diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/queue/CircleArrayQueueDemo.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/queue/CircleArrayQueueDemo.java similarity index 98% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/queue/CircleArrayQueueDemo.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/queue/CircleArrayQueueDemo.java index 9952aef2..bd6aa057 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/queue/CircleArrayQueueDemo.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/queue/CircleArrayQueueDemo.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.queue; +package cn.lastwhisper.atguigu.queue; /** * 数组实现循环队列 diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/recursion/Maze.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/recursion/Maze.java similarity index 98% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/recursion/Maze.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/recursion/Maze.java index 0c1b4658..e496578b 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/recursion/Maze.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/recursion/Maze.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.recursion; +package cn.lastwhisper.atguigu.recursion; /** * 递归解决迷宫问题 diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/recursion/Queue8.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/recursion/Queue8.java similarity index 98% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/recursion/Queue8.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/recursion/Queue8.java index 122ad0e7..cec867c9 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/recursion/Queue8.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/recursion/Queue8.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.recursion; +package cn.lastwhisper.atguigu.recursion; /** * 递归解决八皇后问题 diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/recursion/Recursion.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/recursion/Recursion.java similarity index 96% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/recursion/Recursion.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/recursion/Recursion.java index 5c4d88bf..3d253071 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/recursion/Recursion.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/recursion/Recursion.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.recursion; +package cn.lastwhisper.atguigu.recursion; /** * 递归通俗解释: diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/search/BinarySearch.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/search/BinarySearch.java similarity index 99% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/search/BinarySearch.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/search/BinarySearch.java index c7b9cce2..c180a504 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/search/BinarySearch.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/search/BinarySearch.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.search; +package cn.lastwhisper.atguigu.search; import cn.lastwhisper.util.ArrayUtil; diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/search/FibonacciSearch.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/search/FibonacciSearch.java similarity index 95% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/search/FibonacciSearch.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/search/FibonacciSearch.java index c244ed44..c9dcfd56 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/search/FibonacciSearch.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/search/FibonacciSearch.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.search; +package cn.lastwhisper.atguigu.search; import cn.lastwhisper.util.ArrayUtil; diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/search/InsertValueSearch.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/search/InsertValueSearch.java similarity index 96% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/search/InsertValueSearch.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/search/InsertValueSearch.java index 818590c7..904e621f 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/search/InsertValueSearch.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/search/InsertValueSearch.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.search; +package cn.lastwhisper.atguigu.search; import cn.lastwhisper.util.ArrayUtil; diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/search/SeqSearch.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/search/SeqSearch.java similarity index 93% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/search/SeqSearch.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/search/SeqSearch.java index b074960e..31f1993c 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/search/SeqSearch.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/search/SeqSearch.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.search; +package cn.lastwhisper.atguigu.search; /** * @author cn.lastwhisper diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/DubbleSort.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/DubbleSort.java similarity index 97% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/DubbleSort.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/DubbleSort.java index 9e491615..fdfc3682 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/DubbleSort.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/DubbleSort.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.sort; +package cn.lastwhisper.atguigu.sort; import cn.lastwhisper.util.ArrayUtil; diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/HeapSort.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/HeapSort.java new file mode 100644 index 00000000..c591191a --- /dev/null +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/HeapSort.java @@ -0,0 +1,71 @@ +package cn.lastwhisper.atguigu.sort; + +import java.util.Arrays; + +/** + * 堆排序 + * + * @author cn.lastwhisper + */ +public class HeapSort { + public static void main(String[] args) { + //int[] arr = {4, 6, 8, 5, 9, 58, -10}; + int[] arr = {4, 6, 8, 5, 9}; + heapSort(arr); + System.out.println("数组:" + Arrays.toString(arr)); + } + + public static void heapSort(int[] arr) { + + //adjustHeap(arr, 1, arr.length); + //System.out.println("第1次" + Arrays.toString(arr)); // 4,9,8,5,6 + + //adjustHeap(arr, 0, arr.length); + //System.out.println("第2次" + Arrays.toString(arr)); // 9,6,8,5,4 + // 1. 满二叉树从右向左、从下往上构建大顶堆;完全二叉树从左向右、从下往上构建大顶堆; + // i--意味着,从下到上,每一次都是[i,arr.length]的数组(二叉树)进行重构大顶堆 + // [0,arr.length]重构了数组(二叉树)头部几个元素的大顶堆,同时也会重构下面的二叉树 + for (int i = arr.length / 2 - 1; i >= 0; i--) { + adjustHeap(arr, i, arr.length); + } + // 2. 交换堆顶元素与末尾元素,调整堆结构 + for (int j = arr.length - 1; j >= 0; j--) { + // 交换 + int temp = arr[j]; + arr[j] = arr[0]; + arr[0] = temp; + adjustHeap(arr, 0, j); + } + } + + + /** + * 将一个数组(二叉树), 调整成一个大顶堆 + * 功能: 将以i对应的非叶子节点的树调整成大顶堆 + * 举例 int arr[] = {4, 6, 8, 5, 9}; => i = 1 => adjustHeap => 得到 {4, 9, 8, 5, 6} + * 如果我们再次调用 adjustHeap 传入的是 i = 0 => {4, 9, 8, 5, 6} => {9, 6, 8, 5, 4} + * @param arr 待调整的数组 + * @param i 表示非叶子节点在数组中索引 + * @param length 表示对多少个元素继续调整, length 是在逐渐的减少 + */ + public static void adjustHeap(int[] arr, int i, int length) { + // 当前i节点 + int temp = arr[i]; + // k是i节点的左子节点,k + 1是右子节点 + for (int k = 2 * i + 1; k < length; k = 2 * k + 1) { + // arr[k] < arr[k + 1]左节点小于右节点 + if (k + 1 < length && arr[k] < arr[k + 1]) { + // k指向数值最大的节点 + k++; + } + if (arr[k] > temp) {//子节点大于父节点 + arr[i] = arr[k];//将子节点赋值到父节点 + i = k;//记录子节点的下标,为了最后 arr[i] = temp; + } else { + break; + } + } + //i = k; arr[i]此时已经是子节点的位置了,前面父节点已经拿到了子节点的值了,这里要将子节点的值赋为父节点的值 + arr[i] = temp; + } +} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/InsertSort.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/InsertSort.java new file mode 100644 index 00000000..24d2e60a --- /dev/null +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/InsertSort.java @@ -0,0 +1,108 @@ +package cn.lastwhisper.atguigu.sort; + +import cn.lastwhisper.util.ArrayUtil; + +import java.util.Arrays; + +/** + * @author cn.lastwhisper + */ +public class InsertSort { + public static void main(String[] args) { + //int[] arr = {101, 34, 119, 1}; + //insertSort1(arr); // 插入排序算法实现步骤 + + int[] arr = ArrayUtil.generateArrByRandom(100000); + // 计算耗时 + long start = System.currentTimeMillis(); + insertSort(arr); + long end = System.currentTimeMillis(); + System.out.println("耗时:" + (end - start) + " ms"); + + //System.out.println(Arrays.toString(arr)); + } + + /** + * 插入排序O(n^2) + * insertVal < arr[insertIndex降序 + * insertVal > arr[insertIndex升序 + * @param arr + * @return void + */ + public static void insertSort(int[] arr) { + int insertVal; + int insertIndex; + // 有序列表[0];[1...arr.length]无序列表 + for (int i = 1; i < arr.length; i++) { + // insertVal的意义:缓存无序列表的第一个数,这个数也是待插入有序列表的数 + insertVal = arr[i]; + // insertIndex的意义:记录有序列表的最后一个数的下标 + insertIndex = i - 1; + // [insertIndex+1...i-1]后移到[insertIndex+2...i](从前往后移动) + while (insertIndex >= 0 && insertVal < arr[insertIndex]) { + arr[insertIndex + 1] = arr[insertIndex]; + insertIndex--; + } + // insertIndex == i - 1; 说明数组并未后移,无需赋值 + if (insertIndex != i - 1) { + // arr[insertIndex + 1]为待插入位置 + arr[insertIndex + 1] = insertVal; + } + } + } + + /** + * 插入排序的实现步骤 + * + * @param arr + * @return void + */ + public static void insertSort1(int[] arr) { + // 第1轮 + // 有序列表{101},无序列表{34, 119, 1} + // {101, 34, 119, 1} + + // insertVal的意义:缓存无序列表的第一个数,这个数也是待插入有序列表的数 + int insertVal = arr[1]; + // insertIndex的意义:记录有序列表的最后一个数的下标 + int insertIndex = 1 - 1; + // insertIndex >= 0的意义:防止数组越界; + // insertVal < arr[insertIndex]的意义:找到insertVal要插入位置的前一个位置 + // 整个while循环的意义:数组覆盖后移,找到待插入位置的前一个位置 + while (insertIndex >= 0 && insertVal < arr[insertIndex]) { + // 第1轮原数组:{101, 34, 119, 1} + // arr[1]=arr[0] {101, 101, 119, 1} + arr[insertIndex + 1] = arr[insertIndex]; + //继续向前 + insertIndex--; + } + // arr[0]=insertVal {34, 101, 119, 1} + arr[insertIndex + 1] = insertVal; + + System.out.printf("第1轮插入,数组:%s\n", Arrays.toString(arr)); + + // 第2轮 + insertVal = arr[2]; + insertIndex = 2 - 1; + while (insertIndex >= 0 && insertVal < arr[insertIndex]) { + arr[insertIndex + 1] = arr[insertIndex]; + insertIndex--; + } + arr[insertIndex + 1] = insertVal; + System.out.printf("第2轮插入,数组:%s\n", Arrays.toString(arr)); + + // 第3轮 + insertVal = arr[3]; + insertIndex = 3 - 1; + while (insertIndex >= 0 && insertVal < arr[insertIndex]) { + // 第三轮原数组:{34, 101, 119, 1} + // arr[3]=arr[2] {34, 101, 119, 119} + // arr[2]=arr[1] {34, 101, 101, 119} + // arr[1]=arr[0] {34, 34, 101, 119} + arr[insertIndex + 1] = arr[insertIndex]; + insertIndex--; + } + arr[insertIndex + 1] = insertVal; + System.out.printf("第3轮插入,数组:%s\n", Arrays.toString(arr)); + } +} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/MergeSort.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/MergeSort.java new file mode 100644 index 00000000..dfe39e34 --- /dev/null +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/MergeSort.java @@ -0,0 +1,79 @@ +package cn.lastwhisper.atguigu.sort; + +import java.util.Arrays; + +/** + * @author cn.lastwhisper + */ +public class MergeSort { + + public static void main(String[] args) { + int[] arr = {9, 8, 7, 6, 5, 4, 3, 2, 1}; +// int[] arr = ArrayUtil.generateArrByRandom(10000000);// 1443 ms + // 计算耗时 + long start = System.currentTimeMillis(); + mergeSort(arr, 0, arr.length - 1); + long end = System.currentTimeMillis(); + System.out.println("耗时:" + (end - start) + " ms"); + + System.out.println(Arrays.toString(arr)); + } + + /** + * 归并排序 + * 分 + * + * @param arr 排序的原始数组 + * @param left 左边有序序列的初始索引 + * @param right 右边索引 + */ + public static void mergeSort(int[] arr, int left, int right) { + if (left < right) { + int mid = (left + right) / 2; + mergeSort(arr, left, mid); // 向左分 + mergeSort(arr, mid + 1, right); // 向右分 + merge(arr, left, mid, right);// 治 + } + } + + /** + * 治 + * + * @param arr 排序的原始数组 arr[left...mid] arr[mid+1...right] + * @param left 左边有序序列的初始索引 + * @param mid 中间索引 + * @param right 右边索引 + */ + public static void merge(int[] arr, int left, int mid, int right) { + //开辟额外大集合,设置指针 + int[] temp = new int[right - left + 1]; + + int i = left; //左边有序序列的初始索引 + int j = mid + 1; // 右边有序序列的初始化序索引 + int tempIdx = 0; // 指向temp数组的当前位置 + + // 1)、将左右两边(有序)的数据按照规则填充到temp数组,任意一边处理完毕为止 + while (i <= mid && j <= right) { + if (arr[i] < arr[j]) { + // 左小于右,将左数组第i个元素copy到temp数组的第t个位置 + temp[tempIdx++] = arr[i++]; + } else { + // 右小于或等于左,将右数组第j个元素copy到temp数组的第t个位置 + temp[tempIdx++] = arr[j++]; + } + } + + // 2)、把有剩余数据的一边的数据依次填充到temp + while (i <= mid) {// 说明 右数组还有剩余元素 + temp[tempIdx++] = arr[i++]; + } + while (j <= right) {// 说明 右数组还有剩余元素 + temp[tempIdx++] = arr[j++]; + } + + // 3)、将temp数组的数据copy到arr,注意从本次数组起始位置left,开始复制 + for (int k = left; k < temp.length; k++) { + arr[k] = temp[k]; + } + } +} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/QuickSort.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/QuickSort.java new file mode 100644 index 00000000..45d903c9 --- /dev/null +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/QuickSort.java @@ -0,0 +1,125 @@ +package cn.lastwhisper.atguigu.sort; + +import java.util.Arrays; + +/** + * @author cn.lastwhisper + */ +@Deprecated +public class QuickSort { + + public static void main(String[] args) { + //int[] arr = {-9, 78, 0, 23, -567, 70}; + //int[] arr = {-9, 78, 0, 23, 60, 70}; + //int[] arr = {9, 0, -567}; + int[] arr = {49, 38, 65, 97, 76, 13, 27}; + + //int[] arr = ArrayUtil.generateArrByRandom(10000000);//耗时:1519 ms + // 计算耗时 + long start = System.currentTimeMillis(); + //quickSort(arr, 0, arr.length - 1); + qSort(arr, 0, arr.length - 1); + long end = System.currentTimeMillis(); + System.out.println("耗时:" + (end - start) + " ms"); + + System.out.println(Arrays.toString(arr)); + } + + public static void qSort(int[] arr, int head, int tail) { + if (head >= tail || arr == null || arr.length <= 1) { + return; + } + //定义俩指针 用于移动 + int left = head; + int right = tail; + int pivot = arr[head]; //基准值,也可以arr[(head + tail) / 2] + + while (left <= right) { + while (arr[left] < pivot) { //左指针先走,找到大于等于基准数的停止 + ++left; + } + while (arr[right] > pivot) { //右指针后走,找到小于等于基准数的停止 + --right; + } + if (left < right) { + //交换arr[left]和arr[right]的位置 + int t = arr[left]; + arr[left] = arr[right]; + arr[right] = t; + //继续遍历 + ++left; + --right; + } else if (left == right) { + //遍历完,错开两指针,用于退出循环 + ++left; + //break; + } + } + + qSort(arr, head, right); + qSort(arr, left, tail); + } + + + /** + * 快速排序,选取数组中间的值 + * int pivot = arr[(left + right) / 2]; + * + * @param arr + * @param left + * @param right + * @return void + */ + public static void quickSort1(int[] arr, int left, int right) { + int l = left; // 左下标 + int r = right; // 右下标 + int temp; + // 中轴 + int pivot = arr[(left + right) / 2]; + // while循环的目的:小于或等于pivot的放左边,大于或等于pivot的放右边 + while (l < r) { + // 在pivot左边找比pivot大的值的下标l + while (arr[l] < pivot) { //找到arr[1]=98 >pivot=0 + l++; + } + // 在pivot右边找比pivot小的值的下标r + while (arr[r] > pivot) { //找到arr[4]=-567 < pivot=0 + r--; + } + // 如果l>=r说明pivot左右两边的值,已经满足: + // 小于或等于pivot的放左边,大于或等于pivot的放右边 ——递归结束条件 + if (l >= r) { + break; + } + // 交换 + temp = arr[l]; + arr[l] = arr[r]; + arr[r] = temp; + // 如果交换完后,发现arr[l] == pivot,r--,前移 退出循环 + if (arr[l] == pivot) { + r--; + } + + // 如果交换完后,发现arr[r] == pivot,l++,后移 退出循环 + if (arr[r] == pivot) { + l++; + } + } + + // 第二步 + + // 如果l==r,必须l++,r--,否则会栈溢出 + if (l == r) { + l = l + 1; + r = r - 1; + } + // 向左递归 + if (left < r) { + quickSort1(arr, left, r); + } + // 向右递归 + if (right > l) { + quickSort1(arr, l, right); + } + } +} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/QuickSort2.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/QuickSort2.java new file mode 100644 index 00000000..0c4a1124 --- /dev/null +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/QuickSort2.java @@ -0,0 +1,58 @@ +package cn.lastwhisper.atguigu.sort; + +/** + * @author lastwhisper + */ +public class QuickSort2 { + public static void main(String[] args) { +// int[] arr = {7, 3, 2, 8, 1, 9, 5, 4, 6}; + //int arr[] = {7, 3, 2, 8, 1, 9, 5, 4, 6, 0};//为什么left++和right--条件里面要加 left <= right 限定 + //int arr[] = {7, 3, 2, 8, 1, 9, 5, 4, 6, 10}; +// int arr[] = {7, 3, 2, 6, 8, 1, 9, 5, 4, 6, 10, 6, 6}; // 为什么不取等 arr[right] > pivot +// int[] arr = {4, 6}; //小bug测试 // 为什么while (left <= right)里面要取等 + +// int[] arr = {2, 10, 8, 22, 34, 5, 12, 28, 21, 11}; + int[] arr = {49, 38, 65, 97, 76, 13, 27}; +// int[] arr = {2, 10, 8, 1000}; + sort(arr, 0, arr.length - 1); + print(arr); + } + + private static void sort(int[] arr, int left, int right) { + if (left >= right) return; + int mid = partition(arr, left, right); + sort(arr, left, mid - 1); + sort(arr, mid + 1, right); + } + + /** + * @param arr 待分区数组 + * @param left 左边界 + * @param right 右边界 + */ + private static int partition(int[] arr, int left, int right) { + int pivot = arr[right]; + int start = left, end = right - 1; + // + while (start <= end) { + while (start <= end && arr[start] <= pivot) start++; + while (start <= end && arr[end] > pivot) end--; + if (start < end) swap(arr, start, end); + } + // 此时的start一定>=pivot(right),所以需要交互 + swap(arr, start, right); + return start; + } + + private static void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + + private static void print(int[] arr) { + for (int value : arr) { + System.out.print(value + "\t"); + } + } +} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/RadixSort.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/RadixSort.java new file mode 100644 index 00000000..b55a46a2 --- /dev/null +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/RadixSort.java @@ -0,0 +1,152 @@ +package cn.lastwhisper.atguigu.sort; + +import cn.lastwhisper.util.ArrayUtil; + +import java.util.Arrays; + +/** + * @author cn.lastwhisper + */ +public class RadixSort { + + public static void main(String[] args) { + // 算法实现步骤 + //int[] arr = {53, 3, 542, 748, 14, 214}; + //int[] arr = {3, 205, 14}; + //radixSortStudy(arr); + + // 计算耗时 + // 占用内存 10000000 * 10 * 4 /1024 / 1024 /1024 = 0.3725290298461914‬ + int[] arr = ArrayUtil.generateArrByRandom(10000000); + long start = System.currentTimeMillis(); + radixSort(arr); + long end = System.currentTimeMillis(); + System.out.println("耗时:" + (end - start) + " ms"); + + //System.out.println(Arrays.toString(arr)); + } + + /** + * 基数排序,桶排序的扩展 + * + * @param arr + * @return void + */ + public static void radixSort(int[] arr) { + + int[][] bucket = new int[10][arr.length]; + // 桶元素计数器,记录每个桶中存放了多少数据 + int[] bucketElementCount = new int[10]; + // 原arr下标 + int arrIndex; + // 除数 + int divisor = 1; + // 最大值 + int max = arr[0]; + // 由于基数排序次数由最大数值的位数决定,所以需要求最大值 + for (int i = 1; i < arr.length; i++) { + if (max < arr[i]) { + max = arr[i]; + } + } + // 最大值得位数,即排序次数 + int maxLength = (max + "").length(); + for (int f = 0; f < maxLength; f++) { + for (int i = 0; i < arr.length; i++) { + // digitOfElement对应放在哪个bucket中 + int digitOfElement = arr[i] / divisor % 10; + // 放在第digitOfElement个bucket的第bucketElementCount[digitOfElement]下标位置 + bucket[digitOfElement][bucketElementCount[digitOfElement]] = arr[i]; + // 下次放在bucket的第bucketElementCount[digitOfElement]++下标位置 + bucketElementCount[digitOfElement]++; + } + + arrIndex = 0; + // 将桶中数据放回原数组 + for (int i = 0; i < bucketElementCount.length; i++) { + // 对应桶中有数据 + if (bucketElementCount[i] != 0) { + for (int j = 0; j < bucketElementCount[i]; j++) { + arr[arrIndex++] = bucket[i][j]; + } + } + // 将桶元素计数器清空 + bucketElementCount[i] = 0; + } + divisor *= 10; + } + + } + + /** + * 桶排序算法实现步骤 + * + * @param arr + */ + public static void radixSortStudy(int[] arr) { + // + int[][] bucket = new int[10][arr.length]; + // 桶元素计数器,记录每个桶中存放了多少数据 + int[] bucketElementCount = new int[10]; + // 原arr下标 + int arrIndex; + + for (int i = 0; i < arr.length; i++) { + // digitOfElement对应放在哪个bucket中 + int digitOfElement = arr[i] % 10; + // 放在第digitOfElement个bucket的第bucketElementCount[digitOfElement]下标位置 + bucket[digitOfElement][bucketElementCount[digitOfElement]] = arr[i]; + // 下次放在bucket的第bucketElementCount[digitOfElement]++下标位置 + bucketElementCount[digitOfElement]++; + } + + arrIndex = 0; + // 将桶中数据放回原数组 + for (int i = 0; i < bucketElementCount.length; i++) { + // 对应桶中有数据 + if (bucketElementCount[i] != 0) { + for (int j = 0; j < bucketElementCount[i]; j++) { + arr[arrIndex++] = bucket[i][j]; + } + } + // 将桶元素计数器清空 + bucketElementCount[i] = 0; + } + + System.out.println("第1轮,对个位的排序处理 arr =" + Arrays.toString(arr)); + + for (int i = 0; i < arr.length; i++) { + // digitOfElement对应放在哪个bucket中 + int digitOfElement = arr[i] / 10 % 10; + // 放在第digitOfElement个bucket的第bucketElementCount[digitOfElement]下标位置 + bucket[digitOfElement][bucketElementCount[digitOfElement]] = arr[i]; + // 下次放在bucket的第bucketElementCount[digitOfElement]++下标位置 + bucketElementCount[digitOfElement]++; + } + + arrIndex = 0; + // 将桶中数据放回原数组 + for (int i = 0; i < bucketElementCount.length; i++) { + // 对应桶中有数据 + if (bucketElementCount[i] != 0) { + for (int j = 0; j < bucketElementCount[i]; j++) { + arr[arrIndex++] = bucket[i][j]; + } + } + // 将桶元素计数器清空 + bucketElementCount[i] = 0; + } + + System.out.println("第2轮,对个位的排序处理 arr =" + Arrays.toString(arr)); + + //for (int i = 0; i < bucket.length; i++) { + // for (int j = 0; j < bucket[0].length; j++) { + // System.out.printf("%d\t", bucket[i][j]); + // } + // System.out.println(); + //} + + } + + +} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/SelectSort.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/SelectSort.java new file mode 100644 index 00000000..14f8afb9 --- /dev/null +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/SelectSort.java @@ -0,0 +1,82 @@ +package cn.lastwhisper.atguigu.sort; + +import cn.lastwhisper.util.ArrayUtil; + +import java.util.Arrays; + +/** + * @author cn.lastwhisper + */ +public class SelectSort { + + public static void main(String[] args) { + //int[] arr = {101, 34, 119, 1}; + //selectSort1(arr); + //System.out.println(Arrays.toString(arr)); + + int[] arr = ArrayUtil.generateArrByRandom(100000); + // 计算耗时 + long start = System.currentTimeMillis(); + selectSort(arr); + long end = System.currentTimeMillis(); + System.out.println("耗时:" + (end - start) + " ms"); + } + + /** + * 选择排序O(n^2) + * + * @param arr + * @return void + */ + public static void selectSort(int[] arr) { + for (int i = 0; i < arr.length; i++) { + int min = arr[i]; + int minIndex = i; + // 找出[1+i...arr.length]范围内的最小值,和最小值索引 + for (int j = i + 1; j < arr.length; j++) { + if (min > arr[j]) { + min = arr[j]; + minIndex = j; + } + } + // 交换最小值与第i个数的位置 + if (minIndex != i) { + arr[minIndex] = arr[i]; + arr[i] = min; + } + } + } + + /** + * 算法的实现步骤 + * + * @param arr + * @return void + */ + public static void selectSort1(int[] arr) { + // 第1轮 {101, 34, 119, 1} + + // 1、找最小值 + // 最小值 + int min = arr[0]; + // 最小值索引 + int minIndex = 0; + // {101, 34, 119, 1} 我们假设待排序数组第一个元素就是最小值,即min=arr[0],minIndex=0 + // 经过遍历后我们发现 min=1,minIndex=3 + for (int j = 0 + 1; j < arr.length; j++) { + // 找最小的数 + if (min > arr[j]) { + min = arr[j]; + minIndex = j; + } + } + // 2、交换。minIndex是最小值所在位置,min是最小值 + if (minIndex != 0) { + arr[minIndex] = arr[0]; + arr[0] = min; + } + + System.out.printf("第1轮选择,数组:%s", Arrays.toString(arr)); + } + +} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/ShellSort.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/ShellSort.java new file mode 100644 index 00000000..edd5254a --- /dev/null +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/ShellSort.java @@ -0,0 +1,132 @@ +package cn.lastwhisper.atguigu.sort; + +import java.util.Arrays; + +/** + * @author cn.lastwhisper + */ +public class ShellSort { + public static void main(String[] args) { + int[] arr = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0}; + //int[] arr = ArrayUtil.generateArrByRandom(100000); + // 计算耗时 + long start = System.currentTimeMillis(); + //shellSort1(arr); // 10490 ms + shellSort2(arr); // 10490 ms + long end = System.currentTimeMillis(); + System.out.println("耗时:" + (end - start) + " ms"); + + System.out.printf("希尔排序(交换法),数组:%s\n", Arrays.toString(arr)); + } + + + /** + * 希尔排序(位移法)(插入排序) + * + * @param arr + * @return void + */ + public static void shellSort2(int[] arr) { + // {8, 9, 1, 7, 2, 3, 5, 4, 6, 0} + int gap = arr.length / 2; + int j; + int temp; + while (gap > 0) { + //gap=5,2,1,0 + // i=5——》{0,5} + // i=6——》{1,6} + // i=7——》{2,7} + // i=8——》{3,8} + // i=9——》{4,9} + // 对每个数组进行插入排序;由于每个数组并不是真的存在的数组,而是一个大数组 + // 所以通过gap进行取值 + for (int i = gap; i < arr.length; i++) { + j = i; // 缓存每个数组的起始下标 + temp = arr[i]; // 缓存每个数组的起始下标的数值 + if (temp < arr[j - gap]) { + while (j - gap >= 0 && temp < arr[j - gap]) { + // 从前往后移动 + arr[j] = arr[j - gap]; + j = j - gap; + } + // + arr[j] = temp; + } + } + gap = gap / 2; + } + } + + /** + * 希尔排序(交换法) + * + * @param arr + * @return void + */ + public static void shellSort1(int[] arr) { + // 第1轮 {8, 9, 1, 7, 2, 3, 5, 4, 6, 0} + // 增量 gap=length/2 + int gap = arr.length / 2; + int temp; + while (gap > 0) { + for (int i = gap; i < arr.length; i++) { + // 交换 + for (int j = i - gap; j >= 0; j -= gap) { + if (arr[j] > arr[j + gap]) { + temp = arr[j + gap]; + arr[j + gap] = arr[j]; + arr[j] = temp; + } + } + } + gap = gap / 2; + } + } + + /** + * 交换法希尔排序 + * + * @param arr + * @return void + */ + public static void shellSortStudy(int[] arr) { + // 第1轮 [8, 9, 1, 7, 2, 3, 5, 4, 6, 0] + // 增量 gap=length/2 + int temp; + for (int i = 5; i < arr.length; i++) { + // 交换 + for (int j = i - 5; j >= 0; j -= 5) { + if (arr[j] > arr[j + 5]) { + temp = arr[j + 5]; + arr[j + 5] = arr[j]; + arr[j] = temp; + } + } + } + System.out.printf("第1轮插入,数组:%s\n", Arrays.toString(arr)); + // 第二轮 [3, 5, 1, 6, 0, 8, 9, 4, 7, 2] + for (int i = 2; i < arr.length; i++) { + // 交换 + for (int j = i - 2; j >= 0; j -= 2) { + if (arr[j] > arr[j + 2]) { + temp = arr[j + 2]; + arr[j + 2] = arr[j]; + arr[j] = temp; + } + } + } + System.out.printf("第2轮插入,数组:%s\n", Arrays.toString(arr)); + // 第三轮 [0, 2, 1, 4, 3, 5, 7, 6, 9, 8] + for (int i = 1; i < arr.length; i++) { + // 交换 + for (int j = i - 1; j >= 0; j -= 1) { + if (arr[j] > arr[j + 1]) { + temp = arr[j + 1]; + arr[j + 1] = arr[j]; + arr[j] = temp; + } + } + } + System.out.printf("第3轮插入,数组:%s\n", Arrays.toString(arr)); + } +} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/TimeComplexity.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/TimeComplexity.java similarity index 95% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/TimeComplexity.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/TimeComplexity.java index c6fe47df..36734634 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/TimeComplexity.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/TimeComplexity.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.sort; +package cn.lastwhisper.atguigu.sort; /** * 时间复杂度举例 diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/heap/Heap.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/heap/Heap.java new file mode 100644 index 00000000..5e3cb8e0 --- /dev/null +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/heap/Heap.java @@ -0,0 +1,100 @@ +package cn.lastwhisper.atguigu.sort.heap; + +import java.util.Arrays; + +public class Heap { + private int[] a; // 数组,从下标 1 开始存储数据 + private int n; // 堆可以存储的最大数据个数 + private int count; // 堆中已经存储的数据个数 + + public Heap(int capacity) { + a = new int[capacity + 1]; + n = capacity; + count = 0; + } + + /** + * 插入 + */ + public void insert(int data) { + if (count >= n) return; // 堆满了 + ++count; + a[count] = data; + int i = count; + while (i / 2 > 0 && a[i] > a[i / 2]) { // 自下往上堆化 + swap(a, i, i / 2); // swap() 函数作用:交换下标为 i 和 i/2 的两个元素 + i = i / 2; + } + } + + /** + * 删除堆顶 + */ + public void removeMax() { + if (count == 0) return; // 堆中没有数据 + a[1] = a[count]; + --count; + heapify(a, count, 1); + } + + /** + * 堆化大顶堆 + * 自上往下堆化 + * + * @param arr 数组 + * @param n 堆中元素个数 + * @param i 待堆化的元素 + */ + private static void heapify(int[] arr, int n, int i) { + while (true) { + // 待堆化元素、左、右子树最大值的下标 + int maxPos = i; + // 待堆化元素小于左子树 + if (i * 2 <= n && arr[i] < arr[i * 2]) { + maxPos = i * 2; + } + // 待堆化元素左子树小于右子树, + if (i * 2 + 1 <= n && arr[maxPos] < arr[i * 2 + 1]) { + maxPos = i * 2 + 1; + } + // 最大元素是自己无需向下堆化 + if (maxPos == i) break; + // 最大元素不是自己,交互值 + swap(arr, i, maxPos); + // 将被交互的元素继续向下堆化 + i = maxPos; + } + } + + private static void buildHeap(int[] a, int n) { + // 对非叶子节点进行,自上往下堆化 + for (int i = n / 2; i >= 1; --i) { + heapify(a, n, i); + } + } + + // n 表示数据的个数,数组 a 中的数据从下标 1 到 n 的位置。 + public static void sort(int[] a, int n) { + buildHeap(a, n); + int k = n; + while (k > 1) { + swap(a, 1, k); + --k; + heapify(a, k, 1); + } + } + + private static void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + + public static void main(String[] args) { + int[] arr = new int[]{-99999, 9, 8, 7, 6, 5, 4, 3, 2, 1}; + System.out.println(Arrays.toString(arr)); + Heap.sort(arr, arr.length - 1); + System.out.println(Arrays.toString(arr)); + } + +} \ No newline at end of file diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/heap/Heap2.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/heap/Heap2.java new file mode 100644 index 00000000..2340e830 --- /dev/null +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/heap/Heap2.java @@ -0,0 +1,69 @@ +package cn.lastwhisper.atguigu.sort.heap; + +import java.util.Arrays; + +public class Heap2 { + + + /** + * 堆化大顶堆 + * 自上往下堆化 + * + * @param arr 数组 + * @param n 堆中元素个数 + * @param i 待堆化的元素 + */ + private static void heapify(int[] arr, int n, int i) { + while (true) { + // 待堆化元素、左、右子树最大值的下标 + int maxPos = i; + // 待堆化元素小于左子树 + if (i * 2 + 1 <= n && arr[i] < arr[i * 2 + 1]) { + maxPos = i * 2 + 1; + } + // 待堆化元素左子树小于右子树, + if (i * 2 + 2 <= n && arr[maxPos] < arr[i * 2 + 2]) { + maxPos = i * 2 + 2; + } + // 最大元素是自己无需向下堆化 + if (maxPos == i) break; + // 最大元素不是自己,交互值 + swap(arr, i, maxPos); + // 将被交互的元素继续向下堆化 + i = maxPos; + } + } + + private static void buildHeap(int[] a, int n) { + // 对非叶子节点进行,自上往下堆化 + for (int i = n / 2 - 1; i >= 0; --i) { + heapify(a, n, i); + } + } + + public static void sort(int[] arr, int n) { + // 1. 构建大顶堆 + buildHeap(arr, n); + int disorder = n; + // 2. 交换堆顶元素与末尾元素,调整堆结构 + while (disorder > 0) { + swap(arr, 0, disorder); + disorder--; + heapify(arr, disorder, 0); + } + } + + private static void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + + public static void main(String[] args) { + int[] arr = new int[]{9, 10, 7, 6, 5, 4, 3, 2, 1}; + System.out.println(Arrays.toString(arr)); + Heap2.sort(arr, arr.length - 1); + System.out.println(Arrays.toString(arr)); + } + +} \ No newline at end of file diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/heap/HeapOperator.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/heap/HeapOperator.java new file mode 100644 index 00000000..91466e9d --- /dev/null +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sort/heap/HeapOperator.java @@ -0,0 +1,87 @@ +package cn.lastwhisper.atguigu.sort.heap; + +import java.util.Arrays; + +/** + * 对于二叉堆,如下有几种操作: + * 插入节点 + * 删除节点 + * 构建二叉堆 + * + * @author cunchang + * @date 2022/6/12 11:34 PM + */ +public class HeapOperator { + + + /** + * 上浮调整 + * @param array 待调整的堆 + */ + public static void upAdjust(int[] array) { + int childIndex = array.length - 1; + // child = 2*parent+1,则 parent = (child - 1) / 2 + int parentIndex = (childIndex - 1) / 2; + // temp保存插入的叶子节点值,用于最后的赋值 + int temp = array[childIndex]; + while (childIndex > 0 && temp < array[parentIndex]) { + //无需真正交换,单向赋值即可 + array[childIndex] = array[parentIndex]; + childIndex = parentIndex; + parentIndex = (parentIndex - 1) / 2; + } + array[childIndex] = temp; + } + + + /** + * 下沉调整 + * @param array 待调整的堆 + * @param parentIndex 要下沉的父节点 + * @param length 堆的有效大小 + */ + public static void downAdjust(int[] array, int parentIndex, int length) { + // temp保存父节点值,用于最后的赋值 + int temp = array[parentIndex]; + int childIndex = 2 * parentIndex + 1; + while (childIndex < length) { + // 如果有右孩子,且右孩子小于左孩子的值,则定位到右孩子 + if (childIndex + 1 < length && array[childIndex + 1] < array[childIndex]) { + childIndex++; + } + // 如果父节点小于任何一个孩子的值,直接跳出 + if (temp <= array[childIndex]) { + break; + } + //无需真正交换,单向赋值即可 + array[parentIndex] = array[childIndex]; + parentIndex = childIndex; + childIndex = 2 * childIndex + 1; + } + array[parentIndex] = temp; + } + + + /** + * 构建堆 + * + * @param array 待调整的堆 + */ + public static void buildHeap(int[] array) { + // 从最后一个非叶子节点开始,依次下沉调整 + for (int i = array.length / 2; i >= 0; i--) { + downAdjust(array, i, array.length - 1); + } + } + + public static void main(String[] args) { + int[] array = new int[]{1, 3, 2, 6, 5, 7, 8, 9, 10, 0}; + upAdjust(array); + System.out.println(Arrays.toString(array)); + array = new int[]{7, 1, 3, 10, 5, 2, 8, 9, 6}; + buildHeap(array); + System.out.println(Arrays.toString(array)); + } + + +} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sparsematrix/BestSpmatrix.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sparsematrix/BestSpmatrix.java similarity index 97% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sparsematrix/BestSpmatrix.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sparsematrix/BestSpmatrix.java index 81bbdf1f..e1fd05b9 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sparsematrix/BestSpmatrix.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sparsematrix/BestSpmatrix.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.sparsematrix; +package cn.lastwhisper.atguigu.sparsematrix; /** * @author cn.lastwhisper diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sparsematrix/SparseMatrix.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sparsematrix/SparseMatrix.java similarity index 98% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sparsematrix/SparseMatrix.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sparsematrix/SparseMatrix.java index 8d834fcc..50f30722 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sparsematrix/SparseMatrix.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/sparsematrix/SparseMatrix.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.sparsematrix; +package cn.lastwhisper.atguigu.sparsematrix; /** * 稀疏矩阵压缩与还原 diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/stack/ArrayStackDemo.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/stack/ArrayStackDemo.java similarity index 97% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/stack/ArrayStackDemo.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/stack/ArrayStackDemo.java index 83f31360..5a20dc99 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/stack/ArrayStackDemo.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/stack/ArrayStackDemo.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.stack; +package cn.lastwhisper.atguigu.stack; /** * @author cn.lastwhisper diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/stack/InCalculator.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/stack/InCalculator.java similarity index 99% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/stack/InCalculator.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/stack/InCalculator.java index e07541d4..1288660c 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/stack/InCalculator.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/stack/InCalculator.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.stack; +package cn.lastwhisper.atguigu.stack; /** * 中缀表达式 diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/stack/SuCalculator.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/stack/SuCalculator.java similarity index 98% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/stack/SuCalculator.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/stack/SuCalculator.java index 562aa3b0..18d7afa0 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/stack/SuCalculator.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/stack/SuCalculator.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.stack; +package cn.lastwhisper.atguigu.stack; import java.util.ArrayList; import java.util.List; @@ -103,7 +103,7 @@ public static String infixConverSufix(String infixExpression) { * 中缀表达式String转中缀表达式Lsit * * @param infixExpression - * @return java.util.List + * @return java.array.List */ public static List infixStrConvertInfixList(String infixExpression) { List infixList = new ArrayList<>(); diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/ArrBinaryTreeDemo.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/ArrBinaryTreeDemo.java similarity index 87% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/ArrBinaryTreeDemo.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/ArrBinaryTreeDemo.java index 8ffd0de2..59ca8711 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/ArrBinaryTreeDemo.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/ArrBinaryTreeDemo.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.tree; +package cn.lastwhisper.atguigu.tree; import cn.lastwhisper.util.ArrayUtil; @@ -12,12 +12,12 @@ public static void main(String[] args) { ArrBinaryTree arrBinaryTree = new ArrBinaryTree(arr); System.out.println("先序:"); arrBinaryTree.preOrder(0);//1 2 4 5 3 6 7 - System.out.println(); - System.out.println("中序:"); - arrBinaryTree.infixOrder(0); - System.out.println(); - System.out.println("后序:"); - arrBinaryTree.postOrder(0); + //System.out.println(); + //System.out.println("中序:"); + //arrBinaryTree.infixOrder(0); + //System.out.println(); + //System.out.println("后序:"); + //arrBinaryTree.postOrder(0); } } diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/BinaryTreeDemo.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/BinaryTreeDemo.java similarity index 97% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/BinaryTreeDemo.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/BinaryTreeDemo.java index 5f08ac86..50ff9a40 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/BinaryTreeDemo.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/BinaryTreeDemo.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.tree; +package cn.lastwhisper.atguigu.tree; import org.junit.Test; @@ -9,6 +9,7 @@ /** * 二叉树的遍历:先序、中序、后序 * 二叉树的查找:查找指定节点 + * * @author cn.lastwhisper */ public class BinaryTreeDemo { @@ -182,7 +183,7 @@ public HeroNode postOrderSearch(int no) { /** * 先序遍历(递归) - * 先访问根节点,再先序遍历左子树,再先序遍历右子树 + * 先访问根节点,再先序遍历左子树,再先序遍历右子树 * * @param node */ @@ -196,7 +197,8 @@ public void preOrder(HeroNode node) { /** * 中序遍历(递归) - * 先遍历左子树,再访问根节点,再中序遍历右子树 + * 先遍历左子树,再访问根节点,再中序遍历右子树 + * * @param node */ public void infixOrder(HeroNode node) { @@ -209,7 +211,8 @@ public void infixOrder(HeroNode node) { /** * 后序遍历(递归) - * 先遍历左子树,再后序遍历右子树,再访问根节点 + * 先遍历左子树,再后序遍历右子树,再访问根节点 + * * @param node */ public void postOrder(HeroNode node) { diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/ThreadingBinaryTreeDemo.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/ThreadingBinaryTreeDemo.java similarity index 99% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/ThreadingBinaryTreeDemo.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/ThreadingBinaryTreeDemo.java index 540dc9af..b087fc40 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/ThreadingBinaryTreeDemo.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/ThreadingBinaryTreeDemo.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.tree; +package cn.lastwhisper.atguigu.tree; /** * 线索化二叉树 diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/avl/AVLTreeDemo.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/avl/AVLTreeDemo.java similarity index 99% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/avl/AVLTreeDemo.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/avl/AVLTreeDemo.java index c126c41c..f50d1106 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/avl/AVLTreeDemo.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/avl/AVLTreeDemo.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.tree.avl; +package cn.lastwhisper.atguigu.tree.avl; /** * 平衡二叉树 diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/binarysorttree/BinarySortTreeDemo.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/binarysorttree/BinarySortTreeDemo.java similarity index 98% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/binarysorttree/BinarySortTreeDemo.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/binarysorttree/BinarySortTreeDemo.java index 9f91a7ac..d582a014 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/binarysorttree/BinarySortTreeDemo.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/binarysorttree/BinarySortTreeDemo.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.tree.binarysorttree; +package cn.lastwhisper.atguigu.tree.binarysorttree; /** * 二叉排序树 @@ -104,7 +104,6 @@ public int delLeftTreeMax(Node node) { // 根据value删除节点 public void delNode(int value) { if (root == null) { - return; } else { // 待删除节点 Node targetNode = search(value); @@ -217,10 +216,10 @@ public Node search(int value) { if (this.value == value) { return this; } else if (this.value > value && this.left != null) { - // 2.1 当前节点的value大于value,往左边寻找 + // 2.1 当前节点的value大于value,往左边寻找,因为左子树的值都小于当前节点 return this.left.search(value); } else if (this.value < value && this.right != null) { - // 2.2 当前节点的value小于value,往右边寻找 + // 2.2 当前节点的value小于value,往右边寻找,因为右子树的值都大于当前节点 return this.right.search(value); } else { // 3. this.left&&this.right==null,找不到该节点 diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/huffmancode/HuffmanCode.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/huffmancode/HuffmanCode.java similarity index 98% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/huffmancode/HuffmanCode.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/huffmancode/HuffmanCode.java index 2d0c9659..11ba50fc 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/huffmancode/HuffmanCode.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/huffmancode/HuffmanCode.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.tree.huffmancode; +package cn.lastwhisper.atguigu.tree.huffmancode; import java.io.*; import java.util.*; @@ -358,7 +358,7 @@ public static byte[] zip(byte[] bytes, Map huffmanCodes) { * 根据哈夫曼树建立哈弗曼编码表 * * @param root 根节点 - * @return java.util.Map + * @return java.array.Map */ public static Map getCodes(Node root) { if (root == null) { @@ -431,7 +431,7 @@ public static Node createHuffmanTree(List nodes) { /** * 将字符串转换成哈夫曼树节点 * @param zipStr 待压缩字符串 - * @return java.util.List + * @return java.array.List */ public static List getListNode(String zipStr) { byte[] zipStrBytes = zipStr.getBytes(); @@ -441,7 +441,7 @@ public static List getListNode(String zipStr) { /** * 将字符串转换成哈夫曼树节点 * @param zipBytes 待压缩字节数组 - * @return java.util.List + * @return java.array.List */ public static List getListNode(byte[] zipBytes) { // 将字节数组按字节拆分,统计每个字节出现的次数(select count(byte) weight from zipBytes order by byte) diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/huffmantree/HuffmanTree.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/huffmantree/HuffmanTree.java similarity index 97% rename from algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/huffmantree/HuffmanTree.java rename to algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/huffmantree/HuffmanTree.java index a8fda687..4dd1b9a4 100644 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/huffmantree/HuffmanTree.java +++ b/algorithms/datastructure/src/main/java/cn/lastwhisper/atguigu/tree/huffmantree/HuffmanTree.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.datastructure.tree.huffmantree; +package cn.lastwhisper.atguigu.tree.huffmantree; import java.util.Collections; import java.util.LinkedList; diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/common/TreeNode.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/common/TreeNode.java deleted file mode 100644 index a1a3a5d2..00000000 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/common/TreeNode.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.common; - -/** - * - * @author lastwhisper - * @date 1/21/2020 - */ -public class TreeNode { - public int val; - public TreeNode left; - public TreeNode right; - - public TreeNode(int x) { - val = x; - } -} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/common/tree/bst/BSTTree.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/common/tree/bst/BSTTree.java deleted file mode 100644 index ea4c6bca..00000000 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/common/tree/bst/BSTTree.java +++ /dev/null @@ -1,122 +0,0 @@ -package cn.lastwhisper.common.tree.bst; - -import cn.lastwhisper.common.TreeNode; - -/** - * 二叉搜索树(Binary Search Tree,简称 BST):一个二叉树中, - * 任意节点的值要大于等于左子树所有节点的值,且要小于等于右边子树的所有节点的值。 - * https://leetcode-cn.com/problems/same-tree/solution/xie-shu-suan-fa-de-tao-lu-kuang-jia-by-wei-lai-bu-/ - * @author lastwhisper - * @date 1/21/2020 - */ -public class BSTTree { - - /** - * 判断 BST 的合法性 - * - * @param root - * @return boolean - */ - public boolean isValidBST(TreeNode root) { - return isValidBST(root, null, null); - } - - private boolean isValidBST(TreeNode root, TreeNode min, TreeNode max) { - if (root == null) return true; - if (min != null && root.val <= min.val) return false; - if (max != null && root.val >= max.val) return false; - return isValidBST(root.left, min, root) - && isValidBST(root.right, root, max); - } - - /** - * 在 BST 中查找一个数是否存在 - * - * @param root - * @param target - * @return boolean - */ - public boolean isInBST(TreeNode root, int target) { - if (root == null) return false; - if (root.val == target) - return true; - if (root.val < target) - return isInBST(root.right, target); - if (root.val > target) - return isInBST(root.left, target); - return false; - } - - /** - * 在 BST 中插入一个数 - * - * @param root - * @param val - */ - public TreeNode insertIntoBST(TreeNode root, int val) { - // 找到空位置插入新节点 - if (root == null) return new TreeNode(val); - // if (root.val == val) - // BST 中一般不会插入已存在元素 - if (root.val < val) - root.right = insertIntoBST(root.right, val); - if (root.val > val) - root.left = insertIntoBST(root.left, val); - return root; - } - - /** - * 在 BST 中删除一个节点key,删除节点的同时不能破坏 BST 的性质 - * 情况一:key恰好是末端节点,两个子节点都为空,直接删除 - * 情况二:key只有一个非空子节点,那么它要让这个孩子接替自己的位置 - * 情况三:key有两个子节点,找到左子树中最大的那个节点,或者右子树中最小的那个节点来接替自己。 - * @param root - * @param key - */ - public TreeNode deleteNode(TreeNode root, int key) { - if (root.val == key) { - // 情况一:key恰好是末端节点 - if (root.left == null && root.right == null) - return null; - // 情况二:key只有一个非空子节点 - if (root.left == null) return root.right; - if (root.right == null) return root.left; - // 情况三:key有两个子节点 - // root.left != null && root.right != null - // 找到右子树的最小节点 - TreeNode minNode = getMin(root.right); - // 把 root 改成 minNode - root.val = minNode.val; - // 转而去删除 minNode - root.right = deleteNode(root.right, minNode.val); - } else if (root.val > key) { - root.left = deleteNode(root.left, key); - } else { - // root.val < key - root.right = deleteNode(root.right, key); - } - return root; - } - - /** - * 找到BST中的最小值 - * - * @param node - */ - public TreeNode getMin(TreeNode node) { - // BST 最左边的就是最小的 - while (node.left != null) node = node.left; - return node; - } - - /** - * 找到BST中的最大值 - * - * @param node - */ - public TreeNode getMax(TreeNode node) { - // BST 最左边的就是最小的 - while (node.right != null) node = node.right; - return node; - } -} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/HeapSort.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/HeapSort.java deleted file mode 100644 index 071b0368..00000000 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/HeapSort.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.lastwhisper.datastructure.sort; - -import java.util.Arrays; - -/** - * 堆排序 - * - * @author cn.lastwhisper - */ -public class HeapSort { - public static void main(String[] args) { - //int[] arr = {4, 6, 8, 5, 9, 58, -10}; - int[] arr = {4, 6, 8, 5, 9}; - heapSort(arr); - System.out.println("数组:" + Arrays.toString(arr)); - } - - public static void heapSort(int[] arr) { - - //adjustHeap(arr, 1, arr.length); - //System.out.println("第1次" + Arrays.toString(arr)); // 4,9,8,5,6 - - //adjustHeap(arr, 0, arr.length); - //System.out.println("第2次" + Arrays.toString(arr)); // 9,6,8,5,4 - int temp; - // 1. 满二叉树从右向左、从下往上构建大顶堆;完全二叉树从左向右、从下往上构建大顶堆; - // i--意味着,从下到上,每一次都是[i,arr.length]的数组(二叉树)进行重构大顶堆 - // [0,arr.length]重构了数组(二叉树)头部几个元素的大顶堆,同时也会重构下面的二叉树 - for (int i = arr.length / 2 - 1; i >= 0; i--) { - adjustHeap(arr, i, arr.length); - } - // 2. 交换堆顶元素与末尾元素,调整堆结构 - for (int j = arr.length - 1; j >= 0; j--) { - // 交换 - temp = arr[j]; - arr[j] = arr[0]; - arr[0] = temp; - adjustHeap(arr, 0, j); - } - } - - - /** - * 将一个数组(二叉树), 调整成一个大顶堆 - * 功能: 将以i对应的非叶子节点的树调整成大顶堆 - * 举例 int arr[] = {4, 6, 8, 5, 9}; => i = 1 => adjustHeap => 得到 {4, 9, 8, 5, 6} - * 如果我们再次调用 adjustHeap 传入的是 i = 0 => {4, 9, 8, 5, 6} => {9, 6, 8, 5, 4} - * @param arr 待调整的数组 - * @param i 表示非叶子节点在数组中索引 - * @param length 表示对多少个元素继续调整, length 是在逐渐的减少 - */ - public static void adjustHeap(int[] arr, int i, int length) { - // 当前i节点 - int temp = arr[i]; - // k是i节点的左子节点,k + 1是右子节点 - for (int k = 2 * i + 1; k < length; k = 2 * k + 1) { - // arr[k] < arr[k + 1]左节点小于右节点 - if (k + 1 < length && arr[k] < arr[k + 1]) { - // k指向数值最大的节点 - k++; - } - if (arr[k] > temp) {//子节点大于父节点 - arr[i] = arr[k];//将子节点赋值到父节点 - i = k;//记录子节点的下标,为了最后 arr[i] = temp; - } else { - break; - } - } - //i = k; arr[i]此时已经是子节点的位置了,前面父节点已经拿到了子节点的值了,这里要将子节点的值赋为父节点的值 - arr[i] = temp; - } -} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/InsertSort.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/InsertSort.java deleted file mode 100644 index a1df21d5..00000000 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/InsertSort.java +++ /dev/null @@ -1,108 +0,0 @@ -package cn.lastwhisper.datastructure.sort; - -import cn.lastwhisper.util.ArrayUtil; - -import java.util.Arrays; - -/** - * @author cn.lastwhisper - */ -public class InsertSort { - public static void main(String[] args) { - //int[] arr = {101, 34, 119, 1}; - //insertSort1(arr); // 插入排序算法实现步骤 - - int[] arr = ArrayUtil.generateArrByRandom(100000); - // 计算耗时 - long start = System.currentTimeMillis(); - insertSort(arr); - long end = System.currentTimeMillis(); - System.out.println("耗时:" + (end - start) + " ms"); - - //System.out.println(Arrays.toString(arr)); - } - - /** - * 插入排序O(n^2) - * insertVal < arr[insertIndex降序 - * insertVal > arr[insertIndex升序 - * @param arr - * @return void - */ - public static void insertSort(int[] arr) { - int insertVal; - int insertIndex; - // 有序列表[0];[1...arr.length]无序列表 - for (int i = 1; i < arr.length; i++) { - // insertVal的意义:缓存无序列表的第一个数,这个数也是待插入有序列表的数 - insertVal = arr[i]; - // insertIndex的意义:记录有序列表的最后一个数的下标 - insertIndex = i - 1; - // [insertIndex+1...i-1]后移到[insertIndex+2...i](从前往后移动) - while (insertIndex >= 0 && insertVal < arr[insertIndex]) { - arr[insertIndex + 1] = arr[insertIndex]; - insertIndex--; - } - // insertIndex == i - 1; 说明数组并未后移,无需赋值 - if (insertIndex != i - 1) { - // arr[insertIndex + 1]为待插入位置 - arr[insertIndex + 1] = insertVal; - } - } - } - - /** - * 插入排序的实现步骤 - * - * @param arr - * @return void - */ - public static void insertSort1(int[] arr) { - // 第1轮 - // 有序列表{101},无序列表{34, 119, 1} - // {101, 34, 119, 1} - - // insertVal的意义:缓存无序列表的第一个数,这个数也是待插入有序列表的数 - int insertVal = arr[1]; - // insertIndex的意义:记录有序列表的最后一个数的下标 - int insertIndex = 1 - 1; - // insertIndex >= 0的意义:防止数组越界; - // insertVal < arr[insertIndex]的意义:找到insertVal要插入位置的前一个位置 - // 整个while循环的意义:数组覆盖后移,找到待插入位置的前一个位置 - while (insertIndex >= 0 && insertVal < arr[insertIndex]) { - // 第1轮原数组:{101, 34, 119, 1} - // arr[1]=arr[0] {101, 101, 119, 1} - arr[insertIndex + 1] = arr[insertIndex]; - //继续向前 - insertIndex--; - } - // arr[0]=insertVal {34, 101, 119, 1} - arr[insertIndex + 1] = insertVal; - - System.out.printf("第1轮插入,数组:%s\n", Arrays.toString(arr)); - - // 第2轮 - insertVal = arr[2]; - insertIndex = 2 - 1; - while (insertIndex >= 0 && insertVal < arr[insertIndex]) { - arr[insertIndex + 1] = arr[insertIndex]; - insertIndex--; - } - arr[insertIndex + 1] = insertVal; - System.out.printf("第2轮插入,数组:%s\n", Arrays.toString(arr)); - - // 第3轮 - insertVal = arr[3]; - insertIndex = 3 - 1; - while (insertIndex >= 0 && insertVal < arr[insertIndex]) { - // 第三轮原数组:{34, 101, 119, 1} - // arr[3]=arr[2] {34, 101, 119, 119} - // arr[2]=arr[1] {34, 101, 101, 119} - // arr[1]=arr[0] {34, 34, 101, 119} - arr[insertIndex + 1] = arr[insertIndex]; - insertIndex--; - } - arr[insertIndex + 1] = insertVal; - System.out.printf("第3轮插入,数组:%s\n", Arrays.toString(arr)); - } -} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/MergeSort.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/MergeSort.java deleted file mode 100644 index 3aad1458..00000000 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/MergeSort.java +++ /dev/null @@ -1,97 +0,0 @@ -package cn.lastwhisper.datastructure.sort; - -import cn.lastwhisper.util.ArrayUtil; - -/** - * @author cn.lastwhisper - */ -public class MergeSort { - - public static void main(String[] args) { - //int[] arr = {9, 8, 7, 6, 5, 4, 3, 2, 1}; - int[] arr = ArrayUtil.generateArrByRandom(10000000);// 1443 ms - // 计算耗时 - long start = System.currentTimeMillis(); - int[] temp = new int[arr.length]; - mergeSort(arr, 0, arr.length - 1, temp); - long end = System.currentTimeMillis(); - System.out.println("耗时:" + (end - start) + " ms"); - - //System.out.println(Arrays.toString(arr)); - } - - /** - * 归并排序 - * 分 - * - * @param arr 排序的原始数组 - * @param left 左边有序序列的初始索引 - * @param right 右边索引 - * @param temp 中转数组 - */ - public static void mergeSort(int[] arr, int left, int right, int[] temp) { - int mid; - if (left < right) { - mid = (left + right) / 2; - // 向左分 - mergeSort(arr, left, mid, temp); - // 向右分 - mergeSort(arr, mid + 1, right, temp); - // 治 - merge(arr, left, mid, right, temp); - } - } - - /** - * 治 - * @param arr 排序的原始数组 arr[left...mid] arr[mid+1...right] - * @param left 左边有序序列的初始索引 - * @param mid 中间索引 - * @param right 右边索引 - * @param temp 中转数组 - */ - public static void merge(int[] arr, int left, int mid, int right, int[] temp) { - int i = left; //左边有序序列的初始索引 - int j = mid + 1; // 右边有序序列的初始化序索引 - int t = 0; // 指向temp数组的当前位置 - - // 1)、将左右两边(有序)的数据按照规则填充到temp数组,任意一边处理完毕为止 - while (i <= mid && j <= right) { - - if (arr[i] < arr[j]) { - // 左小于右,将左数组第i个元素copy到temp数组的第t个位置 - temp[t] = arr[i]; - i += 1; - } else { - // 右小于或等于左,将右数组第j个元素copy到temp数组的第t个位置 - temp[t] = arr[j]; - j += 1; - } - t += 1; - } - - // 2)、把有剩余数据的一边的数据依次填充到temp - while (i <= mid) { - // 说明 右数组还有剩余元素 - temp[t] = arr[i]; - t += 1; - i += 1; - } - while (j <= right) { - // 说明 右数组还有剩余元素 - temp[t] = arr[j]; - t += 1; - j += 1; - } - - // 3)、将temp数组的数据copy到arr(并不是每次都copy所有) - t = 0; - int tempLeft = left; - while (tempLeft <= right) { // 0 1;2 3;0 3 - arr[tempLeft] = temp[t]; - t += 1; - tempLeft += 1; - } - - } -} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/QuickSort.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/QuickSort.java deleted file mode 100644 index 2b630986..00000000 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/QuickSort.java +++ /dev/null @@ -1,123 +0,0 @@ -package cn.lastwhisper.datastructure.sort; - -import java.util.Arrays; - -/** - * @author cn.lastwhisper - */ -public class QuickSort { - - public static void main(String[] args) { - //int[] arr = {-9, 78, 0, 23, -567, 70}; - //int[] arr = {-9, 78, 0, 23, 60, 70}; - //int[] arr = {9, 0, -567}; - int[] arr = {49, 38, 65, 97, 76, 13, 27}; - - //int[] arr = ArrayUtil.generateArrByRandom(10000000);//耗时:1519 ms - // 计算耗时 - long start = System.currentTimeMillis(); - //quickSort(arr, 0, arr.length - 1); - qSort(arr, 0, arr.length - 1); - long end = System.currentTimeMillis(); - System.out.println("耗时:" + (end - start) + " ms"); - - System.out.println(Arrays.toString(arr)); - } - - public static void qSort(int[] arr, int head, int tail) { - if (head >= tail || arr == null || arr.length <= 1) { - return; - } - //定义俩指针 用于移动 - int left = head; - int right = tail; - int pivot = arr[head]; //基准值,也可以arr[(head + tail) / 2] - - while (left <= right) { - while (arr[left] < pivot) { //左指针先走,找到大于等于基准数的停止 - ++left; - } - while (arr[right] > pivot) { //右指针后走,找到小于等于基准数的停止 - --right; - } - if (left < right) { - //交换arr[left]和arr[right]的位置 - int t = arr[left]; - arr[left] = arr[right]; - arr[right] = t; - //继续遍历 - ++left; - --right; - } else if (left == right) { - //遍历完,错开两指针,用于退出循环 - ++left; - //break; - } - } - - qSort(arr, head, right); - qSort(arr, left, tail); - } - - - /** - * 快速排序,选取数组中间的值 - * int pivot = arr[(left + right) / 2]; - * @param arr - * @param left - * @param right - * @return void - */ - public static void quickSort1(int[] arr, int left, int right) { - int l = left; // 左下标 - int r = right; // 右下标 - int temp; - // 中轴 - int pivot = arr[(left + right) / 2]; - // while循环的目的:小于或等于pivot的放左边,大于或等于pivot的放右边 - while (l < r) { - // 在pivot左边找比pivot大的值的下标l - while (arr[l] < pivot) { //找到arr[1]=98 >pivot=0 - l ++; - } - // 在pivot右边找比pivot小的值的下标r - while (arr[r] > pivot) { //找到arr[4]=-567 < pivot=0 - r--; - } - // 如果l>=r说明pivot左右两边的值,已经满足: - // 小于或等于pivot的放左边,大于或等于pivot的放右边 ——递归结束条件 - if (l >= r) { - break; - } - // 交换 - temp = arr[l]; - arr[l] = arr[r]; - arr[r] = temp; - // 如果交换完后,发现arr[l] == pivot,r--,前移 退出循环 - if (arr[l] == pivot) { - r --; - } - - // 如果交换完后,发现arr[r] == pivot,l++,后移 退出循环 - if (arr[r] == pivot) { - l ++; - } - } - - // 第二步 - - // 如果l==r,必须l++,r--,否则会栈溢出 - if (l == r) { - l = l + 1; - r = r - 1; - } - // 向左递归 - if (left < r) { - quickSort1(arr, left, r); - } - // 向右递归 - if (right > l) { - quickSort1(arr, l, right); - } - } -} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/QuickSort2.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/QuickSort2.java deleted file mode 100644 index 332a6595..00000000 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/QuickSort2.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.lastwhisper.datastructure.sort; - -/** - * @author lastwhisper - */ -public class QuickSort2 { - public static void main(String[] args) { - int[] arr = {7, 3, 2, 8, 1, 9, 5, 4, 6}; - //int arr[] = {7, 3, 2, 8, 1, 9, 5, 4, 6, 0};//为什么left++和right--条件里面要加 left <= right 限定 - //int arr[] = {7, 3, 2, 8, 1, 9, 5, 4, 6, 10}; - //int arr[] = {7, 3, 2, 6, 8, 1, 9, 5, 4, 6, 10, 6, 6}; // 为什么不取等 arr[right] > pivot - //int arr[] = {4, 6}; //小bug测试 // 为什么while (left <= right)里面要取等 - sort(arr, 0, arr.length - 1); - print(arr); - } - - private static void sort(int[] arr, int left, int right) { - if (left >= right) return; - int mid = partition(arr, left, right); - sort(arr, left, mid - 1); - sort(arr, mid + 1, right); - } - - // 分区 - private static int partition(int[] arr, int leftBound, int rightBound) { - int left = leftBound; - int pivot = arr[rightBound]; - int right = rightBound - 1; - - while (left <= right) { - while (left <= right && arr[left] <= pivot) left++;//left <= right是为了防止pivot最大,找不到比它大的数,导致越界 - while (left <= right && arr[right] > pivot) right--; - System.out.println("left:" + left + "\tright:" + right); - if (left < right) swap(arr, left, right); - } - swap(arr, left, rightBound); - return left; - } - - private static void swap(int[] arr, int i, int j) { - int temp = arr[i]; - arr[i] = arr[j]; - arr[j] = temp; - } - - private static void print(int[] arr) { - for (int value : arr) { - System.out.print(value + "\t"); - } - } -} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/RadixSort.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/RadixSort.java deleted file mode 100644 index b4c7476e..00000000 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/RadixSort.java +++ /dev/null @@ -1,152 +0,0 @@ -package cn.lastwhisper.datastructure.sort; - -import cn.lastwhisper.util.ArrayUtil; - -import java.util.Arrays; - -/** - * @author cn.lastwhisper - */ -public class RadixSort { - - public static void main(String[] args) { - // 算法实现步骤 - //int[] arr = {53, 3, 542, 748, 14, 214}; - //int[] arr = {3, 205, 14}; - //radixSortStudy(arr); - - // 计算耗时 - // 占用内存 10000000 * 10 * 4 /1024 / 1024 /1024 = 0.3725290298461914‬ - int[] arr = ArrayUtil.generateArrByRandom(10000000); - long start = System.currentTimeMillis(); - radixSort(arr); - long end = System.currentTimeMillis(); - System.out.println("耗时:" + (end - start) + " ms"); - - //System.out.println(Arrays.toString(arr)); - } - - /** - * 基数排序,桶排序的扩展 - * - * @param arr - * @return void - */ - public static void radixSort(int[] arr) { - - int[][] bucket = new int[10][arr.length]; - // 桶元素计数器,记录每个桶中存放了多少数据 - int[] bucketElementCount = new int[10]; - // 原arr下标 - int arrIndex; - // 除数 - int divisor = 1; - // 最大值 - int max = arr[0]; - // 由于基数排序次数由最大数值的位数决定,所以需要求最大值 - for (int i = 1; i < arr.length; i++) { - if (max < arr[i]) { - max = arr[i]; - } - } - // 最大值得位数,即排序次数 - int maxLength = (max + "").length(); - for (int f = 0; f < maxLength; f++) { - for (int i = 0; i < arr.length; i++) { - // digitOfElement对应放在哪个bucket中 - int digitOfElement = arr[i] / divisor % 10; - // 放在第digitOfElement个bucket的第bucketElementCount[digitOfElement]下标位置 - bucket[digitOfElement][bucketElementCount[digitOfElement]] = arr[i]; - // 下次放在bucket的第bucketElementCount[digitOfElement]++下标位置 - bucketElementCount[digitOfElement]++; - } - - arrIndex = 0; - // 将桶中数据放回原数组 - for (int i = 0; i < bucketElementCount.length; i++) { - // 对应桶中有数据 - if (bucketElementCount[i] != 0) { - for (int j = 0; j < bucketElementCount[i]; j++) { - arr[arrIndex++] = bucket[i][j]; - } - } - // 将桶元素计数器清空 - bucketElementCount[i] = 0; - } - divisor *= 10; - } - - } - - /** - * 桶排序算法实现步骤 - * - * @param arr - */ - public static void radixSortStudy(int[] arr) { - // - int[][] bucket = new int[10][arr.length]; - // 桶元素计数器,记录每个桶中存放了多少数据 - int[] bucketElementCount = new int[10]; - // 原arr下标 - int arrIndex; - - for (int i = 0; i < arr.length; i++) { - // digitOfElement对应放在哪个bucket中 - int digitOfElement = arr[i] % 10; - // 放在第digitOfElement个bucket的第bucketElementCount[digitOfElement]下标位置 - bucket[digitOfElement][bucketElementCount[digitOfElement]] = arr[i]; - // 下次放在bucket的第bucketElementCount[digitOfElement]++下标位置 - bucketElementCount[digitOfElement]++; - } - - arrIndex = 0; - // 将桶中数据放回原数组 - for (int i = 0; i < bucketElementCount.length; i++) { - // 对应桶中有数据 - if (bucketElementCount[i] != 0) { - for (int j = 0; j < bucketElementCount[i]; j++) { - arr[arrIndex++] = bucket[i][j]; - } - } - // 将桶元素计数器清空 - bucketElementCount[i] = 0; - } - - System.out.println("第1轮,对个位的排序处理 arr =" + Arrays.toString(arr)); - - for (int i = 0; i < arr.length; i++) { - // digitOfElement对应放在哪个bucket中 - int digitOfElement = arr[i] / 10 % 10; - // 放在第digitOfElement个bucket的第bucketElementCount[digitOfElement]下标位置 - bucket[digitOfElement][bucketElementCount[digitOfElement]] = arr[i]; - // 下次放在bucket的第bucketElementCount[digitOfElement]++下标位置 - bucketElementCount[digitOfElement]++; - } - - arrIndex = 0; - // 将桶中数据放回原数组 - for (int i = 0; i < bucketElementCount.length; i++) { - // 对应桶中有数据 - if (bucketElementCount[i] != 0) { - for (int j = 0; j < bucketElementCount[i]; j++) { - arr[arrIndex++] = bucket[i][j]; - } - } - // 将桶元素计数器清空 - bucketElementCount[i] = 0; - } - - System.out.println("第2轮,对个位的排序处理 arr =" + Arrays.toString(arr)); - - //for (int i = 0; i < bucket.length; i++) { - // for (int j = 0; j < bucket[0].length; j++) { - // System.out.printf("%d\t", bucket[i][j]); - // } - // System.out.println(); - //} - - } - - -} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/SelectSort.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/SelectSort.java deleted file mode 100644 index 33ac85a3..00000000 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/SelectSort.java +++ /dev/null @@ -1,82 +0,0 @@ -package cn.lastwhisper.datastructure.sort; - -import cn.lastwhisper.util.ArrayUtil; - -import java.util.Arrays; - -/** - * @author cn.lastwhisper - */ -public class SelectSort { - - public static void main(String[] args) { - //int[] arr = {101, 34, 119, 1}; - //selectSort1(arr); - //System.out.println(Arrays.toString(arr)); - - int[] arr = ArrayUtil.generateArrByRandom(100000); - // 计算耗时 - long start = System.currentTimeMillis(); - selectSort(arr); - long end = System.currentTimeMillis(); - System.out.println("耗时:" + (end - start) + " ms"); - } - - /** - * 选择排序O(n^2) - * - * @param arr - * @return void - */ - public static void selectSort(int[] arr) { - for (int i = 0; i < arr.length; i++) { - int min = arr[i]; - int minIndex = i; - // 找出[1+i...arr.length]范围内的最小值,和最小值索引 - for (int j = i + 1; j < arr.length; j++) { - if (min > arr[j]) { - min = arr[j]; - minIndex = j; - } - } - // 交换最小值与第i个数的位置 - if (minIndex != i) { - arr[minIndex] = arr[i]; - arr[i] = min; - } - } - } - - /** - * 算法的实现步骤 - * - * @param arr - * @return void - */ - public static void selectSort1(int[] arr) { - // 第1轮 {101, 34, 119, 1} - - // 1、找最小值 - // 最小值 - int min = arr[0]; - // 最小值索引 - int minIndex = 0; - // {101, 34, 119, 1} 我们假设待排序数组第一个元素就是最小值,即min=arr[0],minIndex=0 - // 经过遍历后我们发现 min=1,minIndex=3 - for (int j = 0 + 1; j < arr.length; j++) { - // 找最小的数 - if (min > arr[j]) { - min = arr[j]; - minIndex = j; - } - } - // 2、交换。minIndex是最小值所在位置,min是最小值 - if (minIndex != 0) { - arr[minIndex] = arr[0]; - arr[0] = min; - } - - System.out.printf("第1轮选择,数组:%s", Arrays.toString(arr)); - } - -} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/ShellSort.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/ShellSort.java deleted file mode 100644 index 4d834949..00000000 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/sort/ShellSort.java +++ /dev/null @@ -1,132 +0,0 @@ -package cn.lastwhisper.datastructure.sort; - -import java.util.Arrays; - -/** - * @author cn.lastwhisper - */ -public class ShellSort { - public static void main(String[] args) { - int[] arr = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0}; - //int[] arr = ArrayUtil.generateArrByRandom(100000); - // 计算耗时 - long start = System.currentTimeMillis(); - //shellSort1(arr); // 10490 ms - shellSort2(arr); // 10490 ms - long end = System.currentTimeMillis(); - System.out.println("耗时:" + (end - start) + " ms"); - - System.out.printf("希尔排序(交换法),数组:%s\n", Arrays.toString(arr)); - } - - - /** - * 希尔排序(位移法)(插入排序) - * - * @param arr - * @return void - */ - public static void shellSort2(int[] arr) { - // {8, 9, 1, 7, 2, 3, 5, 4, 6, 0} - int gap = arr.length / 2; - int j; - int temp; - while (gap > 0) { - //gap=5,2,1,0 - // i=5——》{0,5} - // i=6——》{1,6} - // i=7——》{2,7} - // i=8——》{3,8} - // i=9——》{4,9} - // 对每个数组进行插入排序;由于每个数组并不是真的存在的数组,而是一个大数组 - // 所以通过gap进行取值 - for (int i = gap; i < arr.length; i++) { - j = i; // 缓存每个数组的起始下标 - temp = arr[i]; // 缓存每个数组的起始下标的数值 - if (temp < arr[j - gap]) { - while (j - gap >= 0 && temp < arr[j - gap]) { - // 从前往后移动 - arr[j] = arr[j - gap]; - j = j - gap; - } - // - arr[j] = temp; - } - } - gap = gap / 2; - } - } - - /** - * 希尔排序(交换法) - * - * @param arr - * @return void - */ - public static void shellSort1(int[] arr) { - // 第1轮 {8, 9, 1, 7, 2, 3, 5, 4, 6, 0} - // 增量 gap=length/2 - int gap = arr.length / 2; - int temp; - while (gap > 0) { - for (int i = gap; i < arr.length; i++) { - // 交换 - for (int j = i - gap; j >= 0; j -= gap) { - if (arr[j] > arr[j + gap]) { - temp = arr[j + gap]; - arr[j + gap] = arr[j]; - arr[j] = temp; - } - } - } - gap = gap / 2; - } - } - - /** - * 交换法希尔排序 - * - * @param arr - * @return void - */ - public static void shellSortStudy(int[] arr) { - // 第1轮 [8, 9, 1, 7, 2, 3, 5, 4, 6, 0] - // 增量 gap=length/2 - int temp; - for (int i = 5; i < arr.length; i++) { - // 交换 - for (int j = i - 5; j >= 0; j -= 5) { - if (arr[j] > arr[j + 5]) { - temp = arr[j + 5]; - arr[j + 5] = arr[j]; - arr[j] = temp; - } - } - } - System.out.printf("第1轮插入,数组:%s\n", Arrays.toString(arr)); - // 第二轮 [3, 5, 1, 6, 0, 8, 9, 4, 7, 2] - for (int i = 2; i < arr.length; i++) { - // 交换 - for (int j = i - 2; j >= 0; j -= 2) { - if (arr[j] > arr[j + 2]) { - temp = arr[j + 2]; - arr[j + 2] = arr[j]; - arr[j] = temp; - } - } - } - System.out.printf("第2轮插入,数组:%s\n", Arrays.toString(arr)); - // 第二轮 [0, 2, 1, 4, 3, 5, 7, 6, 9, 8] - for (int i = 1; i < arr.length; i++) { - // 交换 - for (int j = i - 1; j >= 0; j -= 1) { - if (arr[j] > arr[j + 1]) { - temp = arr[j + 1]; - arr[j + 1] = arr[j]; - arr[j] = temp; - } - } - } - System.out.printf("第2轮插入,数组:%s\n", Arrays.toString(arr)); - } -} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/traversal/Solution.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/traversal/Solution.java deleted file mode 100644 index e1a861dc..00000000 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/datastructure/tree/traversal/Solution.java +++ /dev/null @@ -1,96 +0,0 @@ -package cn.lastwhisper.datastructure.tree.traversal; - -import cn.lastwhisper.common.TreeNode; - -import java.util.Stack; - -public class Solution { - // 二叉树后序遍历的两种易写的非递归写法 - 我要吃栗子的文章 - 知乎 - //https://zhuanlan.zhihu.com/p/80578741 - public static void main(String[] args) { - TreeNode root = new TreeNode(1); - TreeNode treeNode2 = new TreeNode(2); - TreeNode treeNode3 = new TreeNode(3); - TreeNode treeNode4 = new TreeNode(4); - TreeNode treeNode5 = new TreeNode(5); - root.left = treeNode2; - root.right = treeNode3; - treeNode2.left = treeNode4; - treeNode2.right = treeNode5; - - Solution solution = new Solution(); - //solution.preOrderTraversal(root); - //solution.postOrderTraversal1(root); - solution.postOrderTraversal2(root); - - } - - /** - * 非递归先序遍历,遍历顺序:根左右 - * 需要使用一个栈 - */ - public void preOrderTraversal(TreeNode root) { - Stack s = new Stack<>(); - TreeNode cur = root; - while (cur != null || !s.isEmpty()) { - while (cur != null) { // 经过并访问所有左节点 - System.out.println(cur.val); - s.push(cur); - cur = cur.left; - } - while (!s.isEmpty() && cur == null) cur = s.pop().right; // 自底向上找栈中节点的第一个非空右子树 - } - } - - /** - * 非递归后序遍历,遍历顺序:左右根 - * 使用两个栈 - * 参考非递归先序遍历的“根左右”顺序,使用栈反过来 - */ - public void postOrderTraversal1(TreeNode root) { - Stack s = new Stack<>(); - Stack res = new Stack<>(); // 保存节点序列的栈 - TreeNode cur = root; - while (cur != null || !s.isEmpty()) { - while (cur != null) { - res.push(cur.val); - s.push(cur); - cur = cur.right; // 修改处 - } - if (!s.isEmpty()) { - cur = s.pop(); - cur = cur.left; // 修改处 - } - } - while (!res.isEmpty()) System.out.println(res.pop());// 获取倒序的根右左序列 - } - - /** - * 非递归后序遍历,遍历顺序:左右根 - * 使用一个栈 - */ - public void postOrderTraversal2(TreeNode root) { - Stack s = new Stack<>(); - TreeNode cur = root; - TreeNode pre = null; // 用于记录上一次访问的节点 - while(cur!=null || !s.isEmpty()) { - while(cur!=null) { - s.push(cur); - cur = cur.left; - } - if(!s.isEmpty()) { - cur = s.pop(); - if(cur.right==null || pre==cur.right) { // 访问节点的条件 - System.out.println(cur.val); // 访问 - pre = cur; // 这一步是记录上一次访问的节点 - cur = null; // 此处为了跳过下一次循环的访问左子节点的过程,直接进入栈的弹出阶段,因为但凡在栈中的节点,它们的左子节点都肯定被经过且已放入栈中。 - } - else { // 不访问节点的条件 - s.push(cur); // 将已弹出的根节点放回栈中 - cur = cur.right; // 经过右子节点 - } - } - } - } - -} diff --git a/algorithms/datastructure/src/main/java/cn/lastwhisper/time/TimeTest.java b/algorithms/datastructure/src/main/java/cn/lastwhisper/time/TimeTest.java deleted file mode 100644 index cadbe901..00000000 --- a/algorithms/datastructure/src/main/java/cn/lastwhisper/time/TimeTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.lastwhisper.time; - -/** - * @author cn.lastwhisper - */ -public class TimeTest { - - public void test1() { - int x = 1; - for (int i = 0; i < 10000; i++) { - x++; - } - } - - public void test2(int n) { - int i = 1; - while (i < n) { - i = i * 2; - } - } - - public void test3(int n) { - //for (i = 0; i < n; i++) { - // for (j = 0; j < i; j++) { - // for (k = 0; k < j; k++) - // x = x + 2; - // } - //} - } -} diff --git "a/algorithms/go/algorithm/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution1.go" "b/algorithms/go/algorithm/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution1.go" new file mode 100644 index 00000000..eb316f9f --- /dev/null +++ "b/algorithms/go/algorithm/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution1.go" @@ -0,0 +1,31 @@ +package main + +import ( + "fmt" +) + +/** + * 题目地址:https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/ + * 编号:167 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:暴力搜索,找出所有组合进行对比 + * ------------------------------------------------------------------- + * 时间复杂度:O(n^2) + * 空间复杂度:O(1) + */ +func twoSum(numbers []int, target int) []int { + for i := 0; i < len(numbers); i++ { + for j := i + 1; j < len(numbers); j++ { // i + 1 是一个优化点 + if i != j && numbers[i]+numbers[j] == target { + return []int{i + 1, j + 1} + } + } + } + return nil +} + +func main() { + fmt.Println(twoSum([]int{2, 3, 4}, 6)) +} diff --git "a/algorithms/go/algorithm/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution2.go" "b/algorithms/go/algorithm/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution2.go" new file mode 100644 index 00000000..6ad9d169 --- /dev/null +++ "b/algorithms/go/algorithm/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution2.go" @@ -0,0 +1,46 @@ +package main + +import ( + "fmt" +) + +/** + * 题目地址:https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/ + * 编号:167 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:二分搜索 + * (1)遍历数组,对每一个值 nums[i],在 nums 数组中进行 [i,n] 范围的二分搜索 + * ------------------------------------------------------------------- + * 时间复杂度:O(n*logn) + * 空间复杂度:O(1) + */ +func twoSum(numbers []int, target int) []int { + for i := 0; i < len(numbers); i++ { + j := bs(numbers, i, len(numbers)-1, target-numbers[i]) + if j != -1 { + return []int{i + 1, j + 1} + } + } + return nil +} + +func bs(nums []int, l int, r int, target int) int { + // 这里是“<=”因为 [l,r] 内所有值都是可能的目标 + for l <= r { + mid := (l-r)/2 + r + if nums[mid] == target { + return mid + } else if nums[mid] > target { + r = mid - 1 + } else { + l = mid + 1 + } + } + return -1 +} + +func main() { + fmt.Println(twoSum([]int{2, 3, 4}, 6)) +} diff --git "a/algorithms/go/algorithm/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution3.go" "b/algorithms/go/algorithm/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution3.go" new file mode 100644 index 00000000..f3b51b13 --- /dev/null +++ "b/algorithms/go/algorithm/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution3.go" @@ -0,0 +1,40 @@ +package main + +import ( + "fmt" +) + +/** + * 题目地址:https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/ + * 编号:167 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:双指针(对撞指针) + * 这种思路的前提是数组有序 + * (1)定义两个初始指针 l,r 分别指向数组头尾。 + * (2)nums[l]+nums[r] > target,r-- + * (3)nums[l]+nums[r] < target,l++ + * (4)nums[l]+nums[r] == target,找到答案 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ +func twoSum(numbers []int, target int) []int { + l, r := 0, len(numbers)-1 + // 这里不能等于,因为 index1 必须小于 index2 + for l < r { + if numbers[l]+numbers[r] == target { + return []int{l + 1, r + 1} + } else if numbers[l]+numbers[r] < target { + l++ + } else { + r-- + } + } + return nil +} + +func main() { + fmt.Println(twoSum([]int{2, 3, 4}, 6)) +} diff --git "a/algorithms/go/algorithm/leetcode/array/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262_344_\347\256\200\345\215\225/Solution1.go" "b/algorithms/go/algorithm/leetcode/array/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262_344_\347\256\200\345\215\225/Solution1.go" new file mode 100644 index 00000000..e8e1d727 --- /dev/null +++ "b/algorithms/go/algorithm/leetcode/array/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262_344_\347\256\200\345\215\225/Solution1.go" @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" +) + +/** + * 题目地址:https://leetcode-cn.com/problems/reverse-string/ + * 编号:344 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:对撞指针交换元素 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ +func reverseString(s []byte) { + l, r := 0, len(s)-1 + for l < r { + c := s[l] + s[l] = s[r] + s[r] = c + l++ + r-- + } +} + +func main() { + s := []byte{'h', 'e', 'l', 'l', 'o'} + fmt.Println(s) + reverseString(s) + fmt.Println(s) +} diff --git "a/algorithms/go/algorithm/leetcode/array/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\205\203\351\237\263\345\255\227\346\257\215_345_\347\256\200\345\215\225/Solution1.go" "b/algorithms/go/algorithm/leetcode/array/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\205\203\351\237\263\345\255\227\346\257\215_345_\347\256\200\345\215\225/Solution1.go" new file mode 100644 index 00000000..5df7b3ea --- /dev/null +++ "b/algorithms/go/algorithm/leetcode/array/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\205\203\351\237\263\345\255\227\346\257\215_345_\347\256\200\345\215\225/Solution1.go" @@ -0,0 +1,49 @@ +package main + +import ( + "fmt" +) + +/** + * 题目地址:https://leetcode-cn.com/problems/reverse-vowels-of-a-string/ + * 编号:345 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:对撞指针条件交换元素 + * 元音字母:a,e,i,o,u 大小写 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ +func reverseVowels(s string) string { + l, r := 0, len(s)-1 + chars := []uint8(s) + for l < r { + for l < r && !valid(chars[l]) { + l++ + } + for l < r && !valid(chars[r]) { + r-- + } + if l < r { // 需要判断 + c := chars[l] + chars[l] = chars[r] + chars[r] = c + l++ + r-- + } + } + return string(chars) +} + +func valid(c uint8) bool { + return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'A' || + c == 'E' || c == 'I' || c == 'O' || c == 'U' +} + +func main() { + s := "hello" + fmt.Println(s) + fmt.Println(reverseVowels(s)) +} diff --git "a/algorithms/go/algorithm/leetcode/array/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution1.go" "b/algorithms/go/algorithm/leetcode/array/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution1.go" new file mode 100644 index 00000000..19048a82 --- /dev/null +++ "b/algorithms/go/algorithm/leetcode/array/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution1.go" @@ -0,0 +1,60 @@ +package main + +import "fmt" + +/** + * 题目地址:https://leetcode-cn.com/problems/merge-sorted-array/ + * 编号:88 + * ------------------------------------------------------------------- + * 思考: + * 数据特征:数组有序 + * ------------------------------------------------------------------- + * 思路: + * 归并排序,归的过程。 + * (1)从前到后比较(找小)复制只用 nums1,需要移动 nums1 中的元素,不如创建中间数据 + * (2)从后到前比较(找大)复制只用 nums1,无需移动 nums1 中的元素 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ +func merge(nums1 []int, m int, nums2 []int, n int) { + temp := make([]int, m+n) + // p1 是 num1 已拷贝数据的指针,[0,p1] + p1, p2, t := 0, 0, 0 + // 从前到后找 num1 或 num2 最小的复制到 temp + for p1 < m && p2 < n { + if nums1[p1] > nums2[p2] { + temp[t] = nums2[p2] + p2++ + } else { + temp[t] = nums1[p1] + p1++ + } + t++ + } + // 将 num1 中剩余的数据 copy 到 temp + for p1 < m { + temp[t] = nums1[p1] + t++ + p1++ + } + // 将 num2 中剩余的数据 copy 到 temp + for p2 < n { + temp[t] = nums2[p2] + t++ + p2++ + } + // 将 temp 中所有数据 copy 到 num1 + for i := 0; i < len(temp); i++ { + nums1[i] = temp[i] + } +} + +func main() { + nums1 := []int{1, 2, 3, 0, 0, 0} + nums2 := []int{2, 5, 6} + m := 3 + n := 3 + merge(nums1, m, nums2, n) + fmt.Println(nums1) +} diff --git "a/algorithms/go/algorithm/leetcode/array/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution2.go" "b/algorithms/go/algorithm/leetcode/array/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution2.go" new file mode 100644 index 00000000..c0d54a69 --- /dev/null +++ "b/algorithms/go/algorithm/leetcode/array/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution2.go" @@ -0,0 +1,47 @@ +package main + +import "fmt" + +/** + * 题目地址:https://leetcode-cn.com/problems/merge-sorted-array/ + * 编号:88 + * ------------------------------------------------------------------- + * 思考: + * 数据特征:数组有序 + * ------------------------------------------------------------------- + * 思路: + * 从后向前复制 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ +func merge(nums1 []int, m int, nums2 []int, n int) { + // 从后到前找 num1 或 num2 最大的复制到 num1 末尾 + p1, p2, end := m-1, n-1, m+n-1 + for p1 >= 0 && p2 >= 0 { + if nums1[p1] > nums2[p2] { + nums1[end] = nums1[p1] + p1-- + } else { + nums1[end] = nums2[p2] + p2-- + } + end-- + } + // 如果 num1 还没复制完,不用管,因为num1自身就是有序的 + // 将 num2 中剩余的数据 copy 到 temp + for p2 >= 0 { + nums1[end] = nums2[p2] + end-- + p2-- + } +} + +func main() { + nums1 := []int{1, 2, 3, 0, 0, 0} + nums2 := []int{2, 5, 6} + m := 3 + n := 3 + merge(nums1, m, nums2, n) + fmt.Println(nums1) +} diff --git "a/algorithms/go/algorithm/leetcode/array/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution1.go" "b/algorithms/go/algorithm/leetcode/array/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution1.go" new file mode 100644 index 00000000..6620e6b9 --- /dev/null +++ "b/algorithms/go/algorithm/leetcode/array/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution1.go" @@ -0,0 +1,12 @@ +package main + +import "sort" + +func findKthLargest(nums []int, k int) int { + sort.Ints(nums) + return nums[len(nums)-k] +} + +func main() { + +} diff --git "a/algorithms/go/algorithm/leetcode/array/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_\344\270\255\347\255\211/Solution1.go" "b/algorithms/go/algorithm/leetcode/array/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_\344\270\255\347\255\211/Solution1.go" new file mode 100644 index 00000000..eb157e31 --- /dev/null +++ "b/algorithms/go/algorithm/leetcode/array/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_\344\270\255\347\255\211/Solution1.go" @@ -0,0 +1,51 @@ +package main + +import ( + "fmt" +) + +/** + * 题目地址:https://leetcode-cn.com/problems/minimum-size-subarray-sum/ + * 编号:209 + * ------------------------------------------------------------------- + * 思考:边界值一定要考虑取还是不取,为什么? + * ------------------------------------------------------------------- + * 思路:滑动窗口 + * (1)双指针 l、r 维护一个滑动窗口 + * (2)窗口的左边界在数组范围内,则循环继续 + * (3)r未到数组尾且 sums 需要动态缩小窗口左边界 + * (5)循环内每次找 sum >= s 时的最小长度 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) // l 和 r 指针同时遍历了一遍数组 O(2n) + * 空间复杂度:O(1) + */ +func lengthOfLongestSubstring(s string) int { + freq := make([]uint8, 256) + // 窗口 [l,r] 内无重复元素 + l, r, res := 0, 0, 0 + for l < len(s) { + if r < len(s) && freq[s[r]] == 0 { + freq[s[r]]++ + r++ + } else { + freq[s[l]]-- + l++ + } + // 这里 r - l 不加一,因为 l、r 初始化值都是0,并且是先用在加的 + res = max(res, r-l) + } + return res +} + +func max(x int, y int) int { + if x > y { + return x + } + return y +} + +func main() { + s := "abcabcbb" + fmt.Println(lengthOfLongestSubstring(s)) +} diff --git "a/algorithms/go/algorithm/leetcode/array/\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250_11_\344\270\255\347\255\211/Solution1.go" "b/algorithms/go/algorithm/leetcode/array/\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250_11_\344\270\255\347\255\211/Solution1.go" new file mode 100644 index 00000000..c67ee938 --- /dev/null +++ "b/algorithms/go/algorithm/leetcode/array/\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250_11_\344\270\255\347\255\211/Solution1.go" @@ -0,0 +1,36 @@ +package main + +import ( + "fmt" + "math" +) + +/** + * 题目地址:https://leetcode-cn.com/problems/container-with-most-water/ + * 编号:11 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:双指针(对撞指针) + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ +func maxArea(height []int) int { + l, r, max := 0, len(height)-1, float64(-1) + for l < r { + if height[l] < height[r] { + max = math.Max(max, float64(height[l]*(r-l))) + l++ + } else { + max = math.Max(max, float64(height[r]*(r-l))) + r-- + } + } + return int(max) +} + +func main() { + nums := []int{1, 8, 6, 2, 5, 4, 8, 3, 7} + fmt.Println(maxArea(nums)) +} diff --git "a/algorithms/go/algorithm/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution1.go" "b/algorithms/go/algorithm/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution1.go" new file mode 100644 index 00000000..7b603a86 --- /dev/null +++ "b/algorithms/go/algorithm/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution1.go" @@ -0,0 +1,60 @@ +package main + +import ( + "fmt" + "math" +) + +/** + * 题目地址:https://leetcode-cn.com/problems/minimum-size-subarray-sum/ + * 编号:209 + * ------------------------------------------------------------------- + * 思考:边界值一定要考虑取还是不取,为什么? + * ------------------------------------------------------------------- + * 思路:滑动窗口 + * (1)双指针 l、r 维护一个滑动窗口 + * (2)窗口的左边界在数组范围内,则循环继续 + * (3)r未到数组尾且 sums 需要动态缩小窗口左边界 + * (5)循环内每次找 sum >= s 时的最小长度 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) // l 和 r 指针同时遍历了一遍数组 O(2n) + * 空间复杂度:O(1) + */ +func minSubArrayLen(s int, nums []int) int { + // 滑动窗口[l,r] + l, r := 0, -1 + // 窗口和 + sum, result := 0, math.MaxInt64 + // 窗口左边界未越界,说明窗口还可以继续扩容或者缩小 + for l < len(nums) { + // sum= s { + result = min(result, r-l+1) + } + } + if result == math.MaxInt64 { + return 0 + } + return result +} + +func min(x int, y int) int { + if x > y { + return y + } + return x +} + +func main() { + s := 7 + nums := []int{2, 3, 1, 2, 4, 3} + fmt.Println(minSubArrayLen(s, nums)) +} diff --git "a/algorithms/go/algorithm/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution2.go" "b/algorithms/go/algorithm/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution2.go" new file mode 100644 index 00000000..5e234415 --- /dev/null +++ "b/algorithms/go/algorithm/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution2.go" @@ -0,0 +1,54 @@ +package main + +import ( + "fmt" + "math" +) + +/** + * 题目地址:https://leetcode-cn.com/problems/minimum-size-subarray-sum/ + * 编号:209 + * ------------------------------------------------------------------- + * 思考:边界值一定要考虑取还是不取,为什么? + * ------------------------------------------------------------------- + * 思路:滑动窗口 + * (1)双指针 l、r 维护一个滑动窗口 + * (2)窗口的左边界在数组范围内,则循环继续 + * (3)r未到数组尾且 sums 需要动态缩小窗口左边界 + * (5)循环内每次找 sum >= s 时的最小长度 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) // l 和 r 指针同时遍历了一遍数组 O(2n) + * 空间复杂度:O(1) + */ +func minSubArrayLen(s int, nums []int) int { + // 窗口和 + l, sum, result := 0, 0, math.MaxInt64 + // 一直扩容右边界,直到sum >= s,缩小左边界 + // 每次缩小,都计算最小子数组 + for r := 0; r < len(nums); r++ { + sum += nums[r] + for sum >= s { + result = min(result, r-l+1) + sum -= nums[l] + l++ + } + } + if result == math.MaxInt64 { + return 0 + } + return result +} + +func min(x int, y int) int { + if x > y { + return y + } + return x +} + +func main() { + s := 7 + nums := []int{2, 3, 1, 2, 4, 3} + fmt.Println(minSubArrayLen(s, nums)) +} diff --git "a/algorithms/go/algorithm/leetcode/array/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution1.go" "b/algorithms/go/algorithm/leetcode/array/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution1.go" new file mode 100644 index 00000000..51d91b90 --- /dev/null +++ "b/algorithms/go/algorithm/leetcode/array/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution1.go" @@ -0,0 +1,37 @@ +package main + +import "fmt" + +/** + * 题目地址:https://leetcode-cn.com/problems/sort-colors/ + * 编号:75 + * ------------------------------------------------------------------- + * 思考: + * 数据特征:只有0,1,2 + * ------------------------------------------------------------------- + * 思路: + * 计数排序,统计每一个数出现的频率 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ +func sortColors(nums []int) { + freq := [3]int{} + for i := 0; i < len(nums); i++ { + freq[nums[i]]++ + } + idx := 0 + for i := 0; i < len(freq); i++ { + for freq[i] > 0 { + nums[idx] = i + idx++ + freq[i]-- + } + } +} + +func main() { + var arr = []int{2, 0, 2, 1, 1, 0} + sortColors(arr) + fmt.Println(arr) +} diff --git "a/algorithms/go/algorithm/leetcode/array/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution2.go" "b/algorithms/go/algorithm/leetcode/array/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution2.go" new file mode 100644 index 00000000..cc952a6d --- /dev/null +++ "b/algorithms/go/algorithm/leetcode/array/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution2.go" @@ -0,0 +1,51 @@ +package main + +import "fmt" + +/** + * 题目地址:https://leetcode-cn.com/problems/sort-colors/ + * 编号:75 + * ------------------------------------------------------------------- + * 思考: + * 数据特征:只有0,1,2 + * ------------------------------------------------------------------- + * 思路: + * 三路快速排序的思想,对整个数组只遍历了一遍 + * (1)双指针 left=-1,right=n + * (2)下标 i 遍历数组,num[i]==1,i++ + * (3)num[i]==0,将 0 移动到数组最前位置,swap(num,++left,i++) + * i++,即使 num[++left]==0,这次的交换和位移也是正确的 + * (4)num[i]==2,将 2 移动到数组最后位置,swap(num,--right,i) + * i不变,因为有可能num[--right]==2 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ +func sortColors(nums []int) { + left := -1 + right := len(nums) + for i := 0; i < right; { + if nums[i] == 1 { + i++ + } else if nums[i] == 0 { + left++ + swap(nums, left, i) + i++ + } else if nums[i] == 2 { + right-- + swap(nums, right, i) + } + } +} + +func swap(nums []int, i, j int) { + temp := nums[i] + nums[i] = nums[j] + nums[j] = temp +} + +func main() { + var arr = []int{2, 0, 2, 1, 1, 0} + sortColors(arr) + fmt.Println(arr) +} diff --git "a/algorithms/go/algorithm/leetcode/array/\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262_125_Easy/Solution1.go" "b/algorithms/go/algorithm/leetcode/array/\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262_125_Easy/Solution1.go" new file mode 100644 index 00000000..e8d5b633 --- /dev/null +++ "b/algorithms/go/algorithm/leetcode/array/\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262_125_Easy/Solution1.go" @@ -0,0 +1,45 @@ +package main + +import ( + "fmt" + "strings" +) + +/** + * 题目地址:https://leetcode-cn.com/problems/valid-palindrome/ + * 编号:125 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 对撞指针遍历比较 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ +func isPalindrome(s string) bool { + upperS := strings.ToUpper(s) + l, r := 0, len(s)-1 + for l < r { + for l < r && !valid(upperS[l]) { + l++ + } + for l < r && !valid(upperS[r]) { + r-- + } + if upperS[l] != upperS[r] { + return false + } + l++ + r-- + } + return true +} + +func valid(c uint8) bool { + return (c >= 48 && c <= 57) || (c >= 65 && c <= 90) || (c >= 97 && c <= 122) +} + +func main() { + fmt.Println(isPalindrome("A man, a plan, a canal: Panama")) +} diff --git "a/algorithms/go/algorithm/leetcode/array/\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262_125_Easy/Solution2.go" "b/algorithms/go/algorithm/leetcode/array/\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262_125_Easy/Solution2.go" new file mode 100644 index 00000000..5aebc977 --- /dev/null +++ "b/algorithms/go/algorithm/leetcode/array/\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262_125_Easy/Solution2.go" @@ -0,0 +1,45 @@ +package main + +import ( + "fmt" +) + +/** + * 题目地址:https://leetcode-cn.com/problems/valid-palindrome/ + * 编号:125 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 对撞指针遍历比较 + * 统一转成大写:ch & 0b11011111 简写:ch & 0xDF + * 统一转成小写:ch | 0b00100000 简写:ch | 0x20 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ +func isPalindrome(s string) bool { + l, r := 0, len(s)-1 + for l < r { // 这里不能等于 + for l < r && !valid(s[l]) { + l++ + } + for l < r && !valid(s[r]) { + r-- + } + if (s[l] & 0xDF) != (s[r] & 0xDF) { + return false + } + l++ + r-- + } + return true +} + +func valid(c uint8) bool { + return (c >= 48 && c <= 57) || (c >= 65 && c <= 90) || (c >= 97 && c <= 122) +} + +func main() { + fmt.Println(isPalindrome("A man, a plan, a canal: Panama")) +} diff --git a/algorithms/go/algorithm/leetcode/lc69.go b/algorithms/go/algorithm/leetcode/lc69.go new file mode 100644 index 00000000..33b59de5 --- /dev/null +++ b/algorithms/go/algorithm/leetcode/lc69.go @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func mySqrt(x int) int { + + + return 0 +} + +func main() { + fmt.Println(mySqrt(4)) + fmt.Println(mySqrt(8)) +} + diff --git a/algorithms/interview/src/main/java/cn/lastwhisper/interview/lejian/Test1.java b/algorithms/interview/src/main/java/cn/lastwhisper/interview/lejian/Test1.java new file mode 100644 index 00000000..8d64005c --- /dev/null +++ b/algorithms/interview/src/main/java/cn/lastwhisper/interview/lejian/Test1.java @@ -0,0 +1,113 @@ +package cn.lastwhisper.interview.lejian; + +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Pattern; + +/** + * 最长对称子序列,本质上是在找最长公共子序列 + * + * @author gaojun + * + */ +public class Test1 { + + /** + * 输入一个字符串s,我们可以删除字符串s中的任意字符,让剩下的字符串形成一个对称字符串,且该字符串为最长对称字符串。 + * 如:输入google,则找到最长对称字符串为goog; + * 如:输入abcda则能找到3个最长对称字符串为aba/aca/ada。 + * 若最长对称字符串存在多个,则输出多个相同长度的最长对称字符串,且字符串中不包含特殊字符。 + * + */ + public static void main(String[] args) { + // TODO 输出最长对称字符串:goog + String input1 = "google"; + System.out.println(findMaxSymmetry(input1)); + // TODO 输出3个最长对称字符串:aba/aca/ada + String input2 = "abcda"; + System.out.println(findMaxSymmetry(input2)); + // TODO 输出2个最长对称字符串:pop/upu,不会输出特殊字符的对称字符串p-p + String input3 = "pop-upu"; + System.out.println(findMaxSymmetry(input3)); + } + + /** + * 遍历生成的二维数组,递归查找最长路径 + * @param a 第一个字符串 + * @param b 第二个字符串 + * @param mux 二维中间数组 + * @param i 二维数组raw位置 + * @param j 二维数组column位置 + * @param path 一次查找的字符串 + * @param paths 最终结果集合 + */ + private static void getAllLcs(String a, String b, int[][] mux, int i, int j, String path, Set paths) { + StringBuilder pathBuilder = new StringBuilder(path); + while (i > 0 && j > 0) { + if (a.charAt(i - 1) == b.charAt(j - 1)) { + pathBuilder.append(a.charAt(i - 1)); + --i; + --j; + } else { + if (mux[i - 1][j] > mux[i][j - 1]) { + --i; + } else if (mux[i - 1][j] < mux[i][j - 1]) { + --j; + } else { + getAllLcs(a, b, mux, i - 1, j, pathBuilder.toString(), paths); + getAllLcs(a, b, mux, i, j - 1, pathBuilder.toString(), paths); + return; + } + } + } + paths.add(pathBuilder.toString()); + } + + /** + * 查找最大公共子序列 + */ + private static String findLCS(String input) { + if (input == null || input.length() == 0) { + return ""; + } + String reverse = new StringBuilder(input).reverse().toString(); + int len = input.length(); + // 0行0列分别表示空串和input、reverse的 lcs 长度 + // 初始状态 + int[][] dp = new int[len + 1][len + 1]; + + for (int i = 1; i < len + 1; i++) { + for (int j = 1; j < len + 1; j++) { + if (input.charAt(i - 1) == reverse.charAt(j - 1)) { + // 找到一个 lcs 的元素 + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + // 找 lcs 长度最长的。 + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + } + } + } + + // 查找路径时,存在多个路径是一个字符串的情况,set去重。 + Set paths = new HashSet<>(); + getAllLcs(input, reverse, dp, input.length(), reverse.length(), "", paths); + + return String.join("/", paths); + } + + /** + * 包括对特殊字符,结果格式生成 + * @param input 待处理字符串 + */ + public static String findMaxSymmetry(String input) { + String[] prepare = Pattern.compile("[^a-zA-Z0-9]").split(input); + StringBuilder sb = new StringBuilder(); + for (String str : prepare) { + String result = findLCS(str); + sb.append(result); + sb.append("/"); + } + return sb.substring(0, sb.length() - 1); + } + +} \ No newline at end of file diff --git a/algorithms/leetcode/array/pom.xml b/algorithms/leetcode/array/pom.xml index d86e8f28..6689d525 100644 --- a/algorithms/leetcode/array/pom.xml +++ b/algorithms/leetcode/array/pom.xml @@ -13,4 +13,13 @@ array + + + algorithm-common + cn.lastwhisper + 1.0-SNAPSHOT + + + + \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..3114b286 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,34 @@ +package cn.lastwhisper.leetcode.array.两数之和_II_输入有序数组_167_简单; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/ + * 编号:167 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:暴力搜索,找出所有组合进行对比 + * ------------------------------------------------------------------- + * 时间复杂度:O(n^2) + * 空间复杂度:O(1) + */ + public int[] twoSum(int[] numbers, int target) { + if (numbers == null || numbers.length < 2) { + throw new IllegalArgumentException("Illegal argument numbers"); + } + for (int i = 0; i < numbers.length; i++) { + for (int j = i + 1; j < numbers.length; j++) {// i + 1 是一个优化点 + if (i != j && numbers[i] + numbers[j] == target) { + return new int[]{i + 1, j + 1}; + } + } + } + throw new IllegalStateException("No results found"); + } + + public static void main(String[] args) { + Assert.assertArrayEquals(new int[]{1, 2}, new Solution1().twoSum(new int[]{2, 7, 11, 15}, 9)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..d6b0e31b --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,57 @@ +package cn.lastwhisper.leetcode.array.两数之和_II_输入有序数组_167_简单; + +import org.junit.Assert; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/ + * 编号:167 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:二分搜索 + * (1)遍历数组,对每一个值 nums[i],在 nums 数组中进行 [i,n] 范围的二分搜索 + * ------------------------------------------------------------------- + * 时间复杂度:O(n*logn) + * 空间复杂度:O(1) + */ + public int[] twoSum(int[] numbers, int target) { + if (numbers == null || numbers.length < 2) { + throw new IllegalArgumentException("Illegal argument numbers"); + } + for (int i = 0; i < numbers.length; i++) { + int j = bs(numbers, i, numbers.length - 1, target - numbers[i]); + if (j != -1) { + return new int[]{i + 1, j + 1}; + } + } + throw new IllegalStateException("No results found"); + } + + /** + * @param nums 待搜索数组 + * @param l 起始索引 + * @param r 终止索引 + * @param target 目标数值 + * @return int 目标数值在数组中的索引 + */ + private int bs(int[] nums, int l, int r, int target) { + // 这里是“<=”因为 [l,r] 内所有值都是可能的目标 + while (l <= r) { + int mid = (l - r) / 2 + r; + if (nums[mid] == target) { + return mid; + } else if (nums[mid] > target) { + r = mid - 1; + } else { + l = mid + 1; + } + } + return -1; + } + + public static void main(String[] args) { + //Assert.assertArrayEquals(new int[]{1, 2}, new Solution2().twoSum(new int[]{2, 7, 11, 15}, 9)); + Assert.assertArrayEquals(new int[]{1, 3}, new Solution2().twoSum(new int[]{2, 3, 4}, 6)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution3.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution3.java" new file mode 100644 index 00000000..3cb95cf3 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution3.java" @@ -0,0 +1,43 @@ +package cn.lastwhisper.leetcode.array.两数之和_II_输入有序数组_167_简单; + +import org.junit.Assert; + +class Solution3 { + /** + * 题目地址:https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/ + * 编号:167 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:双指针(对撞指针) + * 这种思路的前提是数组有序 + * (1)定义两个初始指针 l,r 分别指向数组头尾。 + * (2)nums[l]+nums[r] > target,r-- + * (3)nums[l]+nums[r] < target,l++ + * (4)nums[l]+nums[r] == target,找到答案 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public int[] twoSum(int[] numbers, int target) { + if (numbers == null || numbers.length < 2) { + throw new IllegalArgumentException("Illegal argument numbers"); + } + int l = 0, r = numbers.length - 1; + // 这里不能等于,因为 index1 必须小于 index2 + while (l < r) { + if (numbers[l] + numbers[r] == target) { + return new int[]{l + 1, r + 1}; + } else if (numbers[l] + numbers[r] < target) { + l++; + } else { + r--; + } + } + throw new IllegalStateException("No results found"); + } + + public static void main(String[] args) { + Assert.assertArrayEquals(new int[]{1, 3}, new Solution3().twoSum(new int[]{2, 3, 4}, 6)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\344\275\277\346\225\260\347\273\204\345\224\257\344\270\200\347\232\204\346\234\200\345\260\217\345\242\236\351\207\217_945_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\344\275\277\346\225\260\347\273\204\345\224\257\344\270\200\347\232\204\346\234\200\345\260\217\345\242\236\351\207\217_945_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..42c50331 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\344\275\277\346\225\260\347\273\204\345\224\257\344\270\200\347\232\204\346\234\200\345\260\217\345\242\236\351\207\217_945_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,25 @@ +package cn.lastwhisper.leetcode.array.使数组唯一的最小增量_945_中等; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/minimum-increment-to-make-array-unique/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public int minIncrementForUnique(int[] A) { + + return 0; + } + + public static void main(String[] args) { + Assert.assertEquals(6, new Solution1().minIncrementForUnique(new int[]{3, 2, 1, 2, 1, 7})); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_26_Easy/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_26_Easy/Solution1.java" deleted file mode 100644 index 2a60a1ba..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_26_Easy/Solution1.java" +++ /dev/null @@ -1,32 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.删除排序数组中的重复项_26_Easy; - - -import java.util.Arrays; - -public class Solution1 { - public int removeDuplicates(int[] nums) { - if (nums == null || nums.length == 0) { - return 0; - } - int len = nums.length; - // 区间[0,...,pos]均为第一次出现元素 - int pos = 0; - // nums[0]肯定是第一次出现,所以i从1开始 - for (int i = 1; i < len; i++) { - // 如果第一(pos)个元素与第二(i)个元素不等(以此类推),说明是第一次出现。 - if (nums[pos] != nums[i]) { - pos++; - nums[pos] = nums[i]; - } - } - return pos + 1; - } - //以下为测试代码 - public static void main(String[] args) { - int[] arr = {0,0,1,1,2,3,4,4}; - System.out.println("原数组长度:" + arr.length); - int length = new Solution1().removeDuplicates(arr); - System.out.println("现数组长度:" + length); - System.out.println(Arrays.toString(arr)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_26_Easy/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_26_Easy/Solution2.java" deleted file mode 100644 index 2486d811..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_26_Easy/Solution2.java" +++ /dev/null @@ -1,33 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.删除排序数组中的重复项_26_Easy; - - -import java.util.Arrays; - -public class Solution2 { - - public int removeDuplicates(int[] nums) { - if (nums == null || nums.length == 0) { - return 0; - } - // 区间[0,...,pos]均为第一次出现元素 - int pos = 0; - // 数字可出现的次数 - int frequency = 1; - for (int n : nums) { - if (pos < frequency || n > nums[pos - frequency]) { - nums[pos++] = n; - } - } - return pos; - } - - //以下为测试代码 - public static void main(String[] args) { - int[] arr = {0, 0, 1, 1, 2, 3, 4, 4, 4, 4, 4}; - System.out.println("原数组长度:" + arr.length); - int length = new Solution2().removeDuplicates(arr); - System.out.println("现数组长度:" + length); - System.out.println(Arrays.toString(arr)); - } - -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_II_80_Medium/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_II_80_Medium/Solution1.java" deleted file mode 100644 index 6463cdb6..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_II_80_Medium/Solution1.java" +++ /dev/null @@ -1,35 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.删除排序数组中的重复项_II_80_Medium; - -public class Solution1 { - public int removeDuplicates(int[] nums) { - if (nums == null || nums.length == 0) { - return 0; - } - // 区间[0,...,pos]每个元素最多出现两次 - int pos = 0; - // 数字可出现的次数 - int frequency = 2; - for (int n : nums) { - if (pos < frequency || n > nums[pos - frequency]) { - nums[pos++] = n; - } - } - return pos; - } - - //以下为测试代码 - public static void main(String[] args) { - int[] arr = {0, 0, 1, 1, 1, 1, 2, 3, 3}; - System.out.println("原数组长度:" + arr.length); - int length = new Solution1().removeDuplicates(arr); - System.out.println("现数组长度:" + length); - for (int i = 0; i < length; i++) { - if (i != length - 1) { - System.out.print(arr[i] + ","); - } else { - System.out.print(arr[i]); - } - } - } - -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_Easy/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_Easy/Solution1.java" deleted file mode 100644 index 37e1a1e9..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_Easy/Solution1.java" +++ /dev/null @@ -1,50 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.合并两个有序数组_88_Easy; - -import java.util.Arrays; - -class Solution1 { - /** - * https://leetcode-cn.com/problems/merge-sorted-array/ - * 合并两个有序数组 - * 核心思路:归并排序,并的算法思路 - */ - public void merge(int[] nums1, int m, int[] nums2, int n) { - if (nums1 == null|| nums1.length == 0 || nums2 == null ) { - return; - } - int[] temp = new int[m + n]; - int p0 = 0, p1 = 0, index = 0; - while (p0 < m && p1 < n) { - int num1 = nums1[p0]; - int num2 = nums2[p1]; - if (num1 <= num2) { - temp[index++] = num1; - p0++; - } else { - temp[index++] = num2; - p1++; - } - } - while (p0 < m) { - temp[index++] = nums1[p0]; - p0++; - } - while (p1 < n) { - temp[index++] = nums2[p1]; - p1++; - } - - for (int i = 0; i < temp.length; i++) { - nums1[i] = temp[i]; - } - - } - - public static void main(String[] args) { - int[] nums1 = {1, 2, 3, 0, 0, 0}; - int[] nums2 = {2, 5, 6}; - new Solution1().merge(nums1, 3, nums2, 3); - System.out.println(Arrays.toString(nums1)); - } - -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_Easy/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_Easy/Solution2.java" deleted file mode 100644 index 66d1aaf7..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_Easy/Solution2.java" +++ /dev/null @@ -1,35 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.合并两个有序数组_88_Easy; - -import java.util.Arrays; - -class Solution2 { - /** - * https://leetcode-cn.com/problems/merge-sorted-array/ - * 核心思想:从后向前合并,不需要额外的空间 - * - */ - public void merge(int[] nums1, int m, int[] nums2, int n) { - if (nums1 == null || nums1.length == 0 || nums2 == null) { - return; - } - int p = m-- + n-- - 1;// num1和num2合并后的空间大小 - while (m >= 0 && n >= 0) { - nums1[p--] = nums1[m] > nums2[n] ? nums1[m--] : nums2[n--]; - } - // 如果nums1还没合并完,num2合并完了 - // 此时不用管,因为num1自身就是有序的,同时num1还是容器 - // 如果nums1合并完了,num2还没合并完 - while (n > 0) { - nums1[p--] = nums2[n--]; - } - - } - - public static void main(String[] args) { - int[] nums1 = {1, 2, 3, 0, 0, 0}; - int[] nums2 = {2, 5, 6}; - new Solution2().merge(nums1, 3, nums2, 3); - System.out.println(Arrays.toString(nums1)); - } - -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\244\232\346\225\260\345\205\203\347\264\240_169_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\244\232\346\225\260\345\205\203\347\264\240_169_\347\256\200\345\215\225/Solution1.java" deleted file mode 100644 index 71774712..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\244\232\346\225\260\345\205\203\347\264\240_169_\347\256\200\345\215\225/Solution1.java" +++ /dev/null @@ -1,38 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.多数元素_169_简单; - -import org.junit.Assert; - -import java.util.HashMap; -import java.util.Map; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/majority-element/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路:hash表 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(n) - */ - public int majorityElement(int[] nums) { - int half = nums.length / 2; - Map map = new HashMap<>(); - for (int num : nums) { - Integer count = map.get(num); - count = count == null ? 1 : ++count; - map.put(num, count); - if (count > half) { - return num; - } - } - return 0; - } - - public static void main(String[] args) { - //Assert.assertEquals(3, new Solution1().majorityElement(new int[]{3, 2, 3})); - Assert.assertEquals(2, new Solution1().majorityElement(new int[]{2, 2, 1, 1, 1, 2, 2})); - - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\244\232\346\225\260\345\205\203\347\264\240_169_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\244\232\346\225\260\345\205\203\347\264\240_169_\347\256\200\345\215\225/Solution2.java" deleted file mode 100644 index 735afaaf..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\345\244\232\346\225\260\345\205\203\347\264\240_169_\347\256\200\345\215\225/Solution2.java" +++ /dev/null @@ -1,32 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.多数元素_169_简单; - -import org.junit.Assert; - -class Solution2 { - /** - * 题目地址:https://leetcode-cn.com/problems/majority-element/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路:摩尔投票法 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(1) - */ - public int majorityElement(int[] nums) { - int candidate = 0; - int count = 0; - for (int num : nums) { - if (count == 0) { - candidate = num; - } - count += candidate == num ? 1 : -1; - } - return candidate; - } - - public static void main(String[] args) { - Assert.assertEquals(3, new Solution2().majorityElement(new int[]{3, 2, 3})); - Assert.assertEquals(2, new Solution2().majorityElement(new int[]{2, 2, 1, 1, 1, 2, 2})); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_Medium/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_Medium/Solution1.java" deleted file mode 100644 index 14314ba6..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_Medium/Solution1.java" +++ /dev/null @@ -1,51 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.数组中的第K个最大元素_215_Medium; - -class Solution1 { - /** - * 利用快排partition思想,将pivot放置在了其正确的位置上的性质 - */ - public int findKthLargest(int[] nums, int k) { - return partition(nums, 0, nums.length - 1, nums.length - k); - } - - public int partition(int[] nums, int leftBound, int rightBound, int k) { - int i = leftBound; - int pivot = nums[leftBound]; - int j = rightBound - 1; - while (i <= j) { - while (i <= j && nums[i] <= pivot) { - i++; - } - while (i <= j && nums[j] > pivot) { - j--; - } - if (i < j) { - swap(nums, i, j); - } - } - //swap(nums, i, rightBound); - if (i == k) { - return pivot; - } else if (i > k) { - return partition(nums, leftBound, i - 1, k); - } else { - return partition(nums, i + 1, rightBound, k); - } - } - - public void swap(int[] arr, int i, int j) { - int temp = arr[j]; - arr[j] = arr[i]; - arr[i] = temp; - } - - public static void main(String[] args) { - int[] arr = {3, 2, 1, 5, 6, 4}; - int k = 2; - //int[] arr = {3, 2, 3, 1, 2, 4, 5, 5, 6}; - //int k = 4; - - int kthLargest = new Solution1().findKthLargest(arr, k); - System.out.println(kthLargest); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_Medium/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_Medium/Solution2.java" deleted file mode 100644 index b5e481a7..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_Medium/Solution2.java" +++ /dev/null @@ -1,36 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.数组中的第K个最大元素_215_Medium; - -class Solution2 { - /** - * 利用堆排序思想 - * O(n)桶排思想 - */ - public int findKthLargest(int[] nums, int k) { - int max = Integer.MIN_VALUE, min = Integer.MAX_VALUE; - for (int i : nums) { - max = Math.max(max, i); - min = Math.min(min, i); - } - int n = max - min; - int[] bucket = new int[n + 1]; - for (int i = 0; i < nums.length; i++) { - int tmp = nums[i] - min; - bucket[tmp]++; - } - for (int i = n; i >= 0; i--) { - if (bucket[i] > 0) - k -= bucket[i]; - if (k <= 0) - return i + min; - } - return 0; - } - - - public static void main(String[] args) { - int[] arr = {3, 2, 3, 1, 2, 4, 5, 5, 6}; - int k = 4; - int kthLargest = new Solution2().findKthLargest(arr, k); - System.out.println(kthLargest); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_242_Easy/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_242_Easy/Solution1.java" deleted file mode 100644 index abd8f159..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_242_Easy/Solution1.java" +++ /dev/null @@ -1,43 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.有效的字母异位词_242_Easy; - -import java.util.HashMap; -import java.util.Map; - -class Solution1 { - public boolean isAnagram(String s, String t) { - char[] sChar = s.toCharArray(); - char[] tChar = t.toCharArray(); - HashMap map = new HashMap<>(); - for (int i = 0; i < sChar.length; i++) { - Integer num = map.get(sChar[i]); - if (num == null) { - map.put(sChar[i], 1); - } else { - map.put(sChar[i], ++num); - } - } - - for (int i = 0; i < tChar.length; i++) { - Integer num = map.get(tChar[i]); - if (num == null) { - return false; - } else { - map.put(tChar[i], --num); - } - } - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() != 0) { - return false; - } - } - return true; - } - - public static void main(String[] args) { - //String s = "anagram", t = "nagaram"; - String s = "rat", t = "car"; - - System.out.println(new Solution1().isAnagram(s, t)); - } - -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_242_Easy/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_242_Easy/Solution2.java" deleted file mode 100644 index efe5b09d..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_242_Easy/Solution2.java" +++ /dev/null @@ -1,39 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.有效的字母异位词_242_Easy; - -class Solution2 { - /** - * https://leetcode-cn.com/problems/valid-anagram/submissions/ - * hash - * 时间复杂度:O(n) - * 空间复杂度:O(1) - */ - public boolean isAnagram(String s, String t) { - if (s.length() != t.length()) { - return false; - } - char[] sChar = s.toCharArray(); - char[] tChar = t.toCharArray(); - byte[] freq = new byte[256]; - for (int i = 0; i < sChar.length; i++) { - freq[sChar[i]]++; - } - - for (int i = 0; i < tChar.length; i++) { - freq[tChar[i]]--; - } - for (int i = 0; i < freq.length; i++) { - if (freq[i] != 0) { - return false; - } - } - return true; - } - - public static void main(String[] args) { - String s = "anagram", t = "nagaram"; - //String s = "rat", t = "car"; - - System.out.println(new Solution2().isAnagram(s, t)); - } - -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\347\247\273\345\212\250\351\233\266_283_Easy/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\347\247\273\345\212\250\351\233\266_283_Easy/Solution1.java" deleted file mode 100644 index a6265d95..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\347\247\273\345\212\250\351\233\266_283_Easy/Solution1.java" +++ /dev/null @@ -1,34 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.移动零_283_Easy; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class Solution1 { - //时间复杂度:O(n) - //空间复杂度:O(n) - public void moveZeroes(int[] nums) { - // 缓存非0元素 - List nonZeroElements = new ArrayList<>(); - // 找出非0元素并将它缓存进nonZeroElements - for (int i = 0; i < nums.length; i++) { - if (nums[i] != 0) { - nonZeroElements.add(nums[i]); - } - } - // 将非0元素放入原数组中 - for (int i = 0; i < nonZeroElements.size(); i++) { - nums[i] = nonZeroElements.get(i); - } - // 将原数组剩余的位置放置为0 - for (int i = nonZeroElements.size(); i < nums.length; i++) { - nums[i] = 0; - } - } - //以下为测试代码 - public static void main(String[] args) { - int[] arr = {0, 1, 0, 3, 12}; - new Solution1().moveZeroes(arr); - System.out.println(Arrays.toString(arr)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\347\247\273\345\212\250\351\233\266_283_Easy/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\347\247\273\345\212\250\351\233\266_283_Easy/Solution2.java" deleted file mode 100644 index d7910c5a..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\347\247\273\345\212\250\351\233\266_283_Easy/Solution2.java" +++ /dev/null @@ -1,29 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.移动零_283_Easy; - - -import java.util.Arrays; - -public class Solution2 { - public void moveZeroes(int[] nums) { - // k保证从[0,...,k)均为非零元素 - int k = 0; - // 遍历到第i个元素后,保证[0,...,i]中所有非零元素, - // 都按顺序排列在[0,...,k)中 - for (int i = 0; i < nums.length; i++) { - if (nums[i] != 0) { - nums[k] = nums[i]; - k++; - } - } - // 同时保证[k,...,nums.length]中均为零元素 - for (int i = k; i < nums.length; i++) { - nums[i] = 0; - } - } - //以下为测试代码 - public static void main(String[] args) { - int[] arr = {0, 1, 0, 3, 12}; - new Solution2().moveZeroes(arr); - System.out.println(Arrays.toString(arr)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\347\247\273\345\212\250\351\233\266_283_Easy/Solution3.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\347\247\273\345\212\250\351\233\266_283_Easy/Solution3.java" deleted file mode 100644 index 944a5029..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\347\247\273\345\212\250\351\233\266_283_Easy/Solution3.java" +++ /dev/null @@ -1,34 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.移动零_283_Easy; - - -import java.util.Arrays; - -public class Solution3 { - public void moveZeroes(int[] nums) { - // k保证从[0,...,k)均为非零元素 - int k = 0; - // temp用于交换时暂存数据 - int temp = 0; - // 遍历到第i个元素后,保证[0,...,i]中所有非零元素,都按顺序排列在[0,...,k)中 - // 同时保证[k,...,i]中均为零元素 - for (int i = 0; i < nums.length; i++) { - if (nums[i] != 0) { - // 防止全为非零元素 - if (i != k) { - temp = nums[k]; - nums[k] = nums[i]; - nums[i] = temp; - k++; - } else { - k++; - } - } - } - } - //以下为测试代码 - public static void main(String[] args) { - int[] arr = {0, 1, 0, 3, 12}; - new Solution3().moveZeroes(arr); - System.out.println(Arrays.toString(arr)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\347\247\273\351\231\244\345\205\203\347\264\240_27_Easy/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\347\247\273\351\231\244\345\205\203\347\264\240_27_Easy/Solution1.java" deleted file mode 100644 index bfcb01ae..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\347\247\273\351\231\244\345\205\203\347\264\240_27_Easy/Solution1.java" +++ /dev/null @@ -1,31 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.移除元素_27_Easy; - -import java.util.Arrays; - -public class Solution1 { - public int removeElement(int[] nums, int val) { - if (nums == null || nums.length == 0) { - return 0; - } - int len = nums.length; - // 区间[0,...,pos)均为不等于val的元素 - int pos = 0; - // nums中不等于val的值,按顺序移动到nums数组的前面。 - for (int i = 0; i < len; i++) { - if (nums[i] != val) { - nums[pos] = nums[i]; - pos++; - } - } - return pos; - } - - //以下为测试代码 - public static void main(String[] args) { - int[] arr = {0, 1, 2, 2, 3, 0, 4, 2}; - System.out.println("原数组长度:" + arr.length); - int length = new Solution1().removeElement(arr, 2); - System.out.println("现数组长度:" + length); - System.out.println(Arrays.toString(arr)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\350\236\272\346\227\213\347\237\251\351\230\265_54_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\350\236\272\346\227\213\347\237\251\351\230\265_54_\344\270\255\347\255\211/Solution1.java" deleted file mode 100644 index 669ed483..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\350\236\272\346\227\213\347\237\251\351\230\265_54_\344\270\255\347\255\211/Solution1.java" +++ /dev/null @@ -1,54 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.螺旋矩阵_54_中等; - -import java.util.ArrayList; -import java.util.List; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/spiral-matrix/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路: - * ------------------------------------------------------------------- - * 时间复杂度:O(n^2) - * 空间复杂度:O(n^2) - */ - public List spiralOrder(int[][] matrix) { - if (matrix == null || matrix.length == 0) return new ArrayList<>(); - List result = new ArrayList<>(matrix.length * matrix[0].length); - // nowColumn当前所在列、totalColumn总列数、nowRow当前所在行、totalRow总行数 - int nowColumn = 0, totalColumn = matrix[0].length - 1, nowRow = 0, totalRow = matrix.length - 1; - // 顺时针遍历 - while (nowColumn <= totalColumn && nowRow <= totalRow) { - //只有一列,不需要从左到右 - for (int i = nowColumn; i <= totalColumn; i++) {//第一步 从左到右 - result.add(matrix[nowRow][i]); - } - //只有一行,不需要从上到下 - for (int i = nowRow + 1; i <= totalRow; i++) {//第二步 从上到下 - result.add(matrix[i][totalColumn]); - } - if (nowRow != totalRow) {//同行,不需要从右向左遍历 - for (int i = totalColumn - 1; i >= nowColumn; i--) {//第三步 从右向左 - result.add(matrix[totalRow][i]); - } - } - if (nowColumn != totalColumn) {//同列,不需要从下到上遍历 - for (int i = totalRow - 1; i > nowRow; i--) {// 第四步 从下到上 - result.add(matrix[i][nowColumn]); - } - } - nowColumn++; - nowRow++; - totalColumn--; - totalRow--; - } - return result; - } - - public static void main(String[] args) { - int[][] matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; - System.out.println(new Solution1().spiralOrder(matrix)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\351\242\234\350\211\262\345\210\206\347\261\273_75_Medium/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\351\242\234\350\211\262\345\210\206\347\261\273_75_Medium/Solution1.java" deleted file mode 100644 index 32bccc0e..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\351\242\234\350\211\262\345\210\206\347\261\273_75_Medium/Solution1.java" +++ /dev/null @@ -1,57 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.颜色分类_75_Medium; - -import java.util.Arrays; - -public class Solution1 { - - /** - * 题目:https://leetcode-cn.com/problems/sort-colors/ - * 计数排序 - * 核心思想:统计每一个数出现的频率 - * 时间复杂度:O(n) - * 时间复杂度:O(1) - */ - public void sortColors(int[] nums) { - if (nums == null || nums.length == 0) { - return; - } - int[] count = new int[3]; - for (int num : nums) { - count[num]++; - } - - for (int i = 0; i < count[0]; i++) { - nums[i] = 0; - } - for (int i = count[0]; i < count[0] + count[1]; i++) { - nums[i] = 1; - } - for (int i = count[0] + count[1]; i < count[0] + count[1] + count[2]; i++) { - nums[i] = 2; - } - } - - // 优化 - public void sortColors1(int[] nums) { - if (nums == null || nums.length == 0) { - return; - } - int[] count = new int[3]; - for (int num : nums) { - count[num]++; - } - int index = 0; - for (int i = 0; i < 3; i++) { - int itemCount = count[i]; - while (itemCount-- > 0) { - nums[index++] = i; - } - } - } - - public static void main(String[] args) { - int[] arr = {2, 0, 2, 1, 1, 0}; - new Solution1().sortColors(arr); - System.out.println(Arrays.toString(arr)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\351\242\234\350\211\262\345\210\206\347\261\273_75_Medium/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\351\242\234\350\211\262\345\210\206\347\261\273_75_Medium/Solution2.java" deleted file mode 100644 index 7ea3427d..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\205\266\344\273\226/\351\242\234\350\211\262\345\210\206\347\261\273_75_Medium/Solution2.java" +++ /dev/null @@ -1,45 +0,0 @@ -package cn.lastwhisper.leetcode.array.其他.颜色分类_75_Medium; - -import java.util.Arrays; - -/** - * @author lastwhisper - */ -public class Solution2 { - - /** - * 题目:https://leetcode-cn.com/problems/sort-colors/ - * 三路快速排序的思想,对整个数组只遍历了一遍 - * 时间复杂度: O(n) - * 空间复杂度: O(1) - */ - public void sortColors(int[] nums) { - if (nums == null || nums.length == 0) { - return; - } - int zero = 0, two = nums.length; - for (int i = 0; i < two; ) { // 小于two与i不加相对应 - int num = nums[i]; - if (num == 1) { - i++; - } else if (num == 0) { - swap(nums, zero++, i++); - } else if (num == 2) { - swap(nums, --two, i);// i不加 - } - } - } - - public void swap(int[] arr, int i, int j) { - int temp = arr[j]; - arr[j] = arr[i]; - arr[i] = temp; - } - - public static void main(String[] args) { - int[] arr = {2, 0, 2, 1, 1, 0}; - new Solution2().sortColors(arr); - System.out.println(Arrays.toString(arr)); - } - -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_26_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_26_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..3dab2b3b --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_26_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,41 @@ +package cn.lastwhisper.leetcode.array.删除排序数组中的重复项_26_简单; + + +import org.junit.Assert; + +public class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/ + * 编号:26 + * ------------------------------------------------------------------- + * 思考: + * 数据特征:从小到大有序 + * ------------------------------------------------------------------- + * 思路: + * 双指针 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public int removeDuplicates(int[] nums) { + // 特判 + if (nums == null || nums.length == 0) { + return 0; + } + // 区间[0,...,pos]均为第一次出现元素 + int pos = 0; + + for (int i = 1; i < nums.length; i++) { + if (nums[pos] != nums[i]) { + nums[++pos] = nums[i]; + } + } + return pos + 1; + } + + //以下为测试代码 + public static void main(String[] args) { + int[] nums = {0, 0, 1, 1, 2, 3, 4, 4}; + Assert.assertEquals(5, new Solution1().removeDuplicates(nums)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_26_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_26_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..8e1ec9fb --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_26_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,30 @@ +package cn.lastwhisper.leetcode.array.删除排序数组中的重复项_26_简单; + + +import org.junit.Assert; + +public class Solution2 { + + public int removeDuplicates(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + // 区间[0,...,pos]均为第一次出现元素 + int pos = 0; + // 数字可出现的次数 + int frequency = 1; + for (int n : nums) { + if (pos < frequency || n > nums[pos - frequency]) { + nums[pos++] = n; + } + } + return pos; + } + + //以下为测试代码 + public static void main(String[] args) { + int[] nums = {0, 0, 1, 1, 2, 3, 4, 4}; + Assert.assertEquals(5, new Solution2().removeDuplicates(nums)); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_II_80_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_II_80_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..d8382336 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_II_80_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,40 @@ +package cn.lastwhisper.leetcode.array.删除排序数组中的重复项_II_80_中等; + +import org.junit.Assert; + +public class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array-ii/ + * 编号:80 + * ------------------------------------------------------------------- + * 思考: + * 数据特征:从小到大有序 + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public int removeDuplicates(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + // 区间[0,...,pos]每个元素最多出现两次 + int pos = 0; + // 数字可出现的次数 + int frequency = 2; + for (int num : nums) { + if (pos < frequency || num > nums[pos - frequency]) { + nums[pos++] = num; + } + } + return pos; + } + + //以下为测试代码 + public static void main(String[] args) { + int[] nums = {0, 0, 1, 1, 1, 1, 2, 3, 3}; + Assert.assertEquals(7, new Solution1().removeDuplicates(nums)); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_II_80_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_II_80_\344\270\255\347\255\211/Solution2.java" new file mode 100644 index 00000000..0d8258b5 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271_II_80_\344\270\255\347\255\211/Solution2.java" @@ -0,0 +1,49 @@ +package cn.lastwhisper.leetcode.array.删除排序数组中的重复项_II_80_中等; + +import org.junit.Assert; + +public class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array-ii/ + * 编号:80 + * ------------------------------------------------------------------- + * 思考: + * 数据特征:从小到大有序 + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public int removeDuplicates(int[] nums) { + // Initialize the counter and the second pointer. + int j = 1, count = 1; + + // Start from the second element of the array and process + // elements one by one. + for (int i = 1; i < nums.length; i++) { + + // If the current element is a duplicate, increment the count. + if (nums[i] == nums[i - 1]) { + count++; + } else { + // Reset the count since we encountered a different element + // than the previous one. + count = 1; + } + // For a count <= 2, we copy the element over thus + // overwriting the element at index "j" in the array + if (count <= 2) { + nums[j++] = nums[i]; + } + } + return j; + } + + //以下为测试代码 + public static void main(String[] args) { + int[] nums = {0, 0, 1, 1, 1, 1, 2, 3, 3}; + Assert.assertEquals(7, new Solution2().removeDuplicates(nums)); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\214\272\351\227\264\345\220\210\345\271\266/\347\237\251\345\275\242\351\207\215\345\217\240_836_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\214\272\351\227\264\345\220\210\345\271\266/\347\237\251\345\275\242\351\207\215\345\217\240_836_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..3a74c52d --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\214\272\351\227\264\345\220\210\345\271\266/\347\237\251\345\275\242\351\207\215\345\217\240_836_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,30 @@ +package cn.lastwhisper.leetcode.array.区间合并.矩形重叠_836_简单; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/rectangle-overlap/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 两个矩阵的重叠是无限的,但是不重叠是有限的 + * 检查位置 + * ------------------------------------------------------------------- + * 时间复杂度:O(1) + * 空间复杂度:O(1) + */ + public boolean isRectangleOverlap(int[] rec1, int[] rec2) { + // 矩阵投影X轴,矩阵1在矩阵2左侧 或 矩阵1在矩阵2右侧 + boolean x_overlap = !(rec1[2] <= rec2[0] || rec2[2] <= rec1[0]); + // 矩阵投影y轴,矩阵1在矩阵2上侧 或 矩阵1在矩阵2下侧 + boolean y_overlap = !(rec1[3] <= rec2[1] || rec2[3] <= rec1[1]); + return x_overlap && y_overlap; + } + + public static void main(String[] args) { + int[] rec1 = {0, 0, 2, 2}, rec2 = {1, 1, 3, 3}; + Assert.assertTrue(new Solution1().isRectangleOverlap(rec1, rec2)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\214\272\351\227\264\345\220\210\345\271\266/\347\237\251\345\275\242\351\207\215\345\217\240_836_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\214\272\351\227\264\345\220\210\345\271\266/\347\237\251\345\275\242\351\207\215\345\217\240_836_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..8107d63e --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\214\272\351\227\264\345\220\210\345\271\266/\347\237\251\345\275\242\351\207\215\345\217\240_836_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,28 @@ +package cn.lastwhisper.leetcode.array.区间合并.矩形重叠_836_简单; + +import org.junit.Assert; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/rectangle-overlap/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 检查重叠的矩阵区域 + * ------------------------------------------------------------------- + * 时间复杂度:O(1) + * 空间复杂度:O(1) + */ + public boolean isRectangleOverlap(int[] rec1, int[] rec2) { + //相交矩阵的水平边 + return (Math.min(rec1[2], rec2[2]) > Math.max(rec1[0], rec2[0]) && + //相交矩阵的垂直边 + Math.min(rec1[3], rec2[3]) > Math.max(rec1[1], rec2[1])); + } + + public static void main(String[] args) { + int[] rec1 = {0, 0, 2, 2}, rec2 = {1, 1, 3, 3}; + Assert.assertTrue(new Solution2().isRectangleOverlap(rec1, rec2)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\215\241\347\211\214\345\210\206\347\273\204_914_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\215\241\347\211\214\345\210\206\347\273\204_914_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..26542e85 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\215\241\347\211\214\345\210\206\347\273\204_914_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,56 @@ +package cn.lastwhisper.leetcode.array.卡牌分组_914_简单; + +import org.junit.Assert; + +import java.util.Arrays; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/x-of-a-kind-in-a-deck-of-cards/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:先将数组排序,对数组进行步长为2~len/2进行分组 + * ------------------------------------------------------------------- + * 时间复杂度:O(n^2) + * 空间复杂度:O(1) + */ + public boolean hasGroupsSizeX(int[] deck) { + // 特判 + if (deck == null || deck.length <= 1) { + return false; + } + if (deck.length == 2) { + return true; + } + Arrays.sort(deck); + for (int i = 2; i <= deck.length / 2; i++) { + if (deck.length % i != 0) {//deck不能整分为i组 + continue; + } + boolean flag = true; + //步长为2~len/2进行分组 + for (int len = 0, start = 0, end = i - 1; len < deck.length; end += i, start += i, len += i) { + for (int j = start; j < end; j++) { + if (deck[j] != deck[j + 1]) { + flag = false; + break; + } + } + if (!flag) { + break; + } + } + if (flag) return true; + } + return false; + } + + public static void main(String[] args) { + Assert.assertTrue(new Solution1().hasGroupsSizeX(new int[]{0, 0, 0, 0, 0, 1, 1, 1, 1, 1})); + Assert.assertTrue(new Solution1().hasGroupsSizeX(new int[]{1, 1})); + Assert.assertFalse(new Solution1().hasGroupsSizeX(new int[]{1, 1, 1, 2, 2, 2, 3, 3})); + //Assert.assertTrue(new Solution1().hasGroupsSizeX(new int[]{0, 0, 0, 1, 1, 1, 2, 2, 2})); + //Assert.assertTrue(new Solution1().hasGroupsSizeX(new int[]{1, 2, 3, 4, 4, 3, 2, 1})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\215\241\347\211\214\345\210\206\347\273\204_914_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\215\241\347\211\214\345\210\206\347\273\204_914_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..8338cd8c --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\215\241\347\211\214\345\210\206\347\273\204_914_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,57 @@ +package cn.lastwhisper.leetcode.array.卡牌分组_914_简单; + +import org.junit.Assert; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/x-of-a-kind-in-a-deck-of-cards/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:统计每个数出现的次数,次数的最大公约数大于1即可 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public boolean hasGroupsSizeX(int[] deck) { + // 特判 + if (deck == null || deck.length <= 1) { + return false; + } + int[] freq = new int[10000]; + for (int num : deck) { + freq[num]++; + } + + int x = freq[deck[0]]; + for (int num : freq) { + // 1个数不能分组 + if (num == 1) { + return false; + } + if (num > 1) { + x = gcd(x, num); + // 最小公倍数是1说明也不能按同样的值分组 + if (x == 1) { + return false; + } + } + } + return true; + } + + private int gcd(int a, int b) { + if (b == 0) { + return a; + } + return gcd(b, a % b); + } + + public static void main(String[] args) { + Assert.assertTrue(new Solution2().hasGroupsSizeX(new int[]{0, 0, 0, 0, 0, 1, 1, 1, 1, 1})); + Assert.assertTrue(new Solution2().hasGroupsSizeX(new int[]{1, 1})); + Assert.assertFalse(new Solution2().hasGroupsSizeX(new int[]{1, 1, 1, 2, 2, 2, 3, 3})); + //Assert.assertTrue(new Solution2().hasGroupsSizeX(new int[]{0, 0, 0, 1, 1, 1, 2, 2, 2})); + //Assert.assertTrue(new Solution2().hasGroupsSizeX(new int[]{1, 2, 3, 4, 4, 3, 2, 1})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262_344_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262_344_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..ff909dd9 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262_344_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,32 @@ +package cn.lastwhisper.leetcode.array.反转字符串_344_简单; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/reverse-string/ + * 编号:344 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:对撞指针交换元素 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public void reverseString(char[] s) { + int l = 0, r = s.length - 1; + while (l < r) { + char c = s[l]; + s[l] = s[r]; + s[r] = c; + l++; r--; + } + } + + public static void main(String[] args) { + char[] s = {'h', 'e', 'l', 'l', 'o'}; + new Solution1().reverseString(s); + Assert.assertArrayEquals(new char[]{'o', 'l', 'l', 'e', 'h'}, s); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\205\203\351\237\263\345\255\227\346\257\215_345_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\205\203\351\237\263\345\255\227\346\257\215_345_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..7c26f183 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\205\203\351\237\263\345\255\227\346\257\215_345_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,48 @@ +package cn.lastwhisper.leetcode.array.反转字符串中的元音字母_345_简单; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/reverse-vowels-of-a-string/ + * 编号:345 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:对撞指针条件交换元素 + * 元音字母:a,e,i,o,u 大小写 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ + public String reverseVowels(String s) { + int l = 0, r = s.length() - 1; + char[] chars = s.toCharArray(); + while (l < r) { + while (l < r && !valid(s.charAt(l))) { + l++; + } + while (l < r && !valid(s.charAt(r))) { + r--; + } + if (l < r) {// 需要判断 + char c = chars[l]; + chars[l] = chars[r]; + chars[r] = c; + l++; + r--; + } + } + return new String(chars); + } + + private boolean valid(char c) { + return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || + c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U'; + } + + public static void main(String[] args) { + Assert.assertEquals("holle", new Solution1().reverseVowels("hello")); + Assert.assertEquals("leotcede", new Solution1().reverseVowels("leetcode")); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..bdba81f3 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,53 @@ +package cn.lastwhisper.leetcode.array.合并两个有序数组_88_简单; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/merge-sorted-array/ + * 编号:88 + * ------------------------------------------------------------------- + * 思考: + * 数据特征:数组有序 + * ------------------------------------------------------------------- + * 思路: + * 归并排序,归的过程。 + * (1)从前到后比较(找小)复制只用 nums1,需要移动 nums1 中的元素,不如创建中间数据 + * (2)从后到前比较(找大)复制只用 nums1,无需移动 nums1 中的元素 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ + public void merge(int[] nums1, int m, int[] nums2, int n) { + // 暂存 nums1 和 nums2 的数据 + int[] temp = new int[m + n]; + int p1 = 0, p2 = 0, t = 0; + // 将 nums1 和 nums2 有序复制到 temp,直到某个数组复制完 + while (p1 < m && p2 < n) { + if (nums1[p1] > nums2[p2]) { + temp[t] = nums2[p2++]; + } else { + temp[t] = nums1[p1++]; + } + t++; + } + // 将 nums1 剩余元素复制到 temp + while (p1 < m) { + temp[t++] = nums1[p1++]; + } + // 将 nums2 剩余元素复制到 temp + while (p2 < n) { + temp[t++] = nums2[p2++]; + } + // 将 temp 所有元素复制到 nums1 + System.arraycopy(temp, 0, nums1, 0, temp.length); + } + + public static void main(String[] args) { + int[] nums1 = {1, 2, 3, 0, 0, 0}, nums2 = {2, 5, 6}; + int m = 3, n = 3; + new Solution1().merge(nums1, m, nums2, n); + + Assert.assertArrayEquals(new int[]{1, 2, 2, 3, 5, 6}, nums1); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..72a5f842 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,39 @@ +package cn.lastwhisper.leetcode.array.合并两个有序数组_88_简单; + +import org.junit.Assert; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/merge-sorted-array/ + * 编号:88 + * ------------------------------------------------------------------- + * 思考: + * 数据特征:数组有序 + * ------------------------------------------------------------------- + * 思路: + * 从后向前复制 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public void merge(int[] nums1, int m, int[] nums2, int n) { + int p1 = m - 1, p2 = n - 1, total = m + n - 1; + // 将 num1 和 num2 中最大的复制到 nums1的最后面 + while (p1 >= 0 && p2 >= 0) { + nums1[total--] = nums1[p1] > nums2[p2] ? nums1[p1--] : nums2[p2--]; + } + // 如果 num1 还没复制完,不用管,因为num1自身就是有序的 + // 如果 num2 还没复制完,把剩余复制进去 + while (p2 >= 0) { + nums1[total--] = nums2[p2--]; + } + } + + public static void main(String[] args) { + int[] nums1 = {1, 2, 3, 0, 0, 0}, nums2 = {2, 5, 6}; + int m = 3, n = 3; + new Solution2().merge(nums1, m, nums2, n); + + Assert.assertArrayEquals(new int[]{1, 2, 2, 3, 5, 6}, nums1); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\244\232\346\225\260\345\205\203\347\264\240_169_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\244\232\346\225\260\345\205\203\347\264\240_169_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..11993f9d --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\244\232\346\225\260\345\205\203\347\264\240_169_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,38 @@ +package cn.lastwhisper.leetcode.array.多数元素_169_简单; + +import org.junit.Assert; + +import java.util.HashMap; +import java.util.Map; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/majority-element/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:hash表 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ + public int majorityElement(int[] nums) { + int half = nums.length / 2; + Map map = new HashMap<>(); + for (int num : nums) { + Integer count = map.get(num); + count = count == null ? 1 : ++count; + map.put(num, count); + if (count > half) { + return num; + } + } + return 0; + } + + public static void main(String[] args) { + //Assert.assertEquals(3, new Solution1().majorityElement(new int[]{3, 2, 3})); + Assert.assertEquals(2, new Solution1().majorityElement(new int[]{2, 2, 1, 1, 1, 2, 2})); + + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\244\232\346\225\260\345\205\203\347\264\240_169_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\244\232\346\225\260\345\205\203\347\264\240_169_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..791be615 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\244\232\346\225\260\345\205\203\347\264\240_169_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,32 @@ +package cn.lastwhisper.leetcode.array.多数元素_169_简单; + +import org.junit.Assert; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/majority-element/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:摩尔投票法 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public int majorityElement(int[] nums) { + int candidate = 0; + int count = 0; + for (int num : nums) { + if (count == 0) { + candidate = num; + } + count += candidate == num ? 1 : -1; + } + return candidate; + } + + public static void main(String[] args) { + Assert.assertEquals(3, new Solution2().majorityElement(new int[]{3, 2, 3})); + Assert.assertEquals(2, new Solution2().majorityElement(new int[]{2, 2, 1, 1, 1, 2, 2})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_Easy/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_Easy/Solution1.java" deleted file mode 100644 index f8d1c128..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_Easy/Solution1.java" +++ /dev/null @@ -1,34 +0,0 @@ -package cn.lastwhisper.leetcode.array.对撞指针.两数之和_II_输入有序数组_167_Easy; - -/** - * https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/ - * @author lastwhisper - */ -public class Solution1 { - /** - * https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/ - * 暴力解法,找出所有组合进行对比 - * 时间复杂度:O(n^2) - * 空间复杂度:O(1) - */ - public int[] twoSum(int[] numbers, int target) { - if (numbers == null || numbers.length < 2) { - return null; - } - int len = numbers.length; - for (int i = 0; i < len; i++) { - for (int j = 1; j < len; j++) { - if ((i != j) && (numbers[i] + numbers[j]) == target) { - return new int[]{i + 1, j + 1}; - } - } - } - return null; - } - - public static void main(String[] args) { - int[] arr = {0, 0, 3, 4}; - int[] index = new Solution1().twoSum(arr, 0); - System.out.printf("[%s,%s]", index[0], index[1]); - } -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_Easy/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_Easy/Solution2.java" deleted file mode 100644 index 9095a772..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_Easy/Solution2.java" +++ /dev/null @@ -1,46 +0,0 @@ -package cn.lastwhisper.leetcode.array.对撞指针.两数之和_II_输入有序数组_167_Easy; - -/** - * @author lastwhisper - */ -public class Solution2 { - - /** - * https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/ - * 将差值放入二分查找剩余数组 - * 时间复杂度:O(nlogn) - * 空间复杂度:O(1) - */ - public int[] twoSum(int[] numbers, int target) { - if (numbers == null || numbers.length < 2) { - return null; - } - for (int index1 = 0; index1 < numbers.length; index1++) { - int differ = target - numbers[index1]; - int index2 = binarySearch(numbers, index1 + 1, numbers.length - 1, differ); - if (index2 != -1) { - return new int[]{index1 + 1, index2 + 1}; - } - } - throw new IllegalStateException("The input has no solution"); - } - - public int binarySearch(int[] arr, int l, int r, int target) { - while (l <= r) { - int mid = l + (r - l) / 2; - if (arr[mid] == target) - return mid; - if (target > arr[mid]) - l = mid + 1; - else - r = mid - 1; - } - return -1; - } - - public static void main(String[] args) { - int[] arr = {1, 2, 3, 4, 4, 9, 56, 90}; - int[] index = new Solution2().twoSum(arr, 8); - System.out.printf("[%s,%s]", index[0], index[1]); - } -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_Easy/Solution3.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_Easy/Solution3.java" deleted file mode 100644 index 2ce5b047..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_Easy/Solution3.java" +++ /dev/null @@ -1,38 +0,0 @@ -package cn.lastwhisper.leetcode.array.对撞指针.两数之和_II_输入有序数组_167_Easy; - -import java.util.Arrays; - -/** - * @author lastwhisper - */ -public class Solution3 { - /** - * https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/ - * 对撞指针(也叫双索引,前提数组有序) - * 时间复杂度:O(n) - * 空间复杂度:O(1) - */ - public int[] twoSum(int[] numbers, int target) { - if (numbers == null || numbers.length < 2) { - return null; - } - int l = 0, r = numbers.length - 1; - while (l < r) { - int left = numbers[l]; - int right = numbers[r]; - if ((left + right) == target) { - return new int[]{l + 1, r + 1}; - } else if ((left + right) > target) { - r--; - } else { - l++; - } - } - return null; - } - - public static void main(String[] args) { - System.out.println(Arrays.toString(new Solution3().twoSum(new int[]{0, 0, 3, 4}, 0))); - System.out.println(Arrays.toString(new Solution3().twoSum(new int[]{1, 7, 17, 2, 6, 3, 14}, 20))); - } -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262_344_Easy/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262_344_Easy/Solution1.java" deleted file mode 100644 index 7301f5c8..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262_344_Easy/Solution1.java" +++ /dev/null @@ -1,31 +0,0 @@ -package cn.lastwhisper.leetcode.array.对撞指针.反转字符串_344_Easy; - -/** - * @author lastwhisper - */ -public class Solution1 { - /** - * https://leetcode-cn.com/problems/reverse-string/ - * 指针对撞 - * 时间复杂度:O(n) - * 空间复杂度:O(1) - */ - public void reverseString(char[] s) { - int l = 0, r = s.length - 1; - while (l < r) { - char temp = s[l]; - s[l] = s[r]; - s[r] = temp; - l++; - r--; - } - } - - public static void main(String[] args) { - char[] reverses = new char[]{'H', 'a', 'n', 'n', 'a', 'h'}; - new Solution1().reverseString(reverses); - for (char c : reverses) { - System.out.printf("\"%s\",", c); - } - } -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\205\203\351\237\263\345\255\227\346\257\215_345_Easy/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\205\203\351\237\263\345\255\227\346\257\215_345_Easy/Solution1.java" deleted file mode 100644 index 59dfaf84..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\345\217\215\350\275\254\345\255\227\347\254\246\344\270\262\344\270\255\347\232\204\345\205\203\351\237\263\345\255\227\346\257\215_345_Easy/Solution1.java" +++ /dev/null @@ -1,43 +0,0 @@ -package cn.lastwhisper.leetcode.array.对撞指针.反转字符串中的元音字母_345_Easy; - -class Solution1 { - /** - * 指针对撞 - * 时间复杂度:O(n) - * 空间复杂度:O(1) - */ - public String reverseVowels(String s) { - char[] chars = s.toCharArray(); - int l = 0, r = chars.length - 1; - while (l < r) { - while (l < r && !isVowel(chars[l])) l++; //找到左边的元音 - while (l < r && !isVowel(chars[r])) r--; //找到右边的元音 - if (l < r) { - // 找到了交换 - char temp = chars[l]; - chars[l] = chars[r]; - chars[r] = temp; - l++; - r--; - } - } - return new String(chars); - } - - public boolean isVowel(char c) { - if (c == 'a' || c == 'A') return true; - else if (c == 'e' || c == 'E') return true; - else if (c == 'i' || c == 'I') return true; - else if (c == 'o' || c == 'O') return true; - else if (c == 'u' || c == 'U') return true; - return false; - } - - - public static void main(String[] args) { - String s = "leetcode"; - //String s = "aA"; - System.out.println(new Solution1().reverseVowels(s)); - ; - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\345\260\206\346\225\260\347\273\204\345\210\206\346\210\220\345\222\214\347\233\270\347\255\211\347\232\204\344\270\211\344\270\252\351\203\250_1013_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\345\260\206\346\225\260\347\273\204\345\210\206\346\210\220\345\222\214\347\233\270\347\255\211\347\232\204\344\270\211\344\270\252\351\203\250_1013_\347\256\200\345\215\225/Solution1.java" deleted file mode 100644 index c6f49076..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\345\260\206\346\225\260\347\273\204\345\210\206\346\210\220\345\222\214\347\233\270\347\255\211\347\232\204\344\270\211\344\270\252\351\203\250_1013_\347\256\200\345\215\225/Solution1.java" +++ /dev/null @@ -1,56 +0,0 @@ -package cn.lastwhisper.leetcode.array.对撞指针.将数组分成和相等的三个部_1013_简单; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/partition-array-into-three-parts-with-equal-sum/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路:三个和相等的非空部分,0~i == i+1~j == j-1~length-1。 - * 观察规律: - * 1.分成三等分,说明sum%3==0。 - * 2.sum%3==0有没有可能不能划分成三等分? - * 有可能,比如[6,7,8],必须把8拆一份给6才行,这是不允许的。 - * 坑: - * 非空部分!!!不一定要把数组里面值全部都使用 - * ------------------------------------------------------------------- - * 时间复杂度: - * 空间复杂度: - */ - public boolean canThreePartsEqualSum(int[] A) { - int sum = 0; - for (int a : A) { - sum += a; - } - if (sum % 3 != 0) { - return false; - } - // 双指针 - int left = 0, right = A.length - 1; - int peer = sum / 3, leftSum = A[left], rightSum = A[right]; - // 使用left + 1 < right 的原因,防止只能将数组分成两个部分 - // 例如:[1,-1,1,-1],使用left < right作为判断条件就会出错 - while (left + 1 < right) { - if (leftSum == peer && rightSum == peer) { - return true; - } - while (left + 1 < right && leftSum != peer) { - left++; - leftSum += A[left]; - } - while (left + 1 < right && rightSum != peer) { - right--; - rightSum += A[right]; - } - } - return false; - } - - public static void main(String[] args) { - //int[] nums = new int[]{0,2,1,-6,6,-7,9,1,2,0,1}; - //int[] nums = new int[]{0, 2, 1, -6, 6, 7, 9, -1, 2, 0, 1}; - //int[] nums = new int[]{3,3,6,5,-2,2,5,1,-9,4}; - int[] nums = new int[]{3, 3, 6, 5, -2, 2, 5, 1, -9, 4}; - System.out.println(new Solution1().canThreePartsEqualSum(nums)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\345\260\206\346\225\260\347\273\204\345\210\206\346\210\220\345\222\214\347\233\270\347\255\211\347\232\204\344\270\211\344\270\252\351\203\250_1013_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\345\260\206\346\225\260\347\273\204\345\210\206\346\210\220\345\222\214\347\233\270\347\255\211\347\232\204\344\270\211\344\270\252\351\203\250_1013_\347\256\200\345\215\225/Solution2.java" deleted file mode 100644 index d382fcf1..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\345\260\206\346\225\260\347\273\204\345\210\206\346\210\220\345\222\214\347\233\270\347\255\211\347\232\204\344\270\211\344\270\252\351\203\250_1013_\347\256\200\345\215\225/Solution2.java" +++ /dev/null @@ -1,43 +0,0 @@ -package cn.lastwhisper.leetcode.array.对撞指针.将数组分成和相等的三个部_1013_简单; - -class Solution2 { - /** - * 题目地址:https://leetcode-cn.com/problems/partition-array-into-three-parts-with-equal-sum/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路: - * ------------------------------------------------------------------- - * 时间复杂度: - * 空间复杂度: - */ - public boolean canThreePartsEqualSum(int[] A) { - int sum = 0; - for (int a : A) { - sum += a; - } - if (sum % 3 != 0) { - return false; - } - - int freq = 0; - int count = 0; - for (int a : A) { - count += a; - if (count == sum / 3) { - freq++; - count = 0; - } - } - // [10,-10,10,-10,10,-10,10,-10] - return freq >= 3; - } - - public static void main(String[] args) { - //int[] nums = new int[]{0,2,1,-6,6,-7,9,1,2,0,1}; - //int[] nums = new int[]{0, 2, 1, -6, 6, 7, 9, -1, 2, 0, 1}; - //int[] nums = new int[]{3,3,6,5,-2,2,5,1,-9,4}; - int[] nums = new int[]{3, 3, 6, 5, -2, 2, 5, 1, -9, 4}; - System.out.println(new Solution2().canThreePartsEqualSum(nums)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250_11_Medium/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250_11_Medium/Solution1.java" deleted file mode 100644 index 79304785..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250_11_Medium/Solution1.java" +++ /dev/null @@ -1,21 +0,0 @@ -package cn.lastwhisper.leetcode.array.对撞指针.盛最多水的容器_11_Medium; - -/** - * @author lastwhisper - */ -public class Solution1 { - public int maxArea(int[] height) { - int maxArea = 0; - for (int i = 0; i < height.length; i++) { - for (int j = i + 1; j < height.length; j++) { - maxArea = Math.max(maxArea, Math.min(height[i], height[j]) * (j - i)); - } - } - return maxArea; - } - - public static void main(String[] args) { - int[] arr = {1, 8, 6, 2, 5, 4, 8, 3, 7}; - System.out.println(new Solution1().maxArea(arr)); - } -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250_11_Medium/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250_11_Medium/Solution2.java" deleted file mode 100644 index 18880fca..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250_11_Medium/Solution2.java" +++ /dev/null @@ -1,24 +0,0 @@ -package cn.lastwhisper.leetcode.array.对撞指针.盛最多水的容器_11_Medium; - -/** - * @author lastwhisper - */ -public class Solution2 { - - public int maxArea(int[] height) { - int maxarea = 0, l = 0, r = height.length - 1; - while (l < r) { - maxarea = Math.max(maxarea, Math.min(height[l], height[r]) * (r - l)); - if (height[l] < height[r]) - l++; - else - r--; - } - return maxarea; - } - - public static void main(String[] args) { - int[] arr = {1, 8, 6, 2, 5, 4, 8, 3, 7}; - System.out.println(new Solution2().maxArea(arr)); - } -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262_125_Easy/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262_125_Easy/Solution1.java" deleted file mode 100644 index c89b5506..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\257\271\346\222\236\346\214\207\351\222\210/\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262_125_Easy/Solution1.java" +++ /dev/null @@ -1,38 +0,0 @@ -package cn.lastwhisper.leetcode.array.对撞指针.验证回文串_125_Easy; - - -class Solution1 { - /** - * https://leetcode-cn.com/problems/valid-palindrome/ - * 指针对撞 - * 时间复杂度:O(n) - * 空间复杂度:O(1) - */ - public boolean isPalindrome(String s) { - String tempStr = s.toUpperCase(); - char[] chars = tempStr.toCharArray(); - int l = 0, r = tempStr.length() - 1; - while (l < r) { - while (l < r && !isWordOrNum(chars[l])) l++; - while (l < r && !isWordOrNum(chars[r])) r--; - if (chars[l] != chars[r]) { - return false; - } - l++; - r--; - } - return true; - } - - // 是否是字母和数字字符 - public boolean isWordOrNum(char c) { - return ((c >= 48 && c <= 57) || (c >= 65 && c <= 90) || (c >= 97 && c <= 122)); - } - - public static void main(String[] args) { - String s = "A man, a plan, a canal: Panama"; - //String s = "race a car"; - System.out.println(new Solution1().isPalindrome(s)); - //System.out.println(s.toUpperCase()); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\260\206\346\225\260\347\273\204\345\210\206\346\210\220\345\222\214\347\233\270\347\255\211\347\232\204\344\270\211\344\270\252\351\203\250_1013_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\260\206\346\225\260\347\273\204\345\210\206\346\210\220\345\222\214\347\233\270\347\255\211\347\232\204\344\270\211\344\270\252\351\203\250_1013_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..2a96a74a --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\260\206\346\225\260\347\273\204\345\210\206\346\210\220\345\222\214\347\233\270\347\255\211\347\232\204\344\270\211\344\270\252\351\203\250_1013_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,56 @@ +package cn.lastwhisper.leetcode.array.将数组分成和相等的三个部_1013_简单; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/partition-array-into-three-parts-with-equal-sum/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:三个和相等的非空部分,0~i == i+1~j == j-1~length-1。 + * 观察规律: + * 1.分成三等分,说明sum%3==0。 + * 2.sum%3==0有没有可能不能划分成三等分? + * 有可能,比如[6,7,8],必须把8拆一份给6才行,这是不允许的。 + * 坑: + * 非空部分!!!不一定要把数组里面值全部都使用 + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public boolean canThreePartsEqualSum(int[] A) { + int sum = 0; + for (int a : A) { + sum += a; + } + if (sum % 3 != 0) { + return false; + } + // 双指针 + int left = 0, right = A.length - 1; + int peer = sum / 3, leftSum = A[left], rightSum = A[right]; + // 使用left + 1 < right 的原因,防止只能将数组分成两个部分 + // 例如:[1,-1,1,-1],使用left < right作为判断条件就会出错 + while (left + 1 < right) { + if (leftSum == peer && rightSum == peer) { + return true; + } + while (left + 1 < right && leftSum != peer) { + left++; + leftSum += A[left]; + } + while (left + 1 < right && rightSum != peer) { + right--; + rightSum += A[right]; + } + } + return false; + } + + public static void main(String[] args) { + //int[] nums = new int[]{0,2,1,-6,6,-7,9,1,2,0,1}; + //int[] nums = new int[]{0, 2, 1, -6, 6, 7, 9, -1, 2, 0, 1}; + //int[] nums = new int[]{3,3,6,5,-2,2,5,1,-9,4}; + int[] nums = new int[]{3, 3, 6, 5, -2, 2, 5, 1, -9, 4}; + System.out.println(new Solution1().canThreePartsEqualSum(nums)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\260\206\346\225\260\347\273\204\345\210\206\346\210\220\345\222\214\347\233\270\347\255\211\347\232\204\344\270\211\344\270\252\351\203\250_1013_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\260\206\346\225\260\347\273\204\345\210\206\346\210\220\345\222\214\347\233\270\347\255\211\347\232\204\344\270\211\344\270\252\351\203\250_1013_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..35b02ccb --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\345\260\206\346\225\260\347\273\204\345\210\206\346\210\220\345\222\214\347\233\270\347\255\211\347\232\204\344\270\211\344\270\252\351\203\250_1013_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,43 @@ +package cn.lastwhisper.leetcode.array.将数组分成和相等的三个部_1013_简单; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/partition-array-into-three-parts-with-equal-sum/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public boolean canThreePartsEqualSum(int[] A) { + int sum = 0; + for (int a : A) { + sum += a; + } + if (sum % 3 != 0) { + return false; + } + + int freq = 0; + int count = 0; + for (int a : A) { + count += a; + if (count == sum / 3) { + freq++; + count = 0; + } + } + // [10,-10,10,-10,10,-10,10,-10] + return freq >= 3; + } + + public static void main(String[] args) { + //int[] nums = new int[]{0,2,1,-6,6,-7,9,1,2,0,1}; + //int[] nums = new int[]{0, 2, 1, -6, 6, 7, 9, -1, 2, 0, 1}; + //int[] nums = new int[]{3,3,6,5,-2,2,5,1,-9,4}; + int[] nums = new int[]{3, 3, 6, 5, -2, 2, 5, 1, -9, 4}; + System.out.println(new Solution2().canThreePartsEqualSum(nums)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..72bd4c28 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,65 @@ +package cn.lastwhisper.leetcode.array.找到字符串中所有字母异位词_438_中等; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/ + * 编号:438 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:双指针(滑动窗口) + * (1)双指针 l、r 维护一个滑动窗口,初始窗口扩容至模式串 p 的长度 + * (2)判断当前 [l,r] 是否满足 异位词,如果满足,记录当前 l 的下标, + * (3)窗口整体右移 + * (4)循环2、3,条件 r 未越界,r 未越界,l 肯定未越界 + * ------------------------------------------------------------------- + * 时间复杂度:O(n^2) //n 是 s 的长度、m 是 p 的长度 + * 空间复杂度:O(1) + */ + public List findAnagrams(String s, String p) { + List result = new ArrayList<>(); + // 特判 + if (s == null || s.length() < p.length()) { + return result; + } + // 直接让 [l,r] 满足模式串长度 + int l = 0, r = p.length() - 1; + int[] visited = new int[26]; + + while (r < s.length()) { + // 检查是否是异位词 + if (anagram(s, l, r, p, visited)) { + result.add(l); + } + l++; + r++; + } + return result; + } + + public boolean anagram(String s, int l, int r, String p, int[] visited) { + Arrays.fill(visited, 0); + + for (int i = l; i <= r; i++) { + visited[s.charAt(i) - 'a']++; + visited[p.charAt(i - l) - 'a']--; + } + + for (int count : visited) { + if (count != 0) { + return false; + } + } + return true; + } + + public static void main(String[] args) { + String s = "cbaebabacd", p = "abc"; + //String s = "abab", p = "ab"; + System.out.println(new Solution1().findAnagrams(s, p)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/Solution2.java" new file mode 100644 index 00000000..c3aaa4dd --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/Solution2.java" @@ -0,0 +1,73 @@ +package cn.lastwhisper.leetcode.array.找到字符串中所有字母异位词_438_中等; + +import java.util.ArrayList; +import java.util.List; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/ + * 编号:438 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:双指针(滑动窗口) + * (1)双指针 l、r 维护一个滑动窗口进行遍历主串 s, + * window[] hash 表用于记录 [l,r] 窗口中某字符次数,是否满足模式串 s 中字符次数, + * total 用于记录 [l,r] 窗口各个字符数量,是否满足模式串 s 中字符数量, + * need[] hash 表用于记录模式串 s 中各个字符数量, + * (2) + * (3) + * (4) + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public List findAnagrams(String s, String p) { + if (s == null || p == null || s.length() < p.length()) { + return new ArrayList<>(); + } + List result = new ArrayList<>(); + int l = 0, r = 0, total = p.length(); + int[] window = new int[26]; + int[] need = new int[26]; + for (int i = 0; i < p.length(); i++) { + need[p.charAt(i) - 'a']++; + } + while (r < s.length()) { + int cr = s.charAt(r) - 'a'; + // s 中的字符,是否存在 p 中 + // 如果存在,window 记录该字符出现次数,该字符出现次数小于等于 p 中该字符数,total-- + if (need[cr] > 0) { + window[cr]++; + if (window[cr] <= need[cr]) { + total--; + } + } + // [l,r] 中包含了 p 中所有字符 + while (total == 0) { + // 必须是和 p 的长度相同才可以算字母异位词 + // 比如 s=ceba p=abc 也满足 total==0 ,但是并不是异位词 + if (r - l == p.length() - 1) { + result.add(l); + } + // 缩小窗口,剔除 l 所指向的字符次数,total++ + int cl = s.charAt(l) - 'a'; + if (need[cl] > 0) { + window[cl]--; + if (window[cl] < need[cl]) { + total++; + } + } + l++; + } + r++; + } + return result; + } + + public static void main(String[] args) { + String s = "cbaebabacd", p = "abc"; + //String s = "abab", p = "ab"; + System.out.println(new Solution2().findAnagrams(s, p)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/backup.md" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/backup.md" new file mode 100644 index 00000000..90baddd1 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/backup.md" @@ -0,0 +1,139 @@ +第一步: +```java + +int l = 0, r = 0; + int[] visit = new int[26]; +while (l < s.length()) { + if (r < s.length() && r - l < p.length() && !anagram(s, l, r, p, visit)) { + r++; + } else { + if (anagram(s, l, r, p, visit)) { + result.add(l); + } + l++; + } + } + + +public boolean anagram(String s, int l, int r, String p, int[] visit) { + if (r - l != p.length()) { + return false; + } +... +} +``` + +第二步: + +思路:双指针(滑动窗口) +(1)双指针 l、r 维护一个滑动窗口,窗口的长度不大于模式串 p 的长度 +(2)判断当前 [l,r] 满足 异位词 +(3)如果不满足,窗口向右扩容 +(4)如果满足,记录当前 l 的下标,窗口向右缩小 +(5)循环2、3、4,条件 l 未越界 + +```java +int l = 0, r = 0; + int[] visit = new int[26]; +if (!anagram(s, l, r, p, visit)) { + // [l,r]不满足异位词且窗口大小不满足,扩展右边界 + if ((r - l+1) != p.length()) { + r++; + } else { + // [l,r]不满足异位词且窗口大小满足,扩展左边界 + l++; + } + } else { + result.add(l); + l++; + } +``` + +第三步: + + +```java + +int l = 0, r = 0; + int[] visit = new int[26]; +while (l < s.length() && r < s.length()) { + // [l,r]不满足窗口大小,扩展右边界 + if ((r - l + 1) != p.length()) { + r++; + } else { + // [l,r]满足窗口大小,检查是否是异位词 + if (anagram(s, l, r, p, visit)) { + result.add(l); + } + l++; + } + } + +``` + +第四步: + +```java +int l = 0, r = 0; + int[] visit = new int[26]; +while (l < s.length() && r < s.length()) { + // [l,r]不满足模式串长度,扩展右边界 + while ((r - l + 1) != p.length()) { + r++; + } + // 此时窗口肯定满足,模式串的长度了,但是有可能越界了 + if (r < s.length()) { + // 检查是否是异位词 + if (anagram(s, l, r, p, visit)) { + result.add(l); + } + l++; + } + } + +``` +第五步: + +```java + +int l = 0, r = 0; + int[] visit = new int[26]; + while (l < s.length() && r < s.length()) { + // [l,r]不满足模式串长度,扩展右边界到窗口最大长度 + // (r - l + 1) != p.length() ==》 推导 r = p.length() + l - 1; + r = p.length() + l - 1; + // 此时窗口肯定满足,模式串的长度了,但是有可能越界了 + if (r < s.length()) { + // 检查是否是异位词 + if (anagram(s, l, r, p, visit)) { + result.add(l); + } + l++; + } + } + +``` +第六步: + +```java +public List findAnagrams(String s, String p) { + List result = new ArrayList<>(); + // 过滤肯定不符合规则的数据 + if (s == null || s.length() < p.length()) { + return result; + } + // 直接让 [l,r] 满足模式串长度 + int l = 0, r = p.length() - 1; + int[] visit = new int[26]; + + while (r < s.length()) { + // 检查是否是异位词 + if (anagram(s, l, r, p, visit)) { + result.add(l); + } + l++; + r++; + } + return result; + } +``` diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/README.md" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/README.md" new file mode 100644 index 00000000..bfb64b8d --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/README.md" @@ -0,0 +1,24 @@ +分类:稳定性、排序原则、存储器不同 + +按稳定性: + +1. 稳定:冒泡排序、插入排序、归并排序、基数排序、桶排序、计数排序 + +2. 不稳定:选择排序、希尔排序、堆排序、快速排序 + +按排序原则: +1. 插入排序:插入排序、希尔排序 +2. 交换排序:冒泡排序、快速排序 +3. 选择排序:选择排序、堆排序 +4. 归并排序:2-路归并排序 +5. 分配排序:基数排序 + + (1)插入类:将无序子序列中的一个或几个记录“插入”到有序序列中,从而增加记录的有序子序列的长度。 + (2)交换类:通过“交换”无序序列中的记录从而得到其中关键字最小或最大的记录,并将它加入到有序子序列中,以此方法增加记录的有序子序列的长度。 + (3)选择类:从记录的无序子序列中“选择”关键字最小或最大的记录,并将它加入到有序子序列中,以此方法增加记录的有序子序列的长度。 + (4)归并类:通过“归并”两个或两个以上的记录有序子序列,逐步增加记录有序序列的长度。 + (5)分配类:是唯一一类不需要进行关键字之间比较的排序方法,排序时主要利用分配和收集两种基本操作来完成。 + + + +​ \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\344\272\244\346\215\242/BubbleSort.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\344\272\244\346\215\242/BubbleSort.java" new file mode 100644 index 00000000..bab4a394 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\344\272\244\346\215\242/BubbleSort.java" @@ -0,0 +1,40 @@ +package cn.lastwhisper.leetcode.array.排序数组_912_中等.交换; + +import org.junit.Assert; + +class BubbleSort { + /** + * 题目地址:https://leetcode-cn.com/problems/rectangle-overlap/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 冒泡排序——稳定 + * https://zh.wikipedia.org/wiki/%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F + * ------------------------------------------------------------------- + * 时间复杂度:O(n^2) + * 空间复杂度:O(1) + */ + public int[] sortArray(int[] nums) { + // 标识数组是否无序 + boolean exchanged = true; + for (int i = 0; exchanged && i < nums.length; i++) { + exchanged = false; + // 每次将最大值交换到无序数组最后的位置 + for (int j = 0; j < nums.length - 1 - i; j++) { + if (nums[j] > nums[j + 1]) { + int temp = nums[j]; + nums[j] = nums[j + 1]; + nums[j + 1] = temp; + exchanged = true; + } + } + } + return nums; + } + + + public static void main(String[] args) { + Assert.assertArrayEquals(new int[]{1, 2, 3, 5}, new BubbleSort().sortArray(new int[]{5, 2, 3, 1})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\344\272\244\346\215\242/Quick2Sort.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\344\272\244\346\215\242/Quick2Sort.java" new file mode 100644 index 00000000..341d33c9 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\344\272\244\346\215\242/Quick2Sort.java" @@ -0,0 +1,73 @@ +package cn.lastwhisper.leetcode.array.排序数组_912_中等.交换; + +import org.junit.Assert; + +class Quick2Sort { + /** + * 题目地址:https://leetcode-cn.com/problems/rectangle-overlap/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 快速排序——不稳定 + * https://zh.wikipedia.org/wiki/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F + * + * 快速排序(Quick Sort)是由冒泡排序改进而得的。在冒泡排序过程中,只对相邻的两个记录进行比较,因此每次交换两个相邻记录时只能消除一个逆序。 + * 如果能通过两个(不相邻)记录的一-次交换,消除多个逆序,则会大大加快排序的速度。快速排序方法中的一次交换可能消除多个逆序。 + * + * 基准值可以选择第一个值、中间值、最后一个值 + * ------------------------------------------------------------------- + * 时间复杂度:O(nlogn) + * 空间复杂度:O(nlogn) + */ + public int[] sortArray(int[] nums) { + quickSort(nums, 0, nums.length - 1); + return nums; + } + + public void quickSort(int[] nums, int left, int right) { + if (left < right) {// 长度大于1 + int pivotLoc = partition(nums, left, right);//中轴下标 + quickSort(nums, left, pivotLoc - 1); + quickSort(nums, pivotLoc + 1, right); + } + } + + /** + * 选择第一个值、中间值、最后一个值为中轴,这里选择第一个值 + * 在[low,high]范围内,中轴左边的值都小于中轴,中轴右边的值都大于中轴 + * + * @param nums 待排序数组 + * @param low 排序起始位置 + * @param high 排序终止位置 + * @return int 中轴下标 + */ + private int partition(int[] nums, int low, int high) { + int pivot = nums[low]; + while (low < high) { + while (low < high && nums[high] >= pivot) high--; + nums[low] = nums[high]; + while (low < high && nums[low] <= pivot) low++; + nums[high] = nums[low]; + } + nums[low] = pivot; + return low; + } + // 选最后一个值 + //private int partition(int[] nums, int low, int high) { + // int pivot = nums[high]; + // while (low < high) { + // while (low < high && nums[low] <= pivot) low++; + // nums[high] = nums[low]; + // while (low < high && nums[high] >= pivot) high--; + // nums[low] = nums[high]; + // } + // nums[high] = pivot; + // return high; + //} + + + public static void main(String[] args) { + Assert.assertArrayEquals(new int[]{1, 2, 3, 5}, new Quick2Sort().sortArray(new int[]{5, 2, 3, 1})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\344\272\244\346\215\242/QuickSort.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\344\272\244\346\215\242/QuickSort.java" new file mode 100644 index 00000000..4968ccac --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\344\272\244\346\215\242/QuickSort.java" @@ -0,0 +1,69 @@ +package cn.lastwhisper.leetcode.array.排序数组_912_中等.交换; + +import org.junit.Assert; + +class QuickSort { + /** + * 题目地址:https://leetcode-cn.com/problems/rectangle-overlap/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 快速排序——不稳定 + * https://zh.wikipedia.org/wiki/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F + * + * 快速排序(Quick Sort)是由冒泡排序改进而得的。在冒泡排序过程中,只对相邻的两个记录进行比较,因此每次交换两个相邻记录时只能消除一个逆序。 + * 如果能通过两个(不相邻)记录的一-次交换,消除多个逆序,则会大大加快排序的速度。快速排序方法中的一次交换可能消除多个逆序。 + * + * 基准值可以选择第一个值、中间值、最后一个值 + * ------------------------------------------------------------------- + * 时间复杂度:O(nlogn) + * 空间复杂度:O(nlogn) + */ + public int[] sortArray(int[] nums) { + quickSort(nums, 0, nums.length - 1); + return nums; + } + + public void quickSort(int[] nums, int left, int right) { + if (left < right) {// 长度大于1 + int pivotLoc = partition(nums, left, right);//中轴下标 + quickSort(nums, left, pivotLoc - 1); + quickSort(nums, pivotLoc + 1, right); + } + } + + /** + * 选择第一个值、中间值、最后一个值为中轴,这里选择最后一个值 + * 在[start,end]范围内,中轴左边的值都小于中轴,中轴右边的值都大于中轴 + * + * @param nums 待排序数组 + * @param leftBound 排序起始位置 + * @param rightBound 排序终止位置 + * @return int 中轴下标 + */ + // 分区 + private static int partition(int[] nums, int leftBound, int rightBound) { + int left = leftBound; + int pivot = nums[rightBound]; + int right = rightBound - 1; + while (left <= right) {// left <= right取等,[4,6]时进不去while + while (left <= right && nums[left] <= pivot) left++; + while (left <= right && nums[right] > pivot) right--; + if (left < right) swap(nums, left, right); + } + swap(nums, left, rightBound); + return left; + } + + private static void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + + + public static void main(String[] args) { + Assert.assertArrayEquals(new int[]{1, 2, 3, 5}, new QuickSort().sortArray(new int[]{5, 2, 3, 1})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\345\210\206\351\205\215/CountSort.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\345\210\206\351\205\215/CountSort.java" new file mode 100644 index 00000000..625e4898 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\345\210\206\351\205\215/CountSort.java" @@ -0,0 +1,37 @@ +package cn.lastwhisper.leetcode.array.排序数组_912_中等.分配; + +class CountSort { + + /** + * 题目地址:https://leetcode-cn.com/problems/rectangle-overlap/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 计数排序——稳定 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ + public int[] sortArray(int[] nums) { + int max = -50001, min = 50001; + for (int num : nums) { + max = Math.max(num, max); + min = Math.min(num, min); + } + + int[] counter = new int[max - min + 1]; + for (int num : nums) { + counter[num - min]++; + } + + int idx = 0; + for (int num = min; num <= max; num++) { + int cnt = counter[num - min]; + while (cnt-- > 0) { + nums[idx++] = num; + } + } + return nums; + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\345\210\206\351\205\215/RadixSort.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\345\210\206\351\205\215/RadixSort.java" new file mode 100644 index 00000000..d9afe66d --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\345\210\206\351\205\215/RadixSort.java" @@ -0,0 +1,67 @@ +package cn.lastwhisper.leetcode.array.排序数组_912_中等.分配; + +import org.junit.Assert; + +class RadixSort { + /** + * 题目地址:https://leetcode-cn.com/problems/rectangle-overlap/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 基数排序——稳定 + * ------------------------------------------------------------------- + * 时间复杂度:O(nlogn) + * 空间复杂度:O(1) + */ + public int[] sortArray(int[] nums) { + int[][] bucket = new int[10][nums.length]; + // 桶元素计数器,记录每个桶中存放了多少数据 + int[] bucketElementCount = new int[10]; + // 原arr下标 + int arrIndex; + // 除数 + int divisor = 1; + // 最大值 + int max = nums[0]; + // 由于基数排序次数由最大数值的位数决定,所以需要求最大值 + for (int i = 1; i < nums.length; i++) { + if (max < nums[i]) { + max = nums[i]; + } + } + + // 最大值得位数,即排序次数 + int maxLength = (max + "").length(); + for (int f = 0; f < maxLength; f++) { + for (int num : nums) { + // digitOfElement对应放在哪个bucket中 + int digitOfElement = num / divisor % 10; + // 放在第digitOfElement个bucket的第bucketElementCount[digitOfElement]下标位置 + bucket[digitOfElement][bucketElementCount[digitOfElement]] = num; + // 下次放在bucket的第bucketElementCount[digitOfElement]++下标位置 + bucketElementCount[digitOfElement]++; + } + + arrIndex = 0; + // 将桶中数据放回原数组 + for (int i = 0; i < bucketElementCount.length; i++) { + // 对应桶中有数据 + if (bucketElementCount[i] != 0) { + for (int j = 0; j < bucketElementCount[i]; j++) { + nums[arrIndex++] = bucket[i][j]; + } + } + // 将桶元素计数器清空 + bucketElementCount[i] = 0; + } + divisor *= 10; + } + return nums; + } + + public static void main(String[] args) { + Assert.assertArrayEquals(new int[]{1, 2, 3, 5}, new RadixSort().sortArray(new int[]{5, 2, 3, 1})); + Assert.assertArrayEquals(new int[]{0, 0, 1, 1, 2, 5}, new RadixSort().sortArray(new int[]{5, 1, 1, 2, 0, 0})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\345\275\222\345\271\266/MergeSort.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\345\275\222\345\271\266/MergeSort.java" new file mode 100644 index 00000000..3b8bde6b --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\345\275\222\345\271\266/MergeSort.java" @@ -0,0 +1,89 @@ +package cn.lastwhisper.leetcode.array.排序数组_912_中等.归并; + +import org.junit.Assert; + +class MergeSort { + /** + * 题目地址:https://leetcode-cn.com/problems/rectangle-overlap/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 归并排序——稳定 + * + * ------------------------------------------------------------------- + * 时间复杂度:O(nlogn) + * 空间复杂度:O(1) + */ + public int[] sortArray(int[] nums) { + mergeSort(nums, 0, nums.length - 1, new int[nums.length]); + return nums; + } + + /** + * 归并排序 + * 分 + * + * @param arr 排序的原始数组 + * @param left 左边有序序列的初始索引 + * @param right 右边索引 + * @param temp 中转数组 + */ + public void mergeSort(int[] arr, int left, int right, int[] temp) { + if (left < right) { + int mid = (left + right) / 2; + // 向左分 + mergeSort(arr, left, mid, temp); + // 向右分 + mergeSort(arr, mid + 1, right, temp); + // 治 + merge(arr, left, mid, right, temp); + } + } + + /** + * 治 + * @param arr 排序的原始数组 arr[left...mid] arr[mid+1...right] + * @param left 左边有序序列的初始索引 + * @param mid 中间索引 + * @param right 右边索引 + * @param temp 中转数组 + */ + public void merge(int[] arr, int left, int mid, int right, int[] temp) { + int i = left; //左边有序序列的初始索引 + int j = mid + 1; // 右边有序序列的初始化序索引 + int t = 0; // 指向temp数组的当前位置 + + // 1)、将左右两边(有序)的数据按照规则填充到temp数组,任意一边处理完毕为止 + while (i <= mid && j <= right) { + if (arr[i] < arr[j]) { + // 左小于右,将左数组第i个元素copy到temp数组的第t个位置 + temp[t++] = arr[i++]; + } else { + // 右小于或等于左,将右数组第j个元素copy到temp数组的第t个位置 + temp[t++] = arr[j++]; + } + } + + // 2)、把有剩余数据的一边的数据依次填充到temp + while (i <= mid) { + // 说明 左数组还有剩余元素 + temp[t++] = arr[i++]; + } + while (j <= right) { + // 说明 右数组还有剩余元素 + temp[t++] = arr[j++]; + } + + // 3)、将temp数组的数据copy到arr,[left,right]是每次copy的范围 + for (int k = left, l = 0; k <= right; k++, l++) { + arr[k] = temp[l]; + } + + } + + public static void main(String[] args) { + Assert.assertArrayEquals(new int[]{1, 2, 3, 5}, new MergeSort().sortArray(new int[]{5, 2, 3, 1})); + Assert.assertArrayEquals(new int[]{0, 0, 1, 1, 2, 5}, new MergeSort().sortArray(new int[]{5, 1, 1, 2, 0, 0})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\346\217\222\345\205\245/InsertSort.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\346\217\222\345\205\245/InsertSort.java" new file mode 100644 index 00000000..13f03c56 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\346\217\222\345\205\245/InsertSort.java" @@ -0,0 +1,36 @@ +package cn.lastwhisper.leetcode.array.排序数组_912_中等.插入; + +import org.junit.Assert; + +class InsertSort { + /** + * 题目地址:https://leetcode-cn.com/problems/rectangle-overlap/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 插入排序——稳定 + * https://zh.wikipedia.org/wiki/%E6%8F%92%E5%85%A5%E6%8E%92%E5%BA%8F + * ------------------------------------------------------------------- + * 时间复杂度:O(n^2) + * 空间复杂度:O(1) + */ + public int[] sortArray(int[] nums) { + for (int i = 1; i < nums.length; i++) { + int num = nums[i];// 无序数组第一个值,待插入数据 + int idx = i - 1;// 有序数组最后一个值下标 + // 把待插入的位置腾出来 + while (idx >= 0 && nums[idx] > num) { + nums[idx + 1] = nums[idx]; + idx--; + } + nums[idx + 1] = num; + } + return nums; + } + + + public static void main(String[] args) { + Assert.assertArrayEquals(new int[]{1, 2, 3, 5}, new InsertSort().sortArray(new int[]{5, 2, 3, 1})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\346\217\222\345\205\245/ShellSort.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\346\217\222\345\205\245/ShellSort.java" new file mode 100644 index 00000000..a0c870e9 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\346\217\222\345\205\245/ShellSort.java" @@ -0,0 +1,46 @@ +package cn.lastwhisper.leetcode.array.排序数组_912_中等.插入; + +import org.junit.Assert; + +class ShellSort { + /** + * 题目地址:https://leetcode-cn.com/problems/rectangle-overlap/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 希尔排序——不稳定 + * https://zh.wikipedia.org/wiki/%E6%8F%92%E5%85%A5%E6%8E%92%E5%BA%8F + * ------------------------------------------------------------------- + * 时间复杂度:O(nlogn) + * 空间复杂度:O(1) + */ + public int[] sortArray(int[] nums) { + int gap = nums.length / 2; + int j; + int temp; + while (gap > 0) { + // 对每个数组进行插入排序;由于每个数组并不是真的存在的数组,而是一个大数组 + // 所以通过gap进行取值 + for (int i = gap; i < nums.length; i++) { + j = i; // 缓存每个数组的起始下标 + temp = nums[i]; // 缓存每个数组的起始下标的数值 + if (temp < nums[j - gap]) { + while (j - gap >= 0 && temp < nums[j - gap]) { + // 从前往后移动 + nums[j] = nums[j - gap]; + j = j - gap; + } + nums[j] = temp; + } + } + gap = gap / 2; + } + return nums; + } + + + public static void main(String[] args) { + Assert.assertArrayEquals(new int[]{1, 2, 3, 5}, new ShellSort().sortArray(new int[]{5, 2, 3, 1})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\351\200\211\346\213\251/HeapSort.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\351\200\211\346\213\251/HeapSort.java" new file mode 100644 index 00000000..39a9521a --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\351\200\211\346\213\251/HeapSort.java" @@ -0,0 +1,74 @@ +package cn.lastwhisper.leetcode.array.排序数组_912_中等.选择; + +import org.junit.Assert; + +class HeapSort { + /** + * 题目地址:https://leetcode-cn.com/problems/rectangle-overlap/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 堆排序——不稳定 + * https://zh.wikipedia.org/wiki/%E5%A0%86%E6%8E%92%E5%BA%8F + * + * 大顶堆升序,小顶堆降序 + * ------------------------------------------------------------------- + * 时间复杂度:O(nlogn) + * 空间复杂度:O(1) + */ + public int[] sortArray(int[] nums) { + // 1. 满二叉树从右向左、从下往上构建大顶堆;完全二叉树从左向右、从下往上构建大顶堆; + // i--意味着,从下到上,每一次都是[i,arr.length]的数组(二叉树)进行重构大顶堆 + // 将整个数组构建成完整的大顶堆,此时nums[0]是数组最大值 + for (int i = nums.length / 2 - 1; i >= 0; i--) { + adjustHeap(nums, i, nums.length); + } + // 2. 交换堆顶元素与末尾元素,调整堆结构 + for (int j = nums.length - 1; j >= 0; j--) { + int temp = nums[j]; + nums[j] = nums[0]; + nums[0] = temp; + adjustHeap(nums, 0, j); + } + + return nums; + } + + + /** + * 将一个数组(二叉树), 调整成一个大顶堆 + * 功能: 将以i对应的非叶子节点的树调整成大顶堆 + * 举例: + * i = 1 => {4, 6, 8, 5, 9} => {4, 9, 8, 5, 6} + * i = 0 => {4, 9, 8, 5, 6} => {9, 6, 8, 5, 4} + * @param arr 待调整的数组 + * @param i 表示非叶子节点在数组中索引 + * @param length 表示对多少个元素继续调整, length 是在逐渐的减少 + */ + public void adjustHeap(int[] arr, int i, int length) { + // 当前非叶子节点值 + int temp = arr[i]; + // k = 2*i+1是i节点的左子节点,k+1是右子节点 + for (int k = 2 * i + 1; k < length; k = 2 * k + 1) { + // 找左右子节点最大的值 + if (k + 1 < length && arr[k] < arr[k + 1]) { + k++; + } + if (arr[k] > temp) {//子节点大于父节点 + arr[i] = arr[k];//将较大的子节点赋值到当前节点(父节点) + i = k;//记录子节点的下标,为了最后 arr[i] = temp; + } else { + break;//从下至上,下面已经是大顶堆 + } + } + //i = k; arr[i]此时已经是子节点的位置了,前面父节点已经拿到了子节点的值了,这里要将子节点的值赋为父节点的值 + // 当for循环结束后,我们已经将以i为父结点的树的最大值,放在了最顶(局部) + arr[i] = temp; + } + + public static void main(String[] args) { + Assert.assertArrayEquals(new int[]{1, 2, 3, 5}, new HeapSort().sortArray(new int[]{5, 2, 3, 1})); + Assert.assertArrayEquals(new int[]{0, 0, 1, 1, 2, 5}, new HeapSort().sortArray(new int[]{5, 1, 1, 2, 0, 0})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\351\200\211\346\213\251/SelectSort.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\351\200\211\346\213\251/SelectSort.java" new file mode 100644 index 00000000..404b1e1a --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\216\222\345\272\217\346\225\260\347\273\204_912_\344\270\255\347\255\211/\351\200\211\346\213\251/SelectSort.java" @@ -0,0 +1,41 @@ +package cn.lastwhisper.leetcode.array.排序数组_912_中等.选择; + +import org.junit.Assert; + +class SelectSort { + /** + * 题目地址:https://leetcode-cn.com/problems/rectangle-overlap/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 选择排序——不稳定 + * https://zh.wikipedia.org/wiki/%E9%80%89%E6%8B%A9%E6%8E%92%E5%BA%8F + * ------------------------------------------------------------------- + * 时间复杂度:O(n^2) + * 空间复杂度:O(1) + */ + public int[] sortArray(int[] nums) { + for (int i = 0; i < nums.length; i++) { + + int minIdx = i; + for (int j = i + 1; j < nums.length; j++) { + if (nums[j] < nums[minIdx]) { + minIdx = j; + } + } + // 每次找到无序数组最小值的下标,放到已排序序列的末尾 + if (nums[i] > nums[minIdx]) { + int temp = nums[i]; + nums[i] = nums[minIdx]; + nums[minIdx] = temp; + } + } + return nums; + } + + public static void main(String[] args) { + Assert.assertArrayEquals(new int[]{1, 2, 3, 5}, new SelectSort().sortArray(new int[]{5, 2, 3, 1})); + Assert.assertArrayEquals(new int[]{0, 0, 1, 1, 2, 5}, new SelectSort().sortArray(new int[]{5, 1, 1, 2, 0, 0})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..7cebc5e1 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,28 @@ +package cn.lastwhisper.leetcode.array.数组中的第K个最大元素_215_中等; + +import org.junit.Assert; + +import java.util.Arrays; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/kth-largest-element-in-an-array/ + * 编号:215 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 升序排序,取n-k个元素 + * ------------------------------------------------------------------- + * 时间复杂度:O(n*logn) + * 空间复杂度:O(1) + */ + public int findKthLargest(int[] nums, int k) { + Arrays.sort(nums); + return nums[nums.length - k]; + } + + public static void main(String[] args) { + Assert.assertEquals(5, new Solution1().findKthLargest(new int[]{3, 2, 1, 5, 6, 4}, 2)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution2.java" new file mode 100644 index 00000000..fe03e634 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution2.java" @@ -0,0 +1,75 @@ +package cn.lastwhisper.leetcode.array.数组中的第K个最大元素_215_中等; + +import org.junit.Assert; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/kth-largest-element-in-an-array/ + * 编号:215 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:小顶堆 + * 利用小顶堆的特性(堆顶元素最小),先对前K个数组元素进行"原地"建小顶堆,建完小顶堆后,堆顶的元素最小,正好是这K个元素的第K大元素。 + * 然后遍历剩下的元素 nums[k] ~ nums[len-1] + * 1、如果比堆顶元素小,跳过 + * 2、如果比堆顶元素大,和堆顶元素交换后重新堆化 + * 建堆 buildHeap 时间复杂度 O(K),遍历剩下元素并且堆化 时间复杂度(N-K)*O(logK),总体的时间复杂度 O(NlogK) + * ------------------------------------------------------------------- + * 时间复杂度:O(NlogK) + * 空间复杂度:O(1) + */ + public int findKthLargest(int[] nums, int k) { + //前K个元素原地建小顶堆 + buildHeap(nums, k); + //遍历剩下元素,比堆顶小,跳过;比堆顶大,交换后重新堆化 + for (int i = k; i < nums.length; i++) { + if (nums[i] < nums[0]) continue; + swap(nums, i, 0); + heapify(nums, k, 0); + } + //K个元素的小顶堆的堆顶即是第K大元素 + return nums[0]; + } + + /** + * 建堆函数 + * 从倒数第一个非叶子节点开始堆化,倒数第一个非叶子节点下标为 K/2-1 + */ + public void buildHeap(int[] a, int k) { + for (int i = k / 2 - 1; i >= 0; i--) { + heapify(a, k, i); + } + } + + /** + * 堆化函数 + * 父节点下标i,左右子节点的下标分别为 2*i+1 和 2*i+2 + */ + public void heapify(int[] a, int k, int i) { + //临时变量 minPos 用于存储最小值的下标,先假设父节点最小 + int minPos = i; + while (true) { + //和左子节点比较 + if (i * 2 + 1 < k && a[i * 2 + 1] < a[i]) minPos = i * 2 + 1; + //和右子节点比较 + if (i * 2 + 2 < k && a[i * 2 + 2] < a[minPos]) minPos = i * 2 + 2; + //如果minPos没有发生变化,说明父节点已经是最小了,直接跳出 + if (minPos == i) break; + //否则交换 + swap(a, i, minPos); + //父节点下标进行更新,继续堆化 + i = minPos; + } + } + + public void swap(int[] arr, int i, int j) { + int temp = arr[j]; + arr[j] = arr[i]; + arr[i] = temp; + } + + public static void main(String[] args) { + Assert.assertEquals(5, new Solution2().findKthLargest(new int[]{3, 2, 1, 5, 6, 4}, 2)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/Solution1.java" deleted file mode 100644 index cef7d85a..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/Solution1.java" +++ /dev/null @@ -1,61 +0,0 @@ -package cn.lastwhisper.leetcode.array.数组值当下标.缺失的第一个正数_41_困难; - -class Solution1 { - - /** - * https://leetcode-cn.com/problems/first-missing-positive/ - * 核心思路:输入数组值映射到数组下标,修改下标对应的值标识该数组值出现过, - * 最后统计数组第一个未标识的下标即为结果 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(n) - * ------------------------------------------------------------------- - * 此思路无法应对输入数组中存在一个很大的值 - */ - public int firstMissingPositive(int[] nums) { - //特殊情况三:输入数组为空 - if (nums.length <= 0) { - return 1; - } - int max = nums[0]; - for (int i = 0; i < nums.length; i++) { - // 特殊情况一:数组中有负数 - if (nums[i] < 0) { - nums[i] = 0; - } - if (nums[i] > max) { - max = nums[i]; - } - } - int[] arr = new int[max + 2]; - for (int num : nums) { - arr[num]++; - } - - for (int i = 0; i < arr.length; i++) { - // 特殊情况二:输入数组第一个数值大于1 - if (i == 0 && arr[i] == 0) { - continue; - } - if (arr[i] == 0) { - return i; - } - } - - return -1; - } - - /** - * 题目: 给定一个未排序的整数数组,找出其中没有出现的最小的正整数 - * 说明: 你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。 - */ - public static void main(String[] args) { - //int[] arr = new int[]{1, 2, 0};//3 - //int[] arr = new int[]{3, 4, -1, 1};//2 //特殊情况一:输入数组中有负数 - //int[] arr = new int[]{7, 8, 9, 11, 12};//1 //特殊情况二:输入数组第一个数值大于1 - //int[] arr = new int[]{};//1 //特殊情况三:输入数组为空 - int[] arr = new int[]{1, 2, 3, 10, 2147483647, 9};//1 //特殊情况四:输入数组值过大 - System.out.println(new Solution1().firstMissingPositive(arr)); - //System.out.println(Integer.MAX_VALUE==2147483647); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/Solution2.java" deleted file mode 100644 index add275d5..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/Solution2.java" +++ /dev/null @@ -1,80 +0,0 @@ -package cn.lastwhisper.leetcode.array.数组值当下标.缺失的第一个正数_41_困难; - -class Solution2 { - - /** - * https://leetcode-cn.com/problems/first-missing-positive/ - * 核心思路:使用数组值当做下标 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(1) - * ------------------------------------------------------------------- - * - */ - public int firstMissingPositive(int[] nums) { - - // 处理负数和0,置为大于输入数组长度的一个整数即可 - for (int i = 0; i < nums.length; i++) { - if (nums[i] <= 0) { - nums[i] = Integer.MAX_VALUE; - } - } - - // 将所有出现的正整数,且值在数组长度内,置为负数 - for (int i = 0; i < nums.length; i++) { - int absNum = Math.abs(nums[i]); - /* - * 将[数组值-1]的值当做下标,并将该下标的值置为负, - * 没有被置为负数的数组值,说明它没有后一位数 - * - * absNum>nums.length,有三种情况 - * 1.负数 - * 2.0 - * 3.输入数组中本身就有一个很大的值(此时数组肯定不连续) - */ - if (absNum <= nums.length) { - /* - * 这个负数不能随便写,一定是-nums[absNum - 1] - * 比如nums={2,2} - * 情况一:nums[absNum - 1] = -Math.abs(nums[absNum - 1]) - * 第一次循环nums={2,-2},第二次循环还是nums={2,-2} - * 情况二:随便写一个负数,nums[absNum - 1] = -1 - * 第一次循环nums={2,-1},第二次循环还是nums={-1,-1} - * - */ - nums[absNum - 1] = -Math.abs(nums[absNum - 1]); - } - } - /* - * 处理不连续的数组和连续的数组 - * (1)长度为5的数组里面有一个100——此时缺失的数一定小于100, - * 且为一个没有帮它置为负数的值 - * (2)长度为100的连续数组,最大值100——此时缺失的数一定为100+1 - */ - for (int i = 0; i < nums.length; i++) { - if (nums[i] > 0) { - return i + 1; - } - } - - // 处理空数组 - return nums.length + 1; - } - - /** - * 题目: 给定一个未排序的整数数组,找出其中没有出现的最小的正整数 - * 说明: 你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。 - */ - public static void main(String[] args) { - //int[] arr = new int[]{1, 2, 0};//3 - //int[] arr = new int[]{3, 4, -1, 1};//2 //特殊情况一:输入数组中有负数 - //int[] arr = new int[]{7, 8, 9, 11, 12};//1 //特殊情况二:输入数组第一个数值大于1 - //int[] arr = new int[]{};//1 //特殊情况三:输入数组为空 - //int[] arr = new int[]{1, 2, 3, 10, 2147483647, 9};//1 //特殊情况四:输入数组值过大 - //int[] arr = new int[]{1};//2 - //int[] arr = new int[]{0};//1 - //int[] arr = new int[]{2,2};//1 - int[] arr = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};//10 - System.out.println(new Solution2().firstMissingPositive(arr)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution1.java" deleted file mode 100644 index ea424c4e..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution1.java" +++ /dev/null @@ -1,62 +0,0 @@ -package cn.lastwhisper.leetcode.array.数组值当下标.错误的集合_645_简单; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -class Solution1 { - /** - * https://leetcode-cn.com/problems/set-mismatch/ - * ------------------------------------------------------------------- - * 数据特征: - * 输入:数组、1~n整数、无序、存在重复数据、不一定包含丢失数据 - * 输出:数组[重复数据,丢失数据]、1~n+1整数、 - * ------------------------------------------------------------------- - * 思路: - * 使用两个set集合,set1找出重复数据,set2记录1~length+1, - * set2.removeAll(set1)得到丢失数据。 - * 特殊情况:[1,1] - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(n) - */ - public int[] findErrorNums(int[] nums) { - if (nums.length == 2) { - if (nums[0] == 1 && nums[1] == 1) return new int[]{1, 2}; - } - - Set allSet = new HashSet<>(); - Set numsSet = new HashSet<>(); - int duplicate = -1, miss = -1; - for (Integer num : nums) { - // 找到重复,并将所有元素放到numsSet - if (numsSet.contains(num)) { - duplicate = num; - } else { - numsSet.add(num); - } - - } - for (int i = 1; i <= nums.length + 1; i++) { - allSet.add(i); - } - allSet.removeAll(numsSet); - for (Integer num : allSet) { - miss = num; - break; - } - - return new int[]{duplicate, miss}; - } - - public static void main(String[] args) { - // example - //int[] arr = {1, 2, 2, 4};//2,3 - //int[] arr = {2, 2};//2,1 - // error example - //int[] arr = {3, 2, 2};//2,1 - //int[] arr = {1, 1};//1,2 - int[] arr = {1, 5, 3, 2, 2, 7, 6, 4, 8, 9}; - System.out.println(Arrays.toString(new Solution1().findErrorNums(arr))); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution2.java" deleted file mode 100644 index 2efd732c..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution2.java" +++ /dev/null @@ -1,54 +0,0 @@ -package cn.lastwhisper.leetcode.array.数组值当下标.错误的集合_645_简单; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -class Solution2 { - /** - * https://leetcode-cn.com/problems/set-mismatch/ - * ------------------------------------------------------------------- - * 数据特征: - * 输入:数组、1~n整数、无序、存在重复数据、不一定包含丢失数据 - * 输出:数组[重复数据,丢失数据]、1~n+1整数、 - * ------------------------------------------------------------------- - * 思路: - * 遍历输入数组,使用map存储数组值出现的频率 - * 正常数据1~length每一个出现的频率都为1,将1~length每一个值当做key查询map, - * frequency=2的为重复数据,frequency=null为丢失数据 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(n) - * ------------------------------------------------------------------- - * 改进: - * 将数组值当做数据下标,统计该值出现的频率 - * map需要使用2n的额外空间,使用额外数组当做map,只需要使用n的额外空间 - */ - public int[] findErrorNums(int[] nums) { - Map numFreMap = new HashMap<>(); - int duplicate = -1, miss = -1; - for (int num : nums) { - numFreMap.put(num, numFreMap.getOrDefault(num, 0) + 1); - } - for (int i = 1; i <= nums.length; i++) { - Integer frequency = numFreMap.get(i); - if (frequency == null) { - miss = i; - } else if (frequency == 2) { - duplicate = i; - } - } - return new int[]{duplicate, miss}; - } - - public static void main(String[] args) { - // example - //int[] arr = {1, 2, 2, 4};//2,3 - //int[] arr = {2, 2};//2,1 - // error example - //int[] arr = {3, 2, 2};//2,1 - //int[] arr = {1, 1};//1,2 - int[] arr = {1, 5, 3, 2, 2, 7, 6, 4, 8, 9}; - System.out.println(Arrays.toString(new Solution2().findErrorNums(arr))); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution3.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution3.java" deleted file mode 100644 index 827d7d0b..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution3.java" +++ /dev/null @@ -1,19 +0,0 @@ -package cn.lastwhisper.leetcode.array.数组值当下标.错误的集合_645_简单; - -class Solution3 { - public int[] findErrorNums(int[] nums) { - int[] copy = new int[nums.length + 1]; - for (int n : nums) { - copy[n]++; - } - - int[] res = new int[2]; - for (int i = 1; i < copy.length; i++) { - if (copy[i] == 0) - res[1] = i; - if (copy[i] >= 2) - res[0] = i; - } - return res; - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution4.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution4.java" deleted file mode 100644 index 1d2d9e22..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution4.java" +++ /dev/null @@ -1,52 +0,0 @@ -package cn.lastwhisper.leetcode.array.数组值当下标.错误的集合_645_简单; - -import java.util.Arrays; - -class Solution4 { - /** - * https://leetcode-cn.com/problems/set-mismatch/ - * ------------------------------------------------------------------- - * 数据特征: - * 输入:数组、1~n整数、无序、存在重复数据、不一定包含丢失数据 - * 输出:数组[重复数据,丢失数据]、1~n+1整数、 - * ------------------------------------------------------------------- - * 思路:将数组中的每一个值当做下标,按下标-1找到数组对应的值,并更新为负数, - * 在更新之前检查这个值是否已经是负数,如果已经是负数,说明这个值是重复数据。 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(1) - * ------------------------------------------------------------------- - * 相似题目:https://leetcode-cn.com/problems/first-missing-positive/ - */ - public int[] findErrorNums(int[] nums) { - // 丢失数据初始值为1, - int duplicate = -1, miss = 1; - for (int num : nums) { - if (nums[Math.abs(num) - 1] < 0) { - // 重复出现的下标 - duplicate = Math.abs(num); - } else { - nums[Math.abs(num) - 1] *= -1; - } - } - for (int i = 0; i < nums.length; i++) { - if (nums[i] > 0) { - miss = i + 1; - } - } - return new int[]{duplicate, miss}; - } - - public static void main(String[] args) { - // example - //int[] arr = {1, 2, 2, 4};//2,3 - //int[] arr = {2, 2};//2,1 - // error example - //int[] arr = {3, 2, 2};//2,1 - //int[] arr = {1, 1};//1,2 - //int[] arr = {1, 5, 3, 2, 2, 7, 6, 4, 8, 9};//10 - //int[] arr = {2, 3, 2}; - int[] arr = {3,3,1}; - System.out.println(Arrays.toString(new Solution4().findErrorNums(arr))); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..2c0f8420 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,64 @@ +package cn.lastwhisper.leetcode.array.无重复字符的最长子串_3_中等; + +import java.util.HashSet; +import java.util.Set; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ + * 编号:3 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:双指针(滑动窗口) + * (1)左指针未超出边界,窗口继续扩容或缩小 + * (2)Hash表每次检查右指针指向的值是否存在 + * (3)存在则,移除该字符(移除标识),窗口长度减一 + * (4)不存在,标识该字符已经存在,窗口长度加一 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) // 字符串的长度 + * 空间复杂度:O(1) // 窗口长度 + */ + public int lengthOfLongestSubstring(String s) { + int[] freq = new int[256]; + // 窗口 [l,r] 内无重复元素 + int l = 0, r = 0; + int res = 0; + while (l < s.length()) { + if (r < s.length() && freq[s.charAt(r)] == 0) { + freq[s.charAt(r++)]++; + } else { + freq[s.charAt(l++)]--; + } + // 这里 r - l 不加一,因为 l、r 初始化值都是0,并且是先用在加的 + res = Math.max(res, (r - l)); + } + return res; + } + + //public int lengthOfLongestSubstring(String s) { + // Set hash = new HashSet<>(); + // // 窗口 [l,r] 内无重复元素 + // int l = 0, r = 0; + // int result = 0; + // while (l < s.length()) { + // if (r < s.length() && !hash.contains(s.charAt(r))) { + // hash.add(s.charAt(r)); + // r++; + // } else { + // hash.remove(s.charAt(l)); + // l++; + // } + // // 这里 r - l 不加一,因为 l、r 初始化值都是0,并且是先用在加的 + // result = Math.max(result, r - l); + // } + // return result; + //} + + public static void main(String[] args) { + System.out.println(new Solution1().lengthOfLongestSubstring("abcabcbb")); + System.out.println(new Solution1().lengthOfLongestSubstring("bbbbb")); + System.out.println(new Solution1().lengthOfLongestSubstring("pwwkew")); + System.out.println(new Solution1().lengthOfLongestSubstring(" ")); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_\344\270\255\347\255\211/Solution2.java" new file mode 100644 index 00000000..ff9f77a7 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_\344\270\255\347\255\211/Solution2.java" @@ -0,0 +1,36 @@ +package cn.lastwhisper.leetcode.array.无重复字符的最长子串_3_中等; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ + * 编号:3 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:双指针(滑动窗口) + * 优化 Solution1 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) // 字符串的长度 + * 空间复杂度:O(1) // 窗口长度 + */ + public int lengthOfLongestSubstring(String s) { + byte[] freq = new byte[256]; + int l = 0, r = 0; + int res = 0; + while (l < s.length()) { + while (r < s.length() && freq[s.charAt(r)] == 0) { + freq[s.charAt(r++)]++; + } + res = Math.max(res, (r - l)); + freq[s.charAt(l++)]--; + } + return res; + } + + public static void main(String[] args) { + System.out.println(new Solution2().lengthOfLongestSubstring("abcabcbb")); + System.out.println(new Solution2().lengthOfLongestSubstring("bbbbb")); + System.out.println(new Solution2().lengthOfLongestSubstring("pwwkew")); + System.out.println(new Solution2().lengthOfLongestSubstring(" ")); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution1.java" new file mode 100644 index 00000000..8026aeef --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution1.java" @@ -0,0 +1,81 @@ +package cn.lastwhisper.leetcode.array.最小覆盖子串_76_hard; + +class Solution1 { + /** + * https://leetcode-cn.com/problems/minimum-window-substring/ + * 核心思想:滑动窗口 + * 超时 + */ + public String minWindow(String s, String t) { + if (s.length() < t.length()) return "";//"a", "aa" + if (s.equals(t)) return s;//"a", "a" + // 用于判断s子串是否包含t + int[] map = new int[128]; + String target = "";//"abc", "ac";"a", "b" + int l = 0, r = 0; + while (l <= s.length() && r <= s.length()) { + if (!isSub(s.substring(l, r), t, map)) { + // 不断增加 r 指针扩大窗口 [l, r],直到窗口中的字符串符合要求 + r++; + } else { + // 不断增加 l 指针缩小窗口 [l, r],直到窗口中的字符串不再符合要求 + if ("".equals(target)) { + target = s.substring(l, r); + } else { + target = target.length() > s.substring(l, r).length() ? s.substring(l, r) : target; + } + l++; + } + + } + return target; + } + + /** + * sub是否包含t + */ + public boolean isSub(String sub, String t, int[] map) { + if (sub.length() < t.length()) return false;//过滤肯定不包含 + boolean flag = true; + for (int i = 0; i < sub.length(); i++) { + map[sub.charAt(i)] += 1; + } + // 检验t在sub是否完全出现过 + for (int i = 0; i < t.length(); i++) { + if (map[t.charAt(i)] > 0) { + //t在sub出现过 + map[t.charAt(i)] -= 1; + } else { + //t在sub没出现过 + flag = false; + } + } + // 检验sub是否完全包含t + for (int i = 0; i < t.length(); i++) { + if (map[t.charAt(i)] < 0) { + flag = false; + } + } + // 清空 + for (int i = 0; i < sub.length(); i++) { + map[sub.charAt(i)] = 0; + } + return flag; + } + + public static void main(String[] args) { + System.out.println("target:" + new Solution1().minWindow("ADOBECODEBANC", "ABC")); + System.out.println("target:" + new Solution1().minWindow("a", "a")); + System.out.println("target:" + new Solution1().minWindow("a", "aa")); + System.out.println("target:" + new Solution1().minWindow("a", "b")); + System.out.println("target:" + new Solution1().minWindow("abc", "ac")); + System.out.println("target:" + new Solution1().minWindow("bbaa", "aba")); + System.out.println("target:" + new Solution1().minWindow("abbc", "abc")); + //int[] arr = new int[128]; + //System.out.println(new Solution1().isSub("ADCB", "ABC", arr)); + //System.out.println(new Solution1().isSub("ADQCB", "ABC", arr)); + //System.out.println(new Solution1().isSub("ADeB", "ABC", arr)); + //System.out.println(new Solution1().isSub("abbc", "abc", arr)); + //System.out.println(new Solution1().isSub("bbaa", "aba", arr)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution2.java" new file mode 100644 index 00000000..91ff8787 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution2.java" @@ -0,0 +1,82 @@ +package cn.lastwhisper.leetcode.array.最小覆盖子串_76_hard; + +class Solution2 { + /** + * https://leetcode-cn.com/problems/minimum-window-substring/ + * 核心思想:滑动窗口 + * 超时 + */ + public String minWindow(String s, String t) { + if (s.length() < t.length()) return "";//"a", "aa" + if (s.equals(t)) return s;//"a", "a" + char[] ss = s.toCharArray(); + // 用于判断s子串是否包含t + int[] map = new int[128]; + String target = "";//"abc", "ac";"a", "b" + int l = 0, r = 0; + while (l <= ss.length && r <= ss.length) { + if (!isSub(ss, l, r, t, map)) { + // 不断增加 r 指针扩大窗口 [l, r],直到窗口中的字符串符合要求 + r++; + } else { + // 不断增加 l 指针缩小窗口 [l, r],直到窗口中的字符串不再符合要求 + if ("".equals(target)) { + target = s.substring(l, r); + } else { + target = target.length() > s.substring(l, r).length() ? s.substring(l, r) : target; + } + l++; + } + + } + return target; + } + + /** + * sub是否包含t + */ + public boolean isSub(char[] sub, int start, int end, String t, int[] map) { + if (sub.length < t.length()) return false;//过滤肯定不包含 + boolean flag = true; + for (int i = start; i < end; i++) { + map[sub[i]] += 1; + } + // 检验t在sub是否完全出现过 + for (int i = 0; i < t.length(); i++) { + if (map[t.charAt(i)] > 0) { + //t在sub出现过 + map[t.charAt(i)] -= 1; + } else { + //t在sub没出现过 + flag = false; + } + } + // 检验sub是否完全包含t + for (int i = 0; i < t.length(); i++) { + if (map[t.charAt(i)] < 0) { + flag = false; + } + } + // 清空 + for (int i = start; i < end; i++) { + map[sub[i]] = 0; + } + return flag; + } + + public static void main(String[] args) { + System.out.println("target:" + new Solution2().minWindow("ADOBECODEBANC", "ABC")); + System.out.println("target:" + new Solution2().minWindow("a", "a")); + System.out.println("target:" + new Solution2().minWindow("a", "aa")); + System.out.println("target:" + new Solution2().minWindow("a", "b")); + System.out.println("target:" + new Solution2().minWindow("abc", "ac")); + System.out.println("target:" + new Solution2().minWindow("bbaa", "aba")); + System.out.println("target:" + new Solution2().minWindow("abbc", "abc")); + //int[] arr = new int[128]; + //System.out.println(new Solution2().isSub("ADCB", "ABC", arr)); + //System.out.println(new Solution2().isSub("ADQCB", "ABC", arr)); + //System.out.println(new Solution2().isSub("ADeB", "ABC", arr)); + //System.out.println(new Solution2().isSub("abbc", "abc", arr)); + //System.out.println(new Solution2().isSub("bbaa", "aba", arr)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution3.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution3.java" new file mode 100644 index 00000000..5d61574b --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution3.java" @@ -0,0 +1,87 @@ +package cn.lastwhisper.leetcode.array.最小覆盖子串_76_hard; + +import java.util.HashMap; +import java.util.Map; + +class Solution3 { + public String minWindow(String s, String t) { + + if (s.length() == 0 || t.length() == 0) { + return ""; + } + + // Dictionary which keeps a count of all the unique characters in t. + Map dictT = new HashMap(); + for (int i = 0; i < t.length(); i++) { + int count = dictT.getOrDefault(t.charAt(i), 0); + dictT.put(t.charAt(i), count + 1); + } + + // Number of unique characters in t, which need to be present in the desired window. + int required = dictT.size(); + + // Left and Right pointer + int l = 0, r = 0; + + // formed is used to keep track of how many unique characters in t + // are present in the current window in its desired frequency. + // e.g. if t is "AABC" then the window must have two A's, one B and one C. + // Thus formed would be = 3 when all these conditions are met. + int formed = 0; + + // Dictionary which keeps a count of all the unique characters in the current window. + Map windowCounts = new HashMap(); + + // ans list of the form (window length, left, right) + int[] ans = {-1, 0, 0}; + + while (r < s.length()) { + // Add one character from the right to the window + char c = s.charAt(r); + int count = windowCounts.getOrDefault(c, 0); + windowCounts.put(c, count + 1); + + // If the frequency of the current character added equals to the + // desired count in t then increment the formed count by 1. + if (dictT.containsKey(c) && windowCounts.get(c).intValue() == dictT.get(c).intValue()) { + formed++; + } + + // Try and co***act the window till the point where it ceases to be 'desirable'. + while (l <= r && formed == required) { + c = s.charAt(l); + // Save the smallest window until now. + if (ans[0] == -1 || r - l + 1 < ans[0]) { + ans[0] = r - l + 1; + ans[1] = l; + ans[2] = r; + } + + // The character at the position pointed by the + // `Left` pointer is no longer a part of the window. + windowCounts.put(c, windowCounts.get(c) - 1); + if (dictT.containsKey(c) && windowCounts.get(c).intValue() < dictT.get(c).intValue()) { + formed--; + } + + // Move the left pointer ahead, this would help to look for a new window. + l++; + } + + // Keep expanding the window once we are done co***acting. + r++; + } + + return ans[0] == -1 ? "" : s.substring(ans[1], ans[2] + 1); + } + + public static void main(String[] args) { + System.out.println("target:" + new Solution3().minWindow("ADOBECODEBANC", "ABC")); + System.out.println("target:" + new Solution3().minWindow("a", "a")); + System.out.println("target:" + new Solution3().minWindow("a", "aa")); + System.out.println("target:" + new Solution3().minWindow("a", "b")); + System.out.println("target:" + new Solution3().minWindow("abc", "ac")); + System.out.println("target:" + new Solution3().minWindow("bbaa", "aba")); + System.out.println("target:" + new Solution3().minWindow("abbc", "abc")); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution4.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution4.java" new file mode 100644 index 00000000..2c81b182 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution4.java" @@ -0,0 +1,49 @@ +package cn.lastwhisper.leetcode.array.最小覆盖子串_76_hard; + +class Solution4 { + public String minWindow(String s, String t) { + //把字符串转换为字符数组 + char[] sChars = s.toCharArray(); + char[] pChars = t.toCharArray(); + // + int[] pMap = new int[128]; + //左指针,右指针 + int i = 0, j = 0; // 考察窗口[i,j-1] + //还没有覆盖的字符数量 + int count = pChars.length; + + //初始化记录答案的变量 + int minLen = s.length() + 1, l = 0, r = 0; + + //记录t串中每种字符出现的次数 + for (char pChar : pChars) + pMap[pChar]++; + + while (j < sChars.length) { + + //减小计数 + if (pMap[sChars[j]] > 0) + count--; + pMap[sChars[j]]--; + j++; + + //计数为 0说明区间[i,j-1] 包含 p + while (count == 0) { + + //更新答案 + if (j - i < minLen) { + minLen = j - i; + l = i; + r = j; + } + + pMap[sChars[i]]++; + // 增加计数 + if (pMap[sChars[i]] > 0) + count++; + i++; + } + } + return minLen == s.length() + 1 ? "" : s.substring(l, r); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_242_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_242_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..9c95a7c8 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_242_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,43 @@ +package cn.lastwhisper.leetcode.array.有效的字母异位词_242_简单; + +import java.util.HashMap; +import java.util.Map; + +class Solution1 { + public boolean isAnagram(String s, String t) { + char[] sChar = s.toCharArray(); + char[] tChar = t.toCharArray(); + HashMap map = new HashMap<>(); + for (int i = 0; i < sChar.length; i++) { + Integer num = map.get(sChar[i]); + if (num == null) { + map.put(sChar[i], 1); + } else { + map.put(sChar[i], ++num); + } + } + + for (int i = 0; i < tChar.length; i++) { + Integer num = map.get(tChar[i]); + if (num == null) { + return false; + } else { + map.put(tChar[i], --num); + } + } + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue() != 0) { + return false; + } + } + return true; + } + + public static void main(String[] args) { + //String s = "anagram", t = "nagaram"; + String s = "rat", t = "car"; + + System.out.println(new Solution1().isAnagram(s, t)); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_242_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_242_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..6c53f39c --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_242_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,39 @@ +package cn.lastwhisper.leetcode.array.有效的字母异位词_242_简单; + +class Solution2 { + /** + * https://leetcode-cn.com/problems/valid-anagram/submissions/ + * hash + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public boolean isAnagram(String s, String t) { + if (s.length() != t.length()) { + return false; + } + char[] sChar = s.toCharArray(); + char[] tChar = t.toCharArray(); + byte[] freq = new byte[256]; + for (int i = 0; i < sChar.length; i++) { + freq[sChar[i]]++; + } + + for (int i = 0; i < tChar.length; i++) { + freq[tChar[i]]--; + } + for (int i = 0; i < freq.length; i++) { + if (freq[i] != 0) { + return false; + } + } + return true; + } + + public static void main(String[] args) { + String s = "anagram", t = "nagaram"; + //String s = "rat", t = "car"; + + System.out.println(new Solution2().isAnagram(s, t)); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/Solution1.java" deleted file mode 100644 index 6a4e0582..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/Solution1.java" +++ /dev/null @@ -1,72 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.找到字符串中所有字母异位词_438_中等; - -import java.util.ArrayList; -import java.util.List; - -class Solution1 { - /** - * https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/ - * 核心思想:滑动窗口 - * 时间复杂度:O(n^2) - */ - public List findAnagrams(String s, String p) { - List list = new ArrayList<>(); - // 过滤肯定不符合规则的数据 - if (s == null || s.length() < p.length()) { - return list; - } - int l = 0, r = 0; - char[] sChar = s.toCharArray(); - char[] pChar = p.toCharArray(); - while (l < sChar.length && r < sChar.length) { - // [l,r]不满足异位词 - if (!isAnagram(sChar, l, r, pChar)) { - // [l,r]不满足异位词且窗口大小不满足,扩展右边界 - if ((r - l) != pChar.length) { - r++; - } else { - // [l,r]不满足异位词且窗口大小满足,扩展左边界 - l++; - } - } else { - // [l,r]满足异位词,扩展左边界 - list.add(l); - l++; - } - } - return list; - } - - public boolean isAnagram(char[] sChar, int start, int end, char[] pChar) { - if ((end - start + 1) != pChar.length) { - return false; - } - byte[] freq = new byte[26]; - for (int i = start; i <= end; i++) { - freq[sChar[i] - 'a']++; - } - - for (int i = 0; i < pChar.length; i++) { - freq[pChar[i] - 'a']--; - } - for (int i = 0; i < freq.length; i++) { - if (freq[i] != 0) { - return false; - } - } - return true; - } - - - public static void main(String[] args) { - new Solution1().findAnagrams("cbaebabacd", "abc").forEach(System.out::print); - System.out.println(); - new Solution1().findAnagrams("abab", "ab").forEach(System.out::print); - System.out.println(); - new Solution1().findAnagrams("", "a").forEach(System.out::print);//错误数据 - - //System.out.println(new Solution1().isAnagram(new char[]{'c','b','a'}, new char[]{'a','b','c'})); - - } - -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/Solution2.java" deleted file mode 100644 index 41d3d6e7..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/Solution2.java" +++ /dev/null @@ -1,46 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.找到字符串中所有字母异位词_438_中等; - -import java.util.ArrayList; -import java.util.List; - -class Solution2 { - /** - * https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/ - * 核心思想:滑动窗口 - * 时间复杂度:O(n) - */ - public List findAnagrams(String s, String p) { - if (s == null || s.length() == 0) return new ArrayList<>(); - List res = new ArrayList<>(); - int[] needs = new int[26]; //由于都是小写字母,因此直接用26个长度的数组代替原来的HashMap - int[] window = new int[26]; - int left = 0, right = 0, total = p.length(); //用total检测窗口中是否已经涵盖了p中的字符 - for (char ch : p.toCharArray()) { - needs[ch - 'a']++; - } - while (right < s.length()) { - char chr = s.charAt(right); - if (needs[chr - 'a'] > 0) { - window[chr - 'a']++; - if (window[chr - 'a'] <= needs[chr - 'a']) { - total--; - } - } - while (total == 0) { - if (right - left + 1 == p.length()) { - res.add(left); - } - char chl = s.charAt(left); - if (needs[chl - 'a'] > 0) { - window[chl - 'a']--; - if (window[chl - 'a'] < needs[chl - 'a']) { - total++; - } - } - left++; - } - right++; - } - return res; - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/Solution3.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/Solution3.java" deleted file mode 100644 index 81e15e74..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215_438_\344\270\255\347\255\211/Solution3.java" +++ /dev/null @@ -1,50 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.找到字符串中所有字母异位词_438_中等; - -import java.util.ArrayList; -import java.util.List; - -class Solution3 { - - public List findAnagrams(String s, String p) { - int sl = s.length(); - int pl = p.length(); - char[] sArr = s.toCharArray(); - char[] pArr = p.toCharArray(); - // 保存当前窗口的字符出现次数的哈希表 - char[] sLetters = new char[26]; - // 保存目标字符串字符出现次数的哈希表 - char[] pLetters = new char[26]; - ArrayList ans = new ArrayList<>(sl / pl); - // 填充目标字符串的哈希表 - for (int i = 0; i < pl; i++) { - pLetters[pArr[i] - 'a']++; - } - // 滑动窗口 - int left = 0; - int right = 0; - while (right < sl) { - // 当前字符在数组中的索引 - int cur = sArr[right++] - 'a'; - // 记录窗口中字符的出现次数 - sLetters[cur]++; - // 如果在窗口中的当前字符的出现次数大于目标字符串中该字符的出现次数,即不符合条件,则右移窗口。 - // 无论是字符出现次数多余目标字符串还是字符不在目标字符串数组中,右移窗口后都可以解决。 - while (pLetters[cur] < sLetters[cur]) { - // 这里将位于left上的字符(滑动窗口最左边的字符)从sLetters(记录窗口中字符出现次数的哈希表)中减去(值减一,抽象上等同于把该字符移出滑动窗口),同时left++,完成窗口右移。 - sLetters[sArr[left++] - 'a']--; - } - // 窗口调整完成后,判断当前窗口是否满足条件,即窗口长度和目标字符串长度是否相等。 - if (right - left == pl) ans.add(left); - } - - return ans; - } - - public static void main(String[] args) { - //new Solution2().findAnagrams("cbaebabacd", "abc").forEach(System.out::print); - //System.out.println(); - new Solution3().findAnagrams("abab", "ab").forEach(System.out::print); - System.out.println(); - //new Solution2().findAnagrams("", "a").forEach(System.out::print);//错误数据 - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Performance.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Performance.java" deleted file mode 100644 index d9e6b3c0..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Performance.java" +++ /dev/null @@ -1,49 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.无重复字符的最长子串_3_Medium; - -import java.lang.reflect.Method; -import java.lang.Class; - -// 比较这个工程中 Solution1, Solution5, Solution6, Solution4 和 Solution3 的算法运行效率 -public class Performance { - - public static void testPerformance(String algoClassName, String algoName, String s){ - - try{ - Class algoClass = Class.forName(algoClassName); - Object solution = algoClass.newInstance(); - - // 通过排序函数的Class对象获得排序方法 - Method algoMethod = algoClass.getMethod(algoName, String.class); - - long startTime = System.currentTimeMillis(); - // 调用算法 - Object resObj = algoMethod.invoke(solution, s); - long endTime = System.currentTimeMillis(); - - int res = (Integer)resObj; - System.out.print(algoClassName + " : res = " + res + " "); - System.out.println("Time = " + (endTime-startTime) + " ms" ); - } - catch(Exception e){ - e.printStackTrace(); - } - } - - public static void main(String[] args) { - - int n = 10000000; - - StringBuilder s = new StringBuilder(n); - for(int i = 0 ; i < n ; i ++) - s.append((char)(Math.random()*95 + 32)); - - System.out.println("Test: 10,000,000 length of completely random string:"); - testPerformance("cn.lastwhisper.leetcode.array.滑动窗口.无重复字符的最长子串_3_Medium.Solution1", "lengthOfLongestSubstring", s.toString()); - testPerformance("cn.lastwhisper.leetcode.array.滑动窗口.无重复字符的最长子串_3_Medium.Solution2", "lengthOfLongestSubstring", s.toString()); - testPerformance("cn.lastwhisper.leetcode.array.滑动窗口.无重复字符的最长子串_3_Medium.Solution3", "lengthOfLongestSubstring", s.toString()); - testPerformance("cn.lastwhisper.leetcode.array.滑动窗口.无重复字符的最长子串_3_Medium.Solution4", "lengthOfLongestSubstring", s.toString()); - testPerformance("cn.lastwhisper.leetcode.array.滑动窗口.无重复字符的最长子串_3_Medium.Solution5", "lengthOfLongestSubstring", s.toString()); - testPerformance("cn.lastwhisper.leetcode.array.滑动窗口.无重复字符的最长子串_3_Medium.Solution6", "lengthOfLongestSubstring", s.toString()); - - } -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution1.java" deleted file mode 100644 index d7c5d7eb..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution1.java" +++ /dev/null @@ -1,47 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.无重复字符的最长子串_3_Medium; - -class Solution1 { - /** - * https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/submissions/ - * 核心思想:滑动窗口 - * 时间复杂度: O(len(s)) - * 空间复杂度: O(len(charset)) - */ - public int lengthOfLongestSubstring(String s) { - int[] freq = new int[256]; - int l = 0, r = 0; - int res = 0; - char[] chars = s.toCharArray(); - while (l < chars.length) { - if (r < chars.length && freq[chars[r]] == 0) { - freq[chars[r++]]++; - } else { - freq[chars[l++]]--; - } - res = Math.max(res, (r - l)); - } - return res; - } - - //public int lengthOfLongestSubstring(String s) { - // int[] freq = new int[256]; - // int l = 0, r = 0; - // int res = 0; - // while (l < s.length()) { - // if (r < s.length() && freq[s.charAt(r)] == 0) { - // freq[s.charAt(r++)]++; - // } else { - // freq[s.charAt(l++)]--; - // } - // res = Math.max(res, (r - l)); - // } - // return res; - //} - - public static void main(String[] args) { - System.out.println(new Solution1().lengthOfLongestSubstring("abcabcbb")); - System.out.println(new Solution1().lengthOfLongestSubstring("bbbbb")); - System.out.println(new Solution1().lengthOfLongestSubstring("pwwkew")); - System.out.println(new Solution1().lengthOfLongestSubstring(" ")); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution2.java" deleted file mode 100644 index 06470611..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution2.java" +++ /dev/null @@ -1,45 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.无重复字符的最长子串_3_Medium; - -class Solution2 { - /** - * https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/submissions/ - * 核心思想:滑动窗口,在Solution1的基础上优化 - * 时间复杂度: O(len(s)) - * 空间复杂度: O(len(charset)) - */ - public int lengthOfLongestSubstring(String s) { - byte[] freq = new byte[256]; - int l = 0, r = 0; - int res = 0; - char[] chars = s.toCharArray(); - while (l < chars.length) { - while (r < chars.length && freq[chars[r]] == 0) { - freq[chars[r++]]++; - } - res = Math.max(res, (r - l)); - freq[chars[l++]]--; - } - return res; - } - - //public int lengthOfLongestSubstring(String s) { - // byte[] freq = new byte[256]; - // int l = 0, r = 0; - // int res = 0; - // while (l < s.length()) { - // while (r < s.length() && freq[s.charAt(r)] == 0) { - // freq[s.charAt(r++)]++; - // } - // res = Math.max(res, (r - l)); - // freq[s.charAt(l++)]--; - // } - // return res; - //} - - public static void main(String[] args) { - System.out.println(new Solution2().lengthOfLongestSubstring("abcabcbb")); - System.out.println(new Solution2().lengthOfLongestSubstring("bbbbb")); - System.out.println(new Solution2().lengthOfLongestSubstring("pwwkew")); - System.out.println(new Solution2().lengthOfLongestSubstring(" ")); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution3.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution3.java" deleted file mode 100644 index 2aa5abb1..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution3.java" +++ /dev/null @@ -1,40 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.无重复字符的最长子串_3_Medium;// 3. Longest Substring Without Repeating Characters -// https://leetcode.com/problems/longest-substring-without-repeating-characters/description/ -// -// 滑动窗口 -// 其中使用last[c]保存字符c上一次出现的位置, 用于在右边界发现重复字符时, 快速移动左边界 -// 使用这种方法, 时间复杂度依然为O(n), 但是只需要动r指针, 实际上对整个s只遍历了一次 -// 相较而言, 之前的方法, 需要移动l和r两个指针, 相对于对s遍历了两次 - -import java.util.Arrays; - -// 时间复杂度: O(len(s)) -// 空间复杂度: O(len(charset)) -public class Solution3 { - - public int lengthOfLongestSubstring(String s) { - - int[] last = new int[256]; - Arrays.fill(last, -1); - int l = 0, r = -1; //滑动窗口为s[l...r] - int res = 0; - while (r + 1 < s.length()) { - r++; - if (last[s.charAt(r)] != -1) - l = Math.max(l, last[s.charAt(r)] + 1); - res = Math.max(res, r - l + 1); - last[s.charAt(r)] = r; - } - - return res; - } - - public static void main(String[] args) { - - System.out.println((new Solution3()).lengthOfLongestSubstring("abcabcbb")); - System.out.println((new Solution3()).lengthOfLongestSubstring("bbbbb")); - System.out.println((new Solution3()).lengthOfLongestSubstring("pwwkew")); - System.out.println((new Solution3()).lengthOfLongestSubstring("")); - System.out.println((new Solution3()).lengthOfLongestSubstring(" ")); - } -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution4.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution4.java" deleted file mode 100644 index ce8e8179..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution4.java" +++ /dev/null @@ -1,51 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.无重复字符的最长子串_3_Medium; - -// 3. Longest Substring Without Repeating Characters -// https://leetcode.com/problems/longest-substring-without-repeating-characters/description/ -// -// 课程问答区 @yatkun 提出的方法, -// l每次可以向前跳跃, 而不仅仅是+1 -// 但代价是, 为了获得这个跳跃的位置, 每次需要遍历整个窗口的字符串 -// -// 时间复杂度: O(len(s)*len(charset)) -// 空间复杂度: O(1) -public class Solution4{ - - public int lengthOfLongestSubstring(String s) { - - int l = 0, r = 0; //滑动窗口为s[l...r] - int res = 0; - - while(r < s.length()){ - - int index = isDuplicateChar(s, l, r); - - // 如果s[r]之前出现过 - // l可以直接跳到s[r+1]之前出现的位置 + 1的地方 - if(index != -1) - l = index + 1; - - res = Math.max(res, r-l+1); - r ++; - } - - return res; - } - - // 查看s[l...r-1]之间是否存在s[r] - // 若存在,返回相应的索引, 否则返回-1 - private int isDuplicateChar(String s, int l, int r){ - for(int i = l ; i < r ; i ++) - if(s.charAt(i) == s.charAt(r)) - return i; - return -1; - } - - public static void main(String[] args) { - - System.out.println((new Solution4()).lengthOfLongestSubstring( "abcabcbb" )); - System.out.println((new Solution4()).lengthOfLongestSubstring( "bbbbb" )); - System.out.println((new Solution4()).lengthOfLongestSubstring( "pwwkew" )); - System.out.println((new Solution4()).lengthOfLongestSubstring( "" )); - } -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution5.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution5.java" deleted file mode 100644 index 41abf904..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution5.java" +++ /dev/null @@ -1,38 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.无重复字符的最长子串_3_Medium; - -// 3. Longest Substring Without Repeating Characters -// https://leetcode.com/problems/longest-substring-without-repeating-characters/description/ -// -// 滑动窗口 -// 时间复杂度: O(len(s)) -// 空间复杂度: O(len(charset)) -public class Solution5 { - public int lengthOfLongestSubstring(String s) { - - int[] freq = new int[256]; - - int l = 0, r = -1; //滑动窗口为s[l...r] - int res = 0; - - // 在这里, 循环中止的条件可以是 r + 1 < s.length(), 想想看为什么? - // 感谢课程QQ群 @千千 指出 :) - while( r + 1 < s.length() ){ - - if( r + 1 < s.length() && freq[s.charAt(r+1)] == 0 ) - freq[s.charAt(++r)] ++; - else //freq[s[r+1]] == 1 - freq[s.charAt(l++)] --; - - res = Math.max(res, r-l+1); - } - - return res; - } - - public static void main(String[] args) { - System.out.println((new Solution5()).lengthOfLongestSubstring( "abcabcbb" )); - System.out.println((new Solution5()).lengthOfLongestSubstring( "bbbbb" )); - System.out.println((new Solution5()).lengthOfLongestSubstring( "pwwkew" )); - System.out.println((new Solution5()).lengthOfLongestSubstring( "" )); - } -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution6.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution6.java" deleted file mode 100644 index 9ae65b79..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262_3_Medium/Solution6.java" +++ /dev/null @@ -1,42 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.无重复字符的最长子串_3_Medium; - -// 3. Longest Substring Without Repeating Characters -// https://leetcode.com/problems/longest-substring-without-repeating-characters/description/ -// -// 滑动窗口的另一个实现, 仅做参考 -// 时间复杂度: O(len(s)) -// 空间复杂度: O(len(charset)) -public class Solution6 { - public int lengthOfLongestSubstring(String s) { - - int[] freq = new int[256]; - - int l = 0, r = -1; //滑动窗口为s[l...r] - int res = 0; - - while(r + 1 < s.length()){ - - while(r + 1 < s.length() && freq[s.charAt(r+1)] == 0) - freq[s.charAt(++r)] ++; - - res = Math.max(res, r - l + 1); - - if(r + 1 < s.length()){ - freq[s.charAt(++r)] ++; - assert(freq[s.charAt(r)] == 2); - while(l <= r && freq[s.charAt(r)] == 2) - freq[s.charAt(l++)] --; - } - } - - return res; - } - - public static void main(String[] args) { - - System.out.println((new Solution6()).lengthOfLongestSubstring( "abcabcbb" )); - System.out.println((new Solution6()).lengthOfLongestSubstring( "bbbbb" )); - System.out.println((new Solution6()).lengthOfLongestSubstring( "pwwkew" )); - System.out.println((new Solution6()).lengthOfLongestSubstring( "" )); - } -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution1.java" deleted file mode 100644 index b3891057..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution1.java" +++ /dev/null @@ -1,81 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.最小覆盖子串_76_hard; - -class Solution1 { - /** - * https://leetcode-cn.com/problems/minimum-window-substring/ - * 核心思想:滑动窗口 - * 超时 - */ - public String minWindow(String s, String t) { - if (s.length() < t.length()) return "";//"a", "aa" - if (s.equals(t)) return s;//"a", "a" - // 用于判断s子串是否包含t - int[] map = new int[128]; - String target = "";//"abc", "ac";"a", "b" - int l = 0, r = 0; - while (l <= s.length() && r <= s.length()) { - if (!isSub(s.substring(l, r), t, map)) { - // 不断增加 r 指针扩大窗口 [l, r],直到窗口中的字符串符合要求 - r++; - } else { - // 不断增加 l 指针缩小窗口 [l, r],直到窗口中的字符串不再符合要求 - if ("".equals(target)) { - target = s.substring(l, r); - } else { - target = target.length() > s.substring(l, r).length() ? s.substring(l, r) : target; - } - l++; - } - - } - return target; - } - - /** - * sub是否包含t - */ - public boolean isSub(String sub, String t, int[] map) { - if (sub.length() < t.length()) return false;//过滤肯定不包含 - boolean flag = true; - for (int i = 0; i < sub.length(); i++) { - map[sub.charAt(i)] += 1; - } - // 检验t在sub是否完全出现过 - for (int i = 0; i < t.length(); i++) { - if (map[t.charAt(i)] > 0) { - //t在sub出现过 - map[t.charAt(i)] -= 1; - } else { - //t在sub没出现过 - flag = false; - } - } - // 检验sub是否完全包含t - for (int i = 0; i < t.length(); i++) { - if (map[t.charAt(i)] < 0) { - flag = false; - } - } - // 清空 - for (int i = 0; i < sub.length(); i++) { - map[sub.charAt(i)] = 0; - } - return flag; - } - - public static void main(String[] args) { - System.out.println("target:" + new Solution1().minWindow("ADOBECODEBANC", "ABC")); - System.out.println("target:" + new Solution1().minWindow("a", "a")); - System.out.println("target:" + new Solution1().minWindow("a", "aa")); - System.out.println("target:" + new Solution1().minWindow("a", "b")); - System.out.println("target:" + new Solution1().minWindow("abc", "ac")); - System.out.println("target:" + new Solution1().minWindow("bbaa", "aba")); - System.out.println("target:" + new Solution1().minWindow("abbc", "abc")); - //int[] arr = new int[128]; - //System.out.println(new Solution1().isSub("ADCB", "ABC", arr)); - //System.out.println(new Solution1().isSub("ADQCB", "ABC", arr)); - //System.out.println(new Solution1().isSub("ADeB", "ABC", arr)); - //System.out.println(new Solution1().isSub("abbc", "abc", arr)); - //System.out.println(new Solution1().isSub("bbaa", "aba", arr)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution2.java" deleted file mode 100644 index acc9e6ec..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution2.java" +++ /dev/null @@ -1,82 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.最小覆盖子串_76_hard; - -class Solution2 { - /** - * https://leetcode-cn.com/problems/minimum-window-substring/ - * 核心思想:滑动窗口 - * 超时 - */ - public String minWindow(String s, String t) { - if (s.length() < t.length()) return "";//"a", "aa" - if (s.equals(t)) return s;//"a", "a" - char[] ss = s.toCharArray(); - // 用于判断s子串是否包含t - int[] map = new int[128]; - String target = "";//"abc", "ac";"a", "b" - int l = 0, r = 0; - while (l <= ss.length && r <= ss.length) { - if (!isSub(ss, l, r, t, map)) { - // 不断增加 r 指针扩大窗口 [l, r],直到窗口中的字符串符合要求 - r++; - } else { - // 不断增加 l 指针缩小窗口 [l, r],直到窗口中的字符串不再符合要求 - if ("".equals(target)) { - target = s.substring(l, r); - } else { - target = target.length() > s.substring(l, r).length() ? s.substring(l, r) : target; - } - l++; - } - - } - return target; - } - - /** - * sub是否包含t - */ - public boolean isSub(char[] sub, int start, int end, String t, int[] map) { - if (sub.length < t.length()) return false;//过滤肯定不包含 - boolean flag = true; - for (int i = start; i < end; i++) { - map[sub[i]] += 1; - } - // 检验t在sub是否完全出现过 - for (int i = 0; i < t.length(); i++) { - if (map[t.charAt(i)] > 0) { - //t在sub出现过 - map[t.charAt(i)] -= 1; - } else { - //t在sub没出现过 - flag = false; - } - } - // 检验sub是否完全包含t - for (int i = 0; i < t.length(); i++) { - if (map[t.charAt(i)] < 0) { - flag = false; - } - } - // 清空 - for (int i = start; i < end; i++) { - map[sub[i]] = 0; - } - return flag; - } - - public static void main(String[] args) { - System.out.println("target:" + new Solution2().minWindow("ADOBECODEBANC", "ABC")); - System.out.println("target:" + new Solution2().minWindow("a", "a")); - System.out.println("target:" + new Solution2().minWindow("a", "aa")); - System.out.println("target:" + new Solution2().minWindow("a", "b")); - System.out.println("target:" + new Solution2().minWindow("abc", "ac")); - System.out.println("target:" + new Solution2().minWindow("bbaa", "aba")); - System.out.println("target:" + new Solution2().minWindow("abbc", "abc")); - //int[] arr = new int[128]; - //System.out.println(new Solution2().isSub("ADCB", "ABC", arr)); - //System.out.println(new Solution2().isSub("ADQCB", "ABC", arr)); - //System.out.println(new Solution2().isSub("ADeB", "ABC", arr)); - //System.out.println(new Solution2().isSub("abbc", "abc", arr)); - //System.out.println(new Solution2().isSub("bbaa", "aba", arr)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution3.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution3.java" deleted file mode 100644 index c7521ecb..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution3.java" +++ /dev/null @@ -1,87 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.最小覆盖子串_76_hard; - -import java.util.HashMap; -import java.util.Map; - -class Solution3 { - public String minWindow(String s, String t) { - - if (s.length() == 0 || t.length() == 0) { - return ""; - } - - // Dictionary which keeps a count of all the unique characters in t. - Map dictT = new HashMap(); - for (int i = 0; i < t.length(); i++) { - int count = dictT.getOrDefault(t.charAt(i), 0); - dictT.put(t.charAt(i), count + 1); - } - - // Number of unique characters in t, which need to be present in the desired window. - int required = dictT.size(); - - // Left and Right pointer - int l = 0, r = 0; - - // formed is used to keep track of how many unique characters in t - // are present in the current window in its desired frequency. - // e.g. if t is "AABC" then the window must have two A's, one B and one C. - // Thus formed would be = 3 when all these conditions are met. - int formed = 0; - - // Dictionary which keeps a count of all the unique characters in the current window. - Map windowCounts = new HashMap(); - - // ans list of the form (window length, left, right) - int[] ans = {-1, 0, 0}; - - while (r < s.length()) { - // Add one character from the right to the window - char c = s.charAt(r); - int count = windowCounts.getOrDefault(c, 0); - windowCounts.put(c, count + 1); - - // If the frequency of the current character added equals to the - // desired count in t then increment the formed count by 1. - if (dictT.containsKey(c) && windowCounts.get(c).intValue() == dictT.get(c).intValue()) { - formed++; - } - - // Try and co***act the window till the point where it ceases to be 'desirable'. - while (l <= r && formed == required) { - c = s.charAt(l); - // Save the smallest window until now. - if (ans[0] == -1 || r - l + 1 < ans[0]) { - ans[0] = r - l + 1; - ans[1] = l; - ans[2] = r; - } - - // The character at the position pointed by the - // `Left` pointer is no longer a part of the window. - windowCounts.put(c, windowCounts.get(c) - 1); - if (dictT.containsKey(c) && windowCounts.get(c).intValue() < dictT.get(c).intValue()) { - formed--; - } - - // Move the left pointer ahead, this would help to look for a new window. - l++; - } - - // Keep expanding the window once we are done co***acting. - r++; - } - - return ans[0] == -1 ? "" : s.substring(ans[1], ans[2] + 1); - } - - public static void main(String[] args) { - System.out.println("target:" + new Solution3().minWindow("ADOBECODEBANC", "ABC")); - System.out.println("target:" + new Solution3().minWindow("a", "a")); - System.out.println("target:" + new Solution3().minWindow("a", "aa")); - System.out.println("target:" + new Solution3().minWindow("a", "b")); - System.out.println("target:" + new Solution3().minWindow("abc", "ac")); - System.out.println("target:" + new Solution3().minWindow("bbaa", "aba")); - System.out.println("target:" + new Solution3().minWindow("abbc", "abc")); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution4.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution4.java" deleted file mode 100644 index fce81bdb..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_hard/Solution4.java" +++ /dev/null @@ -1,49 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.最小覆盖子串_76_hard; - -class Solution4 { - public String minWindow(String s, String t) { - //把字符串转换为字符数组 - char[] sChars = s.toCharArray(); - char[] pChars = t.toCharArray(); - // - int[] pMap = new int[128]; - //左指针,右指针 - int i = 0, j = 0; // 考察窗口[i,j-1] - //还没有覆盖的字符数量 - int count = pChars.length; - - //初始化记录答案的变量 - int minLen = s.length() + 1, l = 0, r = 0; - - //记录t串中每种字符出现的次数 - for (char pChar : pChars) - pMap[pChar]++; - - while (j < sChars.length) { - - //减小计数 - if (pMap[sChars[j]] > 0) - count--; - pMap[sChars[j]]--; - j++; - - //计数为 0说明区间[i,j-1] 包含 p - while (count == 0) { - - //更新答案 - if (j - i < minLen) { - minLen = j - i; - l = i; - r = j; - } - - pMap[sChars[i]]++; - // 增加计数 - if (pMap[sChars[i]] > 0) - count++; - i++; - } - } - return minLen == s.length() + 1 ? "" : s.substring(l, r); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_Medium/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_Medium/Solution1.java" deleted file mode 100644 index 898b86b7..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_Medium/Solution1.java" +++ /dev/null @@ -1,41 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.长度最小的子数组_209_Medium; - -/** - * @author lastwhisper - */ -public class Solution1 { - /** - * https://leetcode-cn.com/problems/minimum-size-subarray-sum/ - * 暴力解法 - * 时间复杂度:O(n^3) - * 空间复杂度:O(1) - */ - public int minSubArrayLen(int s, int[] nums) { - if (s <= 0 || nums == null) { - throw new IllegalArgumentException("Illegal Argument"); - } - int res = nums.length + 1; - for (int l = 0; l < nums.length; l++) { - for (int r = l; r < nums.length; r++) { - int sum = 0; - // 求[l...r]子数组之和 - for (int i = l; i < r; i++) { - sum += nums[i]; - } - if (sum >= s) { - res = Math.min(res, r - l + 1); - } - } - } - if (res == nums.length + 1) { - return 0; - } - return res; - } - - public static void main(String[] args) { - int[] nums = {2, 3, 1, 2, 4, 3}; - int s = 7; - System.out.println((new Solution1()).minSubArrayLen(s, nums)); - } -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_Medium/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_Medium/Solution2.java" deleted file mode 100644 index 85d3de20..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_Medium/Solution2.java" +++ /dev/null @@ -1,46 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.长度最小的子数组_209_Medium; - -/** - * 209. 长度最小的子数组 - * https://leetcode-cn.com/problems/minimum-size-subarray-sum/ - * @author lastwhisper - */ -public class Solution2 { - // 优化暴力解法 - - public int minSubArrayLen(int s, int[] nums) { - if (s <= 0 || nums == null) { - throw new IllegalArgumentException("Illegal Argument"); - } - - int[] sum = new int[nums.length + 1]; - sum[0] = 0; - // nums=> 2, 3, 1, 2, 4, 3 - // sum=>0, 2, 5, 6, 8, 12,7 - // sums[i]存放nums[0...i-1]的和 - for (int i = 1; i <= nums.length; i++) { - sum[i] = sum[i - 1] + nums[i - 1]; - } - - int res = nums.length + 1; - for (int l = 0; l < nums.length; l++) { - for (int r = l; r < nums.length; r++) { - // sum[r + 1] - sum[l]快速求出nums[l...r]之和 - if (sum[r + 1] - sum[l] >= s) { - res = Math.min(res, r - l + 1); - } - } - } - - if (res == nums.length + 1) { - res = 0; - } - return res; - } - - public static void main(String[] args) { - int[] nums = {2, 3, 1, 2, 4, 3}; - int s = 7; - System.out.println((new Solution2()).minSubArrayLen(s, nums)); - } -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_Medium/Solution3.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_Medium/Solution3.java" deleted file mode 100644 index e3d5ced6..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_Medium/Solution3.java" +++ /dev/null @@ -1,48 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.长度最小的子数组_209_Medium; - -/** - * @author lastwhisper - */ -public class Solution3 { - /** - * https://leetcode-cn.com/problems/minimum-size-subarray-sum/ - * 核心思想:滑动窗口,两个指针从起始点向前推进,维护一个窗口 - * 时间复杂度:O(n) - * 空间复杂度:O(1) - */ - public int minSubArrayLen(int s, int[] nums) { - if (s <= 0 || nums == null) { - throw new IllegalArgumentException("Illegal Argument"); - } - // nums[l...r]是一个滑动窗口 - int l = 0, r = -1; - int sum = 0; - int res = nums.length + 1; - // 窗口的左边界在数组范围内,则循环继续 - while (l < nums.length) { - if (r < nums.length - 1 && sum < s) { - //r未到头且sums,需要动态缩小窗口左边界 - sum -= nums[l]; - l++; - } - if (sum >= s) { - res = Math.min(res, r - l + 1); - } - } - - if (res == nums.length + 1) { - res = 0; - } - return res; - } - - public static void main(String[] args) { - int[] nums = {2, 3, 1, 2, 4, 3}; - int s = 7; - System.out.println((new Solution3()).minSubArrayLen(s, nums)); - } -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_Medium/Solution4.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_Medium/Solution4.java" deleted file mode 100644 index 0e014fc2..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_Medium/Solution4.java" +++ /dev/null @@ -1,51 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.长度最小的子数组_209_Medium; - -/** - * 209. 长度最小的子数组 - * https://leetcode-cn.com/problems/minimum-size-subarray-sum/ - * @author lastwhisper - */ -public class Solution4 { - // 滑动窗口 - // 时间复杂度:O(n) - // 空间复杂度:O(1) - public int minSubArrayLen(int s, int[] nums) { - if (s <= 0 || nums == null) { - throw new IllegalArgumentException("Illegal Argument"); - } - - // nums[l...r]是一个滑动窗口 - int l = 0, r = -1; - int sum = 0; - int res = nums.length + 1; - // 窗口的右边界在数组范围内,则循环继续 - while (r < nums.length - 1) { - while (r < nums.length - 1 && sum < s) { - r++; - sum += nums[r]; - } - if (sum >= s) { - res = Math.min(res, r - l + 1); - } - while (l < nums.length && sum >= s) { - sum -= nums[l]; - l++; - if (sum >= s) { - res = Math.min(res, r - l + 1); - } - } - } - - if (res == nums.length + 1) { - res = 0; - } - return res; - } - - public static void main(String[] args) { - int[] nums = {2, 3, 1, 2, 4, 3}; - int s = 7; - System.out.println((new Solution4()).minSubArrayLen(s, nums)); - } - -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_Medium/Solution5.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_Medium/Solution5.java" deleted file mode 100644 index 3143d09b..00000000 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_Medium/Solution5.java" +++ /dev/null @@ -1,71 +0,0 @@ -package cn.lastwhisper.leetcode.array.滑动窗口.长度最小的子数组_209_Medium; - -/** - * 209. 长度最小的子数组 - * https://leetcode-cn.com/problems/minimum-size-subarray-sum/ - * @author lastwhisper - */ -public class Solution5 { - // 二分搜索 - // 扩展 Solution5 的方法。对于每一个l, 可以使用二分搜索法搜索r - // 时间复杂度: O(nlogn) - // 空间复杂度: O(n) - public int minSubArrayLen(int s, int[] nums) { - - if(s <= 0 || nums == null) - throw new IllegalArgumentException("Illigal Arguments"); - - // sums[i]存放nums[0...i-1]的和 - int[] sums = new int[nums.length + 1]; - sums[0] = 0; - for(int i = 1 ; i <= nums.length ; i ++) - sums[i] = sums[i-1] + nums[i-1]; - - int res = nums.length + 1; - for(int l = 0 ; l < nums.length - 1 ; l ++){ - // Java类库中没有内置的lowerBound方法, - // 我们需要自己实现一个基于二分搜索的lowerBound:) - int r = lowerBound(sums, sums[l] + s); - if(r != sums.length){ - res = Math.min(res, r - l); - } - } - - if(res == nums.length + 1) - return 0; - return res; - } - - // 在有序数组nums中寻找大于等于target的最小值 - // 如果没有(nums数组中所有值都小于target),则返回nums.length - private int lowerBound(int[] nums, int target){ - - if(nums == null /*|| !isSorted(nums)*/) - throw new IllegalArgumentException("Illegal argument nums in lowerBound."); - - int l = 0, r = nums.length; // 在nums[l...r)的范围里寻找解 - while(l != r){ - int mid = l + (r - l) / 2; - if(nums[mid] >= target) - r = mid; - else - l = mid + 1; - } - - return l; - } - - private boolean isSorted(int[] nums){ - for(int i = 1 ; i < nums.length ; i ++) - if(nums[i] < nums[i-1]) - return false; - return true; - } - - public static void main(String[] args) { - - int[] nums = {2, 3, 1, 2, 4, 3}; - int s = 7; - System.out.println((new Solution5()).minSubArrayLen(s, nums)); - } -} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250_11_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250_11_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..5b285110 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250_11_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,31 @@ +package cn.lastwhisper.leetcode.array.盛最多水的容器_11_中等; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/container-with-most-water/ + * 编号:11 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:暴力组合高和底 + * ------------------------------------------------------------------- + * 时间复杂度:O(n^2) + * 空间复杂度:O(1) + */ + public int maxArea(int[] height) { + int max = Integer.MIN_VALUE, h; + for (int i = 0; i < height.length; i++) { + for (int j = i + 1; j < height.length; j++) { + h = Math.min(height[i], height[j]);// 最小高度 + max = Math.max(max, h * (j - i)); + } + } + return max; + } + + public static void main(String[] args) { + Assert.assertEquals(49, new Solution1().maxArea(new int[]{1, 8, 6, 2, 5, 4, 8, 3, 7})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250_11_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250_11_\344\270\255\347\255\211/Solution2.java" new file mode 100644 index 00000000..2c7c9213 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\233\233\346\234\200\345\244\232\346\260\264\347\232\204\345\256\271\345\231\250_11_\344\270\255\347\255\211/Solution2.java" @@ -0,0 +1,34 @@ +package cn.lastwhisper.leetcode.array.盛最多水的容器_11_中等; + +import org.junit.Assert; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/container-with-most-water/ + * 编号:11 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:双指针(对撞指针) + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public int maxArea(int[] height) { + int l = 0, r = height.length - 1, max = Integer.MIN_VALUE; + while (l < r) { + if (height[l] < height[r]) { + max = Math.max(max, height[l] * (r - l)); + l++; + } else { + max = Math.max(max, height[r] * (r - l)); + r--; + } + } + return max; + } + + public static void main(String[] args) { + Assert.assertEquals(49, new Solution2().maxArea(new int[]{1, 8, 6, 2, 5, 4, 8, 3, 7})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\247\273\345\212\250\351\233\266_283_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\247\273\345\212\250\351\233\266_283_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..08cf49e7 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\247\273\345\212\250\351\233\266_283_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,44 @@ +package cn.lastwhisper.leetcode.array.移动零_283_简单; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Solution1 { + /** + * 题目地址:https://leetcode.cn/problems/move-zeroes/ + * 编号:283 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ + public void moveZeroes(int[] nums) { + // 缓存非0元素 + List nonZeroElements = new ArrayList<>(); + // 找出非0元素并将它缓存进nonZeroElements + for (int i = 0; i < nums.length; i++) { + if (nums[i] != 0) { + nonZeroElements.add(nums[i]); + } + } + // 将非0元素放入原数组中 + for (int i = 0; i < nonZeroElements.size(); i++) { + nums[i] = nonZeroElements.get(i); + } + // 将原数组剩余的位置放置为0 + for (int i = nonZeroElements.size(); i < nums.length; i++) { + nums[i] = 0; + } + } + + //以下为测试代码 + public static void main(String[] args) { + int[] arr = {0, 1, 0, 3, 12}; + new Solution1().moveZeroes(arr); + System.out.println(Arrays.toString(arr)); + } +} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\247\273\345\212\250\351\233\266_283_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\247\273\345\212\250\351\233\266_283_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..b55ff636 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\247\273\345\212\250\351\233\266_283_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,41 @@ +package cn.lastwhisper.leetcode.array.移动零_283_简单; + + +import java.util.Arrays; + +public class Solution2 { + /** + * 题目地址:https://leetcode.cn/problems/move-zeroes/ + * 编号:283 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public void moveZeroes(int[] nums) { + // k保证从[0,...,k)均为非零元素 + int k = 0; + // 遍历到第i个元素后,保证[0,...,i]中所有非零元素, + // 都按顺序排列在[0,...,k)中 + for (int i = 0; i < nums.length; i++) { + if (nums[i] != 0) { + nums[k] = nums[i]; + k++; + } + } + // 同时保证[k,...,nums.length]中均为零元素 + for (int i = k; i < nums.length; i++) { + nums[i] = 0; + } + } + + //以下为测试代码 + public static void main(String[] args) { + int[] arr = {0, 1, 0, 3, 12}; + new Solution2().moveZeroes(arr); + System.out.println(Arrays.toString(arr)); + } +} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\247\273\345\212\250\351\233\266_283_\347\256\200\345\215\225/Solution3.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\247\273\345\212\250\351\233\266_283_\347\256\200\345\215\225/Solution3.java" new file mode 100644 index 00000000..b96bbb3c --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\247\273\345\212\250\351\233\266_283_\347\256\200\345\215\225/Solution3.java" @@ -0,0 +1,44 @@ +package cn.lastwhisper.leetcode.array.移动零_283_简单; + + +import java.util.Arrays; + +public class Solution3 { + /** + * 题目地址:https://leetcode.cn/problems/move-zeroes/ + * 编号:283 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:快慢指针 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public void moveZeroes(int[] nums) { + // k保证从[0,...,k)均为非零元素,k 表示0的索引 + int k = 0; + // temp用于交换时暂存数据 + int temp; + // 遍历到第i个元素后,保证[0,...,i]中所有非零元素,都按顺序排列在[0,...,k)中 + // 同时保证[k,...,i]中均为零元素 + for (int i = 0; i < nums.length; i++) { + if (nums[i] != 0) { + if (i != k) { // 防止数组本身就是“有序”,这里的有序指 + temp = nums[k]; + nums[k] = nums[i]; + nums[i] = temp; + } + k++; + } + } + } + + //以下为测试代码 + public static void main(String[] args) { + //int[] arr = {0, 1, 0, 3, 12}; + int[] arr = {0, 0, 0, 0, 0}; + new Solution3().moveZeroes(arr); + System.out.println(Arrays.toString(arr)); + } +} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\247\273\351\231\244\345\205\203\347\264\240_27_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\247\273\351\231\244\345\205\203\347\264\240_27_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..e5be0ff3 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\247\273\351\231\244\345\205\203\347\264\240_27_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,45 @@ +package cn.lastwhisper.leetcode.array.移除元素_27_简单; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/min-stack/ + * 编号:27 + * ------------------------------------------------------------------- + * 思考: + * 特殊场景1:数组本身“有序” + * num=[1,1,1,1,1],Val=1 + * ------------------------------------------------------------------- + * 思路: + * 快慢指针 + * 1、记录val的索引slow + * 2、遍历,找到非val的索引i后,交换i和pos位置的值 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public int removeElement(int[] nums, int val) { + // 特判 + if (nums == null || nums.length == 0) { + return 0; + } + // 区间[0,...,slow)均为不等于val的元素,slow为val的索引 + int slow = 0; + for (int i = 0; i < nums.length; i++) { + if (nums[i] != val) { + if (slow != i) { // 防止数组本身就是“有序” + nums[slow] = nums[i]; + } + slow++; + } + } + return slow; + } + + public static void main(String[] args) { + //Assert.assertEquals(2, new Solution1().removeElement(new int[]{3, 2, 2, 3}, 3)); + Assert.assertEquals(2, new Solution1().removeElement(new int[]{2, 2, 3, 3}, 3)); + + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\247\273\351\231\244\345\205\203\347\264\240_27_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\247\273\351\231\244\345\205\203\347\264\240_27_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..62da8322 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\247\273\351\231\244\345\205\203\347\264\240_27_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,46 @@ +package cn.lastwhisper.leetcode.array.移除元素_27_简单; + +import org.junit.Assert; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/min-stack/ + * 编号:27 + * ------------------------------------------------------------------- + * 思考: + * 特殊场景2:数组中只有少量待删除数据 + * num=[1,2,3,5,4],Val=4 + * num=[4,1,2,3,5],Val=4 + * ------------------------------------------------------------------- + * 思路: + * 快慢指针 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public int removeElement(int[] nums, int val) { + // 特判 + if (nums == null || nums.length == 0) { + return 0; + } + // 区间[0,...,slow)均为不等于val的元素,slow为val的索引 + int i = 0; + int n = nums.length - 1; + while (i < n) { + if (nums[i] == val) { + nums[i] = nums[n]; + n--; + } else { + i++; + } + } + + return i; + } + + public static void main(String[] args) { + //Assert.assertEquals(2, new Solution1().removeElement(new int[]{3, 2, 2, 3}, 3)); + Assert.assertEquals(2, new Solution2().removeElement(new int[]{2, 2, 3, 3}, 3)); + + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/Solution1.java" new file mode 100644 index 00000000..c5426aee --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/Solution1.java" @@ -0,0 +1,61 @@ +package cn.lastwhisper.leetcode.array.缺失的第一个正数_41_困难; + +class Solution1 { + + /** + * https://leetcode-cn.com/problems/first-missing-positive/ + * 核心思路:输入数组值映射到数组下标,修改下标对应的值标识该数组值出现过, + * 最后统计数组第一个未标识的下标即为结果 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + * ------------------------------------------------------------------- + * 此思路无法应对输入数组中存在一个很大的值 + */ + public int firstMissingPositive(int[] nums) { + //特殊情况三:输入数组为空 + if (nums.length <= 0) { + return 1; + } + int max = nums[0]; + for (int i = 0; i < nums.length; i++) { + // 特殊情况一:数组中有负数 + if (nums[i] < 0) { + nums[i] = 0; + } + if (nums[i] > max) { + max = nums[i]; + } + } + int[] arr = new int[max + 2]; + for (int num : nums) { + arr[num]++; + } + + for (int i = 0; i < arr.length; i++) { + // 特殊情况二:输入数组第一个数值大于1 + if (i == 0 && arr[i] == 0) { + continue; + } + if (arr[i] == 0) { + return i; + } + } + + return -1; + } + + /** + * 题目: 给定一个未排序的整数数组,找出其中没有出现的最小的正整数 + * 说明: 你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。 + */ + public static void main(String[] args) { + //int[] arr = new int[]{1, 2, 0};//3 + //int[] arr = new int[]{3, 4, -1, 1};//2 //特殊情况一:输入数组中有负数 + //int[] arr = new int[]{7, 8, 9, 11, 12};//1 //特殊情况二:输入数组第一个数值大于1 + //int[] arr = new int[]{};//1 //特殊情况三:输入数组为空 + int[] arr = new int[]{1, 2, 3, 10, 2147483647, 9};//1 //特殊情况四:输入数组值过大 + System.out.println(new Solution1().firstMissingPositive(arr)); + //System.out.println(Integer.MAX_VALUE==2147483647); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/Solution2.java" new file mode 100644 index 00000000..4748e957 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/Solution2.java" @@ -0,0 +1,80 @@ +package cn.lastwhisper.leetcode.array.缺失的第一个正数_41_困难; + +class Solution2 { + + /** + * https://leetcode-cn.com/problems/first-missing-positive/ + * 核心思路:使用数组值当做下标 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + * ------------------------------------------------------------------- + * + */ + public int firstMissingPositive(int[] nums) { + + // 处理负数和0,置为大于输入数组长度的一个整数即可 + for (int i = 0; i < nums.length; i++) { + if (nums[i] <= 0) { + nums[i] = Integer.MAX_VALUE; + } + } + + // 将所有出现的正整数,且值在数组长度内,置为负数 + for (int i = 0; i < nums.length; i++) { + int absNum = Math.abs(nums[i]); + /* + * 将[数组值-1]的值当做下标,并将该下标的值置为负, + * 没有被置为负数的数组值,说明它没有后一位数 + * + * absNum>nums.length,有三种情况 + * 1.负数 + * 2.0 + * 3.输入数组中本身就有一个很大的值(此时数组肯定不连续) + */ + if (absNum <= nums.length) { + /* + * 这个负数不能随便写,一定是-nums[absNum - 1] + * 比如nums={2,2} + * 情况一:nums[absNum - 1] = -Math.abs(nums[absNum - 1]) + * 第一次循环nums={2,-2},第二次循环还是nums={2,-2} + * 情况二:随便写一个负数,nums[absNum - 1] = -1 + * 第一次循环nums={2,-1},第二次循环还是nums={-1,-1} + * + */ + nums[absNum - 1] = -Math.abs(nums[absNum - 1]); + } + } + /* + * 处理不连续的数组和连续的数组 + * (1)长度为5的数组里面有一个100——此时缺失的数一定小于100, + * 且为一个没有帮它置为负数的值 + * (2)长度为100的连续数组,最大值100——此时缺失的数一定为100+1 + */ + for (int i = 0; i < nums.length; i++) { + if (nums[i] > 0) { + return i + 1; + } + } + + // 处理空数组 + return nums.length + 1; + } + + /** + * 题目: 给定一个未排序的整数数组,找出其中没有出现的最小的正整数 + * 说明: 你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。 + */ + public static void main(String[] args) { + //int[] arr = new int[]{1, 2, 0};//3 + //int[] arr = new int[]{3, 4, -1, 1};//2 //特殊情况一:输入数组中有负数 + //int[] arr = new int[]{7, 8, 9, 11, 12};//1 //特殊情况二:输入数组第一个数值大于1 + //int[] arr = new int[]{};//1 //特殊情况三:输入数组为空 + //int[] arr = new int[]{1, 2, 3, 10, 2147483647, 9};//1 //特殊情况四:输入数组值过大 + //int[] arr = new int[]{1};//2 + //int[] arr = new int[]{0};//1 + //int[] arr = new int[]{2,2};//1 + int[] arr = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};//10 + System.out.println(new Solution2().firstMissingPositive(arr)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/YourVersion1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/YourVersion1.java" similarity index 94% rename from "algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/YourVersion1.java" rename to "algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/YourVersion1.java" index 8fe4f73a..84f9bdd0 100644 --- "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\346\225\260\347\273\204\345\200\274\345\275\223\344\270\213\346\240\207/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/YourVersion1.java" +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\347\274\272\345\244\261\347\232\204\347\254\254\344\270\200\344\270\252\346\255\243\346\225\260_41_\345\233\260\351\232\276/YourVersion1.java" @@ -1,4 +1,4 @@ -package cn.lastwhisper.leetcode.array.数组值当下标.缺失的第一个正数_41_困难; +package cn.lastwhisper.leetcode.array.缺失的第一个正数_41_困难; class YourVersion1 { diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\350\236\272\346\227\213\347\237\251\351\230\265_54_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\350\236\272\346\227\213\347\237\251\351\230\265_54_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..494ce3ce --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\350\236\272\346\227\213\347\237\251\351\230\265_54_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,54 @@ +package cn.lastwhisper.leetcode.array.螺旋矩阵_54_中等; + +import java.util.ArrayList; +import java.util.List; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/spiral-matrix/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度:O(n^2) + * 空间复杂度:O(n^2) + */ + public List spiralOrder(int[][] matrix) { + if (matrix == null || matrix.length == 0) return new ArrayList<>(); + List result = new ArrayList<>(matrix.length * matrix[0].length); + // nowColumn当前所在列、totalColumn总列数、nowRow当前所在行、totalRow总行数 + int nowColumn = 0, totalColumn = matrix[0].length - 1, nowRow = 0, totalRow = matrix.length - 1; + // 顺时针遍历 + while (nowColumn <= totalColumn && nowRow <= totalRow) { + //只有一列,不需要从左到右 + for (int i = nowColumn; i <= totalColumn; i++) {//第一步 从左到右 + result.add(matrix[nowRow][i]); + } + //只有一行,不需要从上到下 + for (int i = nowRow + 1; i <= totalRow; i++) {//第二步 从上到下 + result.add(matrix[i][totalColumn]); + } + if (nowRow != totalRow) {//同行,不需要从右向左遍历 + for (int i = totalColumn - 1; i >= nowColumn; i--) {//第三步 从右向左 + result.add(matrix[totalRow][i]); + } + } + if (nowColumn != totalColumn) {//同列,不需要从下到上遍历 + for (int i = totalRow - 1; i > nowRow; i--) {// 第四步 从下到上 + result.add(matrix[i][nowColumn]); + } + } + nowColumn++; + nowRow++; + totalColumn--; + totalRow--; + } + return result; + } + + public static void main(String[] args) { + int[][] matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; + System.out.println(new Solution1().spiralOrder(matrix)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..e37115a5 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,62 @@ +package cn.lastwhisper.leetcode.array.错误的集合_645_简单; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +class Solution1 { + /** + * https://leetcode-cn.com/problems/set-mismatch/ + * ------------------------------------------------------------------- + * 数据特征: + * 输入:数组、1~n整数、无序、存在重复数据、不一定包含丢失数据 + * 输出:数组[重复数据,丢失数据]、1~n+1整数、 + * ------------------------------------------------------------------- + * 思路: + * 使用两个set集合,set1找出重复数据,set2记录1~length+1, + * set2.removeAll(set1)得到丢失数据。 + * 特殊情况:[1,1] + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ + public int[] findErrorNums(int[] nums) { + if (nums.length == 2) { + if (nums[0] == 1 && nums[1] == 1) return new int[]{1, 2}; + } + + Set allSet = new HashSet<>(); + Set numsSet = new HashSet<>(); + int duplicate = -1, miss = -1; + for (Integer num : nums) { + // 找到重复,并将所有元素放到numsSet + if (numsSet.contains(num)) { + duplicate = num; + } else { + numsSet.add(num); + } + + } + for (int i = 1; i <= nums.length + 1; i++) { + allSet.add(i); + } + allSet.removeAll(numsSet); + for (Integer num : allSet) { + miss = num; + break; + } + + return new int[]{duplicate, miss}; + } + + public static void main(String[] args) { + // example + //int[] arr = {1, 2, 2, 4};//2,3 + //int[] arr = {2, 2};//2,1 + // error example + //int[] arr = {3, 2, 2};//2,1 + //int[] arr = {1, 1};//1,2 + int[] arr = {1, 5, 3, 2, 2, 7, 6, 4, 8, 9}; + System.out.println(Arrays.toString(new Solution1().findErrorNums(arr))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..b604915c --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,54 @@ +package cn.lastwhisper.leetcode.array.错误的集合_645_简单; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +class Solution2 { + /** + * https://leetcode-cn.com/problems/set-mismatch/ + * ------------------------------------------------------------------- + * 数据特征: + * 输入:数组、1~n整数、无序、存在重复数据、不一定包含丢失数据 + * 输出:数组[重复数据,丢失数据]、1~n+1整数、 + * ------------------------------------------------------------------- + * 思路: + * 遍历输入数组,使用map存储数组值出现的频率 + * 正常数据1~length每一个出现的频率都为1,将1~length每一个值当做key查询map, + * frequency=2的为重复数据,frequency=null为丢失数据 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + * ------------------------------------------------------------------- + * 改进: + * 将数组值当做数据下标,统计该值出现的频率 + * map需要使用2n的额外空间,使用额外数组当做map,只需要使用n的额外空间 + */ + public int[] findErrorNums(int[] nums) { + Map numFreMap = new HashMap<>(); + int duplicate = -1, miss = -1; + for (int num : nums) { + numFreMap.put(num, numFreMap.getOrDefault(num, 0) + 1); + } + for (int i = 1; i <= nums.length; i++) { + Integer frequency = numFreMap.get(i); + if (frequency == null) { + miss = i; + } else if (frequency == 2) { + duplicate = i; + } + } + return new int[]{duplicate, miss}; + } + + public static void main(String[] args) { + // example + //int[] arr = {1, 2, 2, 4};//2,3 + //int[] arr = {2, 2};//2,1 + // error example + //int[] arr = {3, 2, 2};//2,1 + //int[] arr = {1, 1};//1,2 + int[] arr = {1, 5, 3, 2, 2, 7, 6, 4, 8, 9}; + System.out.println(Arrays.toString(new Solution2().findErrorNums(arr))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution3.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution3.java" new file mode 100644 index 00000000..277ee841 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution3.java" @@ -0,0 +1,19 @@ +package cn.lastwhisper.leetcode.array.错误的集合_645_简单; + +class Solution3 { + public int[] findErrorNums(int[] nums) { + int[] copy = new int[nums.length + 1]; + for (int n : nums) { + copy[n]++; + } + + int[] res = new int[2]; + for (int i = 1; i < copy.length; i++) { + if (copy[i] == 0) + res[1] = i; + if (copy[i] >= 2) + res[0] = i; + } + return res; + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution4.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution4.java" new file mode 100644 index 00000000..da9c2807 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\224\231\350\257\257\347\232\204\351\233\206\345\220\210_645_\347\256\200\345\215\225/Solution4.java" @@ -0,0 +1,52 @@ +package cn.lastwhisper.leetcode.array.错误的集合_645_简单; + +import java.util.Arrays; + +class Solution4 { + /** + * https://leetcode-cn.com/problems/set-mismatch/ + * ------------------------------------------------------------------- + * 数据特征: + * 输入:数组、1~n整数、无序、存在重复数据、不一定包含丢失数据 + * 输出:数组[重复数据,丢失数据]、1~n+1整数、 + * ------------------------------------------------------------------- + * 思路:将数组中的每一个值当做下标,按下标-1找到数组对应的值,并更新为负数, + * 在更新之前检查这个值是否已经是负数,如果已经是负数,说明这个值是重复数据。 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + * ------------------------------------------------------------------- + * 相似题目:https://leetcode-cn.com/problems/first-missing-positive/ + */ + public int[] findErrorNums(int[] nums) { + // 丢失数据初始值为1, + int duplicate = -1, miss = 1; + for (int num : nums) { + if (nums[Math.abs(num) - 1] < 0) { + // 重复出现的下标 + duplicate = Math.abs(num); + } else { + nums[Math.abs(num) - 1] *= -1; + } + } + for (int i = 0; i < nums.length; i++) { + if (nums[i] > 0) { + miss = i + 1; + } + } + return new int[]{duplicate, miss}; + } + + public static void main(String[] args) { + // example + //int[] arr = {1, 2, 2, 4};//2,3 + //int[] arr = {2, 2};//2,1 + // error example + //int[] arr = {3, 2, 2};//2,1 + //int[] arr = {1, 1};//1,2 + //int[] arr = {1, 5, 3, 2, 2, 7, 6, 4, 8, 9};//10 + //int[] arr = {2, 3, 2}; + int[] arr = {3,3,1}; + System.out.println(Arrays.toString(new Solution4().findErrorNums(arr))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..1c23fde0 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,45 @@ +package cn.lastwhisper.leetcode.array.长度最小的子数组_209_中等; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/minimum-size-subarray-sum/ + * 编号:209 + * ------------------------------------------------------------------- + * 思考:边界值一定要考虑取还是不取,为什么? + * ------------------------------------------------------------------- + * 思路:二层循环暴力组合,一层循环计算组合范围值 + * ------------------------------------------------------------------- + * 时间复杂度:O(n^3) + * 空间复杂度:O(1) + */ + public int minSubArrayLen(int s, int[] nums) { + if (s <= 0 || nums == null) { + throw new IllegalArgumentException("Illegal Argument"); + } + // 子数组长度有可能等于 nums.length + int ans = Integer.MAX_VALUE; + for (int i = 0; i < nums.length; i++) { + for (int j = i; j < nums.length; j++) { + int sum = 0; + // 计算 [i,j] 子数组的和 + for (int k = i; k <= j; k++) { + sum += nums[k]; + } + if (sum >= s) { + ans = Math.min(ans, j - i + 1);// i=0,j=1 ————> ans=2 + j = nums.length;// 退出内循环 + } + } + } + // 子数组长度等于 nums.length+1,说明无解 + if (ans == Integer.MAX_VALUE) + return 0; + return ans; + } + + public static void main(String[] args) { + Assert.assertEquals(2, new Solution1().minSubArrayLen(7, new int[]{2, 3, 1, 2, 4, 3})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution2.java" new file mode 100644 index 00000000..e9082877 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution2.java" @@ -0,0 +1,54 @@ +package cn.lastwhisper.leetcode.array.长度最小的子数组_209_中等; + +import org.junit.Assert; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/minimum-size-subarray-sum/ + * 编号:209 + * ------------------------------------------------------------------- + * 思考:边界值一定要考虑取还是不取,为什么? + * ------------------------------------------------------------------- + * 思路:二层循环暴力组合 + * 组合的和提前计算 + * (1)提前将 sum[0...n] 计算出来, sum[0] = 0; sum[i] = sum[i-1] + num[i-1] + * (2)nums[i...j] 的和 = sum[j+1]-sum[i] + * ------------------------------------------------------------------- + * 时间复杂度:O(n^2) + * 空间复杂度:O(n) + */ + public int minSubArrayLen(int s, int[] nums) { + if (s <= 0 || nums == null) { + throw new IllegalArgumentException("Illegal Argument"); + } + // nums=> 2, 3, 1, 2, 4, 3 + // sum=>0, 2, 5, 6, 8, 12, 15 + // sums[i] 存放 nums[0...i-1] 的和 + int[] sum = new int[nums.length + 1]; + sum[0] = 0; + for (int i = 1; i <= nums.length; i++) { + sum[i] = sum[i - 1] + nums[i - 1]; + } + // 子数组长度有可能等于 nums.length + int ans = Integer.MAX_VALUE; + for (int i = 0; i < nums.length; i++) { + for (int j = i; j < nums.length; j++) { + // sum[j+1] - sum[0] = num[0,j]的和,sum[0]==0 + // sum[j+1] - sum[i] = num[i,j]的和 + if (sum[j + 1] - sum[i] >= s) { + ans = Math.min(ans, j - i + 1); + //j = nums.length;// 退出内循环 + break; + } + } + } + // 子数组长度等于 nums.length+1,说明无解 + if (ans == Integer.MAX_VALUE) + return 0; + return ans; + } + + public static void main(String[] args) { + Assert.assertEquals(2, new Solution2().minSubArrayLen(7, new int[]{2, 3, 1, 2, 4, 3})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution3.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution3.java" new file mode 100644 index 00000000..f34de047 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution3.java" @@ -0,0 +1,51 @@ +package cn.lastwhisper.leetcode.array.长度最小的子数组_209_中等; + +import org.junit.Assert; + +class Solution3 { + /** + * 题目地址:https://leetcode-cn.com/problems/minimum-size-subarray-sum/ + * 编号:209 + * ------------------------------------------------------------------- + * 思考:边界值一定要考虑取还是不取,为什么? + * ------------------------------------------------------------------- + * 思路:滑动窗口 + * (1)双指针 l、r 维护一个滑动窗口 + * (2)窗口的左边界在数组范围内,则循环继续 + * (3)r未到数组尾且 sums 需要动态缩小窗口左边界 + * (5)循环内每次找 sum >= s 时的最小长度 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) // l 和 r 指针同时遍历了一遍数组 O(2n) + * 空间复杂度:O(1) + */ + public int minSubArrayLen(int s, int[] nums) { + if (s <= 0 || nums == null) { + throw new IllegalArgumentException("Illegal Argument"); + } + // 初始窗口 [l,r] 是一个空集,所以 r 初值为 -1,后面需要先加才能使用 + int l = 0, r = -1; + int ans = Integer.MAX_VALUE, sum = 0; + // 维护窗口,通过窗口内 sum 与 s 的关系,触发窗口的扩容或缩小 + // 窗口的左边界在数组范围内,说明窗口还能继续扩容或者缩小 + while (l < nums.length) { + // 因为 r 先加再用所以要保证 r + 1 < nums.length + if (r + 1 < nums.length && sum < s) { + sum += nums[++r]; + } else { + sum -= nums[l++]; + } + if (sum >= s) { + ans = Math.min(ans, (r - l + 1)); + } + } + if (ans == Integer.MAX_VALUE) { + ans = 0; + } + return ans; + } + + public static void main(String[] args) { + Assert.assertEquals(2, new Solution3().minSubArrayLen(7, new int[]{2, 3, 1, 2, 4, 3})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution4.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution4.java" new file mode 100644 index 00000000..32800e20 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution4.java" @@ -0,0 +1,32 @@ +package cn.lastwhisper.leetcode.array.长度最小的子数组_209_中等; + +import org.junit.Assert; + +class Solution4 { + /** + * 题目地址:https://leetcode-cn.com/problems/minimum-size-subarray-sum/ + * 编号:209 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:滑动窗口 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) // l 和 r 指针同时遍历了一遍数组 O(2n) + * 空间复杂度:O(1) + */ + public int minSubArrayLen(int s, int[] nums) { + int l = 0, sum = 0, ans = Integer.MAX_VALUE; + for (int r = 0; r < nums.length; r++) { + sum += nums[r]; + while (sum >= s) { + ans = Math.min(ans, r - l + 1); + sum -= nums[l++]; + } + } + return ans == Integer.MAX_VALUE ? 0 : ans; + } + + public static void main(String[] args) { + Assert.assertEquals(2, new Solution4().minSubArrayLen(7, new int[]{2, 3, 1, 2, 4, 3})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution5.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution5.java" new file mode 100644 index 00000000..95b5835d --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution5.java" @@ -0,0 +1,69 @@ +package cn.lastwhisper.leetcode.array.长度最小的子数组_209_中等; + +/** + * 209. 长度最小的子数组 + * https://leetcode-cn.com/problems/minimum-size-subarray-sum/ + * @author lastwhisper + */ +public class Solution5 { + // 二分搜索 + // 扩展 Solution5 的方法。对于每一个l, 可以使用二分搜索法搜索r + // 时间复杂度: O(nlogn) + // 空间复杂度: O(n) + public int minSubArrayLen(int s, int[] nums) { + if(s <= 0 || nums == null) + throw new IllegalArgumentException("Illegal Arguments"); + + // sums[i]存放nums[0...i-1]的和 + int[] sums = new int[nums.length + 1]; + sums[0] = 0; + for(int i = 1 ; i <= nums.length ; i ++) + sums[i] = sums[i-1] + nums[i-1]; + + int res = Integer.MAX_VALUE; + for(int l = 0 ; l < nums.length - 1 ; l ++){ + // Java类库中没有内置的lowerBound方法, + // 我们需要自己实现一个基于二分搜索的lowerBound:) + int r = lowerBound(sums, sums[l] + s); + if(r != sums.length){ + res = Math.min(res, r - l); + } + } + + if(res == Integer.MAX_VALUE) + return 0; + return res; + } + + // 在有序数组nums中寻找大于等于target的最小值 + // 如果没有(nums数组中所有值都小于target),则返回nums.length + private int lowerBound(int[] nums, int target){ + if(nums == null /*|| !isSorted(nums)*/) + throw new IllegalArgumentException("Illegal argument nums in lowerBound."); + + int l = 0, r = nums.length; // 在nums[l...r)的范围里寻找解 + while(l != r){ + int mid = l + (r - l) / 2; + if(nums[mid] >= target) + r = mid; + else + l = mid + 1; + } + + return l; + } + + private boolean isSorted(int[] nums){ + for(int i = 1 ; i < nums.length ; i ++) + if(nums[i] < nums[i-1]) + return false; + return true; + } + + public static void main(String[] args) { + + int[] nums = {2, 3, 1, 2, 4, 3}; + int s = 7; + System.out.println((new Solution5()).minSubArrayLen(s, nums)); + } +} diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution6.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution6.java" new file mode 100644 index 00000000..ffb08944 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204_209_\344\270\255\347\255\211/Solution6.java" @@ -0,0 +1,52 @@ +package cn.lastwhisper.leetcode.array.长度最小的子数组_209_中等; + +import org.junit.Assert; + +class Solution6 { + /** + * 题目地址:https://leetcode-cn.com/problems/minimum-size-subarray-sum/ + * 编号:209 + * ------------------------------------------------------------------- + * 思考:边界值一定要考虑取还是不取,为什么? + * ------------------------------------------------------------------- + * 思路:滑动窗口 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public int minSubArrayLen(int s, int[] nums) { + if (s <= 0 || nums == null) { + throw new IllegalArgumentException("Illegal Argument"); + } + // 初始窗口 [l,r] 是一个空集,所以 r 初值为 -1,后面需要先加才能使用 + int l = 0, r = -1; + int ans = Integer.MAX_VALUE, sum = 0; + // 维护窗口,通过窗口内 sum 与 s 的关系,触发窗口的扩容或缩小 + // 窗口的右边界在数组范围内,说明窗口还能继续扩容或者缩小 + while (r + 1 < nums.length) { + // 因为 r 先加再用所以 r < nums.length - 1 + while (r + 1 < nums.length && sum < s) { + r++; + sum += nums[r]; + } + if (sum >= s) { + ans = Math.min(ans, (r + 1 - l)); + } + while (l < nums.length && sum >= s) { + sum -= nums[l]; + l++; + if (sum >= s) { + ans = Math.min(ans, (r + 1 - l)); + } + } + } + if (ans == Integer.MAX_VALUE) { + ans = 0; + } + return ans; + } + + public static void main(String[] args) { + Assert.assertEquals(2, new Solution6().minSubArrayLen(7, new int[]{2, 3, 1, 2, 4, 3})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..17a33f1c --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,39 @@ +package cn.lastwhisper.leetcode.array.颜色分类_75_中等; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/sort-colors/ + * 编号:75 + * ------------------------------------------------------------------- + * 思考: + * 数据特征:只有0,1,2 + * ------------------------------------------------------------------- + * 思路: + * 计数排序,统计每一个数出现的频率 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public void sortColors(int[] nums) { + // freq 统计0、1、2的频率 + int[] freq = new int[3]; + for (int num : nums) { + freq[num]++; + } + int idx = 0; + for (int i = 0; i < freq.length; i++) { + while (freq[i]-- > 0) { + nums[idx++] = i; + } + } + } + + public static void main(String[] args) { + int[] arr = new int[]{2, 0, 2, 1, 1, 0}; + new Solution1().sortColors(arr); + Assert.assertArrayEquals(new int[]{0, 0, 1, 1, 2, 2}, arr); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution2.java" new file mode 100644 index 00000000..d169835d --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution2.java" @@ -0,0 +1,51 @@ +package cn.lastwhisper.leetcode.array.颜色分类_75_中等; + +import org.junit.Assert; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/sort-colors/ + * 编号:75 + * ------------------------------------------------------------------- + * 思考: + * 数据特征:只有0,1,2 + * ------------------------------------------------------------------- + * 思路: + * 三路快速排序的思想,对整个数组只遍历了一遍 + * (1)双指针 left=-1,right=n + * (2)下标 i 遍历数组,num[i]==1,i++ + * (3)num[i]==0,将 0 移动到数组最前位置,swap(num,++left,i++) + * i++,即使 num[++left]==0,这次的交换和位移也是正确的 + * (4)num[i]==2,将 2 移动到数组最后位置,swap(num,--right,i) + * i不变,因为有可能num[--right]==2 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public void sortColors(int[] nums) { + int left = -1, right = nums.length; + for (int i = 0; i < right; ) { + if (nums[i] == 1) { + i++; + } else if (nums[i] == 0) { + swap(nums, ++left, i++); + } else if (nums[i] == 2) { + swap(nums, --right, i); + } + } + } + + public void swap(int[] num, int i, int j) { + if (i != j) { + int temp = num[j]; + num[j] = num[i]; + num[i] = temp; + } + } + + public static void main(String[] args) { + int[] arr = new int[]{2, 0, 2, 1, 1, 0}; + new Solution2().sortColors(arr); + Assert.assertArrayEquals(new int[]{0, 0, 1, 1, 2, 2}, arr); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262_125_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262_125_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..1db21830 --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262_125_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,48 @@ +package cn.lastwhisper.leetcode.array.验证回文串_125_简单; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/valid-palindrome/ + * 编号:125 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 对撞指针遍历比较 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ + public boolean isPalindrome(String s) { + String upperS = s.toUpperCase(); + int l = 0, r = upperS.length() - 1; + // 这里不能等于 + while (l < r) { + while (l < r && !valid(upperS.charAt(l))) { + l++; + } + while (l < r && !valid(upperS.charAt(r))) { + r--; + } + if (upperS.charAt(l) != upperS.charAt(r)) { + return false; + } + l++; + r--; + } + return true; + } + // 只考虑字母和数字字符 + private boolean valid(char c) { + return ((c >= 48 && c <= 57) || (c >= 65 && c <= 90) || (c >= 97 && c <= 122)); + } + + public static void main(String[] args) { + //String s = "A man, a plan, a canal: Panama"; + //String s = "race a car"; + String s = "a"; + Assert.assertTrue(new Solution1().isPalindrome(s)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262_125_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262_125_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..2720acde --- /dev/null +++ "b/algorithms/leetcode/array/src/main/java/cn/lastwhisper/leetcode/array/\351\252\214\350\257\201\345\233\236\346\226\207\344\270\262_125_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,41 @@ +package cn.lastwhisper.leetcode.array.验证回文串_125_简单; + +import org.junit.Assert; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/valid-palindrome/ + * 编号:125 + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 对撞指针遍历比较 + * 统一转成大写:ch & 0b11011111 简写:ch & 0xDF + * 统一转成小写:ch | 0b00100000 简写:ch | 0x20 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public boolean isPalindrome(String s) { + int l = 0, r = s.length() - 1; + while (l < r) {// 这里不能等于 + while (l < r && !valid(s.charAt(l))) l++; + while (l < r && !valid(s.charAt(r))) r--; + if ((s.charAt(l++) & 0xDF) != (s.charAt(r--) & 0xDF)) return false; + } + return true; + } + + // 只考虑字母和数字字符 + private boolean valid(char c) { + return ((c >= 48 && c <= 57) || (c >= 65 && c <= 90) || (c >= 97 && c <= 122)); + } + + public static void main(String[] args) { + String s = "A man, a plan, a canal: Panama"; + //String s = "race a car"; + //String s = "a"; + Assert.assertTrue(new Solution2().isPalindrome(s)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210_235_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210_235_\347\256\200\345\215\225/Solution1.java" index f7a233ab..09897e63 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210_235_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210_235_\347\256\200\345\215\225/Solution1.java" @@ -2,7 +2,7 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution1 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210_235_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210_235_\347\256\200\345\215\225/Solution2.java" index e02fa203..e12d84ce 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210_235_\347\256\200\345\215\225/Solution2.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210_235_\347\256\200\345\215\225/Solution2.java" @@ -2,7 +2,7 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution2 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\347\273\223\347\202\271\346\234\200\345\260\217\350\267\235\347\246\273_783_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\347\273\223\347\202\271\346\234\200\345\260\217\350\267\235\347\246\273_783_\347\256\200\345\215\225/Solution1.java" index bdae1c91..0de79d03 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\347\273\223\347\202\271\346\234\200\345\260\217\350\267\235\347\246\273_783_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\347\273\223\347\202\271\346\234\200\345\260\217\350\267\235\347\246\273_783_\347\256\200\345\215\225/Solution1.java" @@ -6,7 +6,7 @@ import java.util.LinkedList; import java.util.List; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution1 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\211\200\346\234\211\350\267\257\345\276\204_257_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\211\200\346\234\211\350\267\257\345\276\204_257_\347\256\200\345\215\225/Solution1.java" index 840eb0fc..ce85bab8 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\211\200\346\234\211\350\267\257\345\276\204_257_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\211\200\346\234\211\350\267\257\345\276\204_257_\347\256\200\345\215\225/Solution1.java" @@ -5,9 +5,8 @@ import java.util.ArrayList; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printList; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution1 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\211\200\346\234\211\350\267\257\345\276\204_257_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\211\200\346\234\211\350\267\257\345\276\204_257_\347\256\200\345\215\225/Solution2.java" index 2cb7a68b..b5aa12b8 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\211\200\346\234\211\350\267\257\345\276\204_257_\347\256\200\345\215\225/Solution2.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\211\200\346\234\211\350\267\257\345\276\204_257_\347\256\200\345\215\225/Solution2.java" @@ -7,9 +7,8 @@ import java.util.LinkedList; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printList; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution2 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution1.java" index 2252e958..a64d7d02 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution1.java" @@ -2,7 +2,7 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; class Solution1 { /** @@ -27,7 +27,7 @@ public int maxDepth(TreeNode root) { } public static void main(String[] args) { - System.out.println(new Solution1().maxDepth(TreeUtils.createTree())); + System.out.println(new Solution1().maxDepth(TreeUtil.createTree())); } } \ No newline at end of file diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution2.java" index b4d24f0a..9f1c06d8 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution2.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution2.java" @@ -2,7 +2,7 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; import javafx.util.Pair; import java.util.LinkedList; @@ -41,7 +41,7 @@ public int maxDepth(TreeNode root) { } public static void main(String[] args) { - System.out.println(new Solution2().maxDepth(TreeUtils.createTree())); + System.out.println(new Solution2().maxDepth(TreeUtil.createTree())); } } \ No newline at end of file diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246_111_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246_111_\347\256\200\345\215\225/Solution1.java" index 383e4cd2..71dd7713 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246_111_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246_111_\347\256\200\345\215\225/Solution1.java" @@ -1,7 +1,7 @@ package cn.lastwhisper.leetcode.binarytree.二叉树的最小深度_111_简单; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; class Solution1 { /** * 题目地址:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/ @@ -35,6 +35,6 @@ public int minDepth(TreeNode root) { } public static void main(String[] args) { - System.out.println(new Solution1().minDepth(TreeUtils.createTree())); + System.out.println(new Solution1().minDepth(TreeUtil.createTree())); } } diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246_111_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246_111_\347\256\200\345\215\225/Solution2.java" index a9ad3b37..ccba9434 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246_111_\347\256\200\345\215\225/Solution2.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246_111_\347\256\200\345\215\225/Solution2.java" @@ -1,7 +1,7 @@ package cn.lastwhisper.leetcode.binarytree.二叉树的最小深度_111_简单; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; import javafx.util.Pair; import java.util.LinkedList; @@ -52,6 +52,6 @@ public static void main(String[] args) { * / \ * 15 7 */ - System.out.println(new Solution2().minDepth(TreeUtils.createTree(3,9,20,null,null,15,7))); + System.out.println(new Solution2().minDepth(TreeUtil.createTree(3,9,20,null,null,15,7))); } } diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246_111_\347\256\200\345\215\225/Solution3.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246_111_\347\256\200\345\215\225/Solution3.java" index 0c2e988b..27c4da84 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246_111_\347\256\200\345\215\225/Solution3.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246_111_\347\256\200\345\215\225/Solution3.java" @@ -1,7 +1,7 @@ package cn.lastwhisper.leetcode.binarytree.二叉树的最小深度_111_简单; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; import javafx.util.Pair; import java.util.LinkedList; @@ -55,6 +55,6 @@ public static void main(String[] args) { * / \ * 15 7 */ - System.out.println(new Solution2().minDepth(TreeUtils.createTree(3,9,20,null,null,15,7))); + System.out.println(new Solution2().minDepth(TreeUtil.createTree(3,9,20,null,null,15,7))); } } diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\347\233\264\345\276\204_543_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\347\233\264\345\276\204_543_\347\256\200\345\215\225/Solution1.java" index 29b9e1b8..99d1d4aa 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\347\233\264\345\276\204_543_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\344\272\214\345\217\211\346\240\221\347\232\204\347\233\264\345\276\204_543_\347\256\200\345\215\225/Solution1.java" @@ -1,7 +1,7 @@ package cn.lastwhisper.leetcode.binarytree.二叉树的直径_543_简单; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; class Solution1 { /** @@ -45,7 +45,7 @@ private int height(TreeNode node) { public static void main(String[] args) { Integer[] nums = new Integer[]{4, -7, -3, null, null, -9, -3, 9, -7, -4, null, 6, null, -6, -6, null, null, 0, 6, 5, null, 9, null, null, -1, -4, null, null, null, -2}; - TreeNode tree = TreeUtils.createTree(nums); + TreeNode tree = TreeUtil.createTree(nums); System.out.println(new Solution1().diameterOfBinaryTree(tree)); } } \ No newline at end of file diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\215\225\350\257\215\347\232\204\345\216\213\347\274\251\347\274\226\347\240\201_820_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\215\225\350\257\215\347\232\204\345\216\213\347\274\251\347\274\226\347\240\201_820_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..691c0a9d --- /dev/null +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\215\225\350\257\215\347\232\204\345\216\213\347\274\251\347\274\226\347\240\201_820_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,66 @@ +package cn.lastwhisper.leetcode.binarytree.单词的压缩编码_820_中等; + +import org.junit.Assert; + +import java.util.Arrays; +import java.util.Comparator; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/short-encoding-of-words/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 按长度排序,逆序插入字典树, + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public int minimumLengthEncoding(String[] words) { + int len = 0; + // 先对单词列表根据单词长度由长到短排序 + Arrays.sort(words, (s1, s2) -> s2.length() - s1.length()); + Trie trie = new Trie(); + // 单词插入trie,返回该单词增加的编码长度 + for (String word : words) { + len += trie.insert(word); + } + return len; + } + + static class TrieNode { + TrieNode[] children = new TrieNode[26]; + public TrieNode() {} + } + + static class Trie { + + private TrieNode root; + + public Trie() { + root = new TrieNode(); + } + + public int insert(String word) { + TrieNode cur = root; + boolean isNew = false; + // 倒着插入单词 + for (int i = word.length() - 1; i >= 0; i--) { + int c = word.charAt(i) - 'a'; + if (cur.children[c] == null) { + isNew = true; + cur.children[c] = new TrieNode(); + } + cur = cur.children[c]; + } + // +1是# + return isNew ? word.length() + 1 : 0; + } + } + + public static void main(String[] args) { + + Assert.assertEquals(10,new Solution1().minimumLengthEncoding(new String[]{"time", "me", "bell"})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221\347\232\204\350\212\202\347\202\271\344\270\252\346\225\260_222_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221\347\232\204\350\212\202\347\202\271\344\270\252\346\225\260_222_\344\270\255\347\255\211/Solution1.java" index c9217c5e..a3f262df 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221\347\232\204\350\212\202\347\202\271\344\270\252\346\225\260_222_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221\347\232\204\350\212\202\347\202\271\344\270\252\346\225\260_222_\344\270\255\347\255\211/Solution1.java" @@ -2,7 +2,7 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution1 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221\347\232\204\350\212\202\347\202\271\344\270\252\346\225\260_222_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221\347\232\204\350\212\202\347\202\271\344\270\252\346\225\260_222_\344\270\255\347\255\211/Solution2.java" index 3ac061c6..06775da1 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221\347\232\204\350\212\202\347\202\271\344\270\252\346\225\260_222_\344\270\255\347\255\211/Solution2.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221\347\232\204\350\212\202\347\202\271\344\270\252\346\225\260_222_\344\270\255\347\255\211/Solution2.java" @@ -4,7 +4,7 @@ import java.util.LinkedList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution2 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221\347\232\204\350\212\202\347\202\271\344\270\252\346\225\260_222_\344\270\255\347\255\211/Solution3.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221\347\232\204\350\212\202\347\202\271\344\270\252\346\225\260_222_\344\270\255\347\255\211/Solution3.java" index afd0c863..a529f89c 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221\347\232\204\350\212\202\347\202\271\344\270\252\346\225\260_222_\344\270\255\347\255\211/Solution3.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221\347\232\204\350\212\202\347\202\271\344\270\252\346\225\260_222_\344\270\255\347\255\211/Solution3.java" @@ -2,7 +2,7 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution3 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\256\236\347\216\260Trie\345\211\215\347\274\200\346\240\221_208_\344\270\255\347\255\211/Trie.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\256\236\347\216\260Trie\345\211\215\347\274\200\346\240\221_208_\344\270\255\347\255\211/Trie.java" new file mode 100644 index 00000000..f21bad54 --- /dev/null +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\256\236\347\216\260Trie\345\211\215\347\274\200\346\240\221_208_\344\270\255\347\255\211/Trie.java" @@ -0,0 +1,101 @@ +package cn.lastwhisper.leetcode.binarytree.实现Trie前缀树_208_中等; + +import cn.lastwhisper.leetcode.common.tree.TrieNode; +import org.junit.Assert; + +class Trie { + + private TrieNode root; + + /** + * 功能: + * 找到具有同一前缀的全部键值。 + * 按词典序枚举字符串的数据集。 + * + * 与哈希表相比,Trie 树在存储多个具有相同前缀的键时可以使用较少的空间。 + * 此时 Trie 树只需要 O(m) 的时间复杂度,其中 m 为键长。而在平衡树中查找键值需要 O(mlogn) 时间复杂度。 + * + * https://leetcode-cn.com/problems/implement-trie-prefix-tree/solution/shi-xian-trie-qian-zhui-shu-by-leetcode/ + */ + public Trie() { + root = new TrieNode(); + } + + /** + * 通过搜索 Trie 树来插入一个键。我们从根开始搜索它对应于第一个键字符的链接。有两种情况: + * 链接存在。沿着链接移动到树的下一个子层。算法继续搜索下一个键字符。 + * 链接不存在。创建一个新的节点,并将它与父节点的链接相连,该链接与当前的键字符相匹配。 + * 重复以上步骤,直到到达键的最后一个字符,然后将当前节点标记为结束节点,算法完成。 + * + * 时间复杂度:O(m),其中 m 为键长。在算法的每次迭代中,我们要么检查要么创建一个节点,直到到达键尾。只需要 m 次操作。 + * 空间复杂度:O(m)。最坏的情况下,新插入的键和 Trie 树中已有的键没有公共前缀。此时需要添加 m 个结点,使用 O(m) 空间。 + */ + public void insert(String word) { + TrieNode node = root; + for (int i = 0; i < word.length(); i++) { + char currentChar = word.charAt(i); + if (!node.containsKey(currentChar)) { + node.put(currentChar, new TrieNode()); + } + node = node.get(currentChar); + } + node.setEnd(); + } + + /** + * 功能:查找word在是否在前缀树中 + * + * 每个键在trie中表示为从根到内部节点或叶的路径。我们用第一个键字符从根开始,检查当前节点中与键字符对应的链接。 + * 有两种情况: + * 1.存在链接。我们移动到该链接后面路径中的下一个节点,并继续搜索下一个键字符。 + * 2.不存在链接。若已无键字符,且当前结点标记为 isEnd,则返回 true。否则有两种可能,均返回 false : + * 还有键字符剩余,但无法跟随 Trie 树的键路径,找不到键。 + * 没有键字符剩余,但当前结点没有标记为 isEnd。也就是说,待查找键只是Trie树中另一个键的前缀。 + */ + public boolean search(String word) { + TrieNode node = searchPrefix(word); + return node != null && node.isEnd(); + } + + // search a prefix or whole key in trie and + // returns the node where search ends + /** + * + * 时间复杂度 : O(m) + * 空间复杂度 : O(1) + */ + private TrieNode searchPrefix(String word) { + TrieNode node = root; + for (int i = 0; i < word.length(); i++) { + char curLetter = word.charAt(i); + if (node.containsKey(curLetter)) { + node = node.get(curLetter); + } else { + return null; + } + } + return node; + } + + /** + * 功能:查找prefix在是否在前缀树中 + * + * 时间复杂度 : O(m) + * 空间复杂度 : O(1) + */ + public boolean startsWith(String prefix) { + TrieNode node = searchPrefix(prefix); + return node != null; + } + + public static void main(String[] args) { + Trie trie = new Trie(); + + trie.insert("apple"); + Assert.assertTrue(trie.search("apple")); // 返回 true + Assert.assertFalse(trie.search("app")); // 返回 false + Assert.assertTrue(trie.startsWith("app")); // 返回 true + trie.insert("app"); + Assert.assertTrue(trie.search("app")); // 返回 true + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution1.java" index 84471d9d..5f3468c6 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution1.java" @@ -2,7 +2,7 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution1 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution2.java" index 9d32d59a..b4e7dd56 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution2.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution2.java" @@ -4,7 +4,7 @@ import java.util.LinkedList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution2 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution3.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution3.java" index fd67d05d..5e5b322d 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution3.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution3.java" @@ -5,7 +5,7 @@ import java.util.LinkedList; import java.util.Queue; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution3 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution6.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution6.java" index 38e66c78..42322e65 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution6.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution6.java" @@ -2,7 +2,7 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution6 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214_404_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214_404_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..795ff180 --- /dev/null +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214_404_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,29 @@ +package cn.lastwhisper.leetcode.binarytree.左叶子之和_404_简单; + +import cn.lastwhisper.leetcode.common.tree.TreeNode; + +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; + +class Solution { + public int sumOfLeftLeaves(TreeNode root) { + return helper(root); + } + + public int helper(TreeNode node) { + int sum = 0; + if (node == null) { + return 0; + } + if (node.left != null && (node.left.left == null && node.left.right == null)) { + sum += node.left.val; + } + sum += helper(node.left) + helper(node.right); + return sum; + } + + public static void main(String[] args) { + //System.out.println(new Solution().sumOfLeftLeaves(createTree(1, 2, 3, 4, 5))); + //System.out.println(new Solution().sumOfLeftLeaves(createTree(1, null, 2))); + System.out.println(new Solution().sumOfLeftLeaves(createTree(3, 9, 20, null, null, 15, 7))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214_404_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214_404_\347\256\200\345\215\225/Solution1.java" index 3a44fd0d..ecc08b4f 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214_404_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214_404_\347\256\200\345\215\225/Solution1.java" @@ -2,7 +2,7 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution1 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214_404_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214_404_\347\256\200\345\215\225/Solution2.java" index e4398597..188e1cf6 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214_404_\347\256\200\345\215\225/Solution2.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214_404_\347\256\200\345\215\225/Solution2.java" @@ -5,7 +5,7 @@ import java.util.LinkedList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution2 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221_110_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221_110_\347\256\200\345\215\225/Solution1.java" index d4ca78cd..24674fc9 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221_110_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221_110_\347\256\200\345\215\225/Solution1.java" @@ -2,7 +2,7 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution1 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221_110_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221_110_\347\256\200\345\215\225/Solution2.java" index 61a89d8b..9788109f 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221_110_\347\256\200\345\215\225/Solution2.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221_110_\347\256\200\345\215\225/Solution2.java" @@ -2,7 +2,7 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution2 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\346\261\202\346\240\271\345\210\260\345\217\266\345\255\220\350\212\202\347\202\271\346\225\260\345\255\227\344\271\213\345\222\214_129_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\346\261\202\346\240\271\345\210\260\345\217\266\345\255\220\350\212\202\347\202\271\346\225\260\345\255\227\344\271\213\345\222\214_129_\344\270\255\347\255\211/Solution1.java" index 08adfb34..38996df2 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\346\261\202\346\240\271\345\210\260\345\217\266\345\255\220\350\212\202\347\202\271\346\225\260\345\255\227\344\271\213\345\222\214_129_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\346\261\202\346\240\271\345\210\260\345\217\266\345\255\220\350\212\202\347\202\271\346\225\260\345\255\227\344\271\213\345\222\214_129_\344\270\255\347\255\211/Solution1.java" @@ -5,8 +5,7 @@ import java.util.ArrayList; import java.util.List; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution1 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\346\261\202\346\240\271\345\210\260\345\217\266\345\255\220\350\212\202\347\202\271\346\225\260\345\255\227\344\271\213\345\222\214_129_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\346\261\202\346\240\271\345\210\260\345\217\266\345\255\220\350\212\202\347\202\271\346\225\260\345\255\227\344\271\213\345\222\214_129_\344\270\255\347\255\211/Solution2.java" index cf732dfd..a4070533 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\346\261\202\346\240\271\345\210\260\345\217\266\345\255\220\350\212\202\347\202\271\346\225\260\345\255\227\344\271\213\345\222\214_129_\344\270\255\347\255\211/Solution2.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\346\261\202\346\240\271\345\210\260\345\217\266\345\255\220\350\212\202\347\202\271\346\225\260\345\255\227\344\271\213\345\222\214_129_\344\270\255\347\255\211/Solution2.java" @@ -7,7 +7,7 @@ import java.util.LinkedList; import java.util.List; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution2 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution1.java" index a9af1a16..55cb44d5 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution1.java" @@ -2,7 +2,7 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.*; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.*; class Solution1 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution2.java" index 7caec413..17868463 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution2.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution2.java" @@ -4,7 +4,7 @@ import java.util.LinkedList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution2 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution3.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution3.java" index d9243a54..6bc50c58 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution3.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution3.java" @@ -4,7 +4,7 @@ import java.util.LinkedList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution3 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution4.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution4.java" index 46134be0..bbf69363 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution4.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution4.java" @@ -4,7 +4,7 @@ import java.util.LinkedList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution4 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution5.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution5.java" index 457b8c5b..5e70cdcd 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution5.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution5.java" @@ -4,7 +4,7 @@ import java.util.LinkedList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution5 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution6.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution6.java" index 7cc021ef..cfe0f756 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution6.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\233\270\345\220\214\347\232\204\346\240\221_100_\347\256\200\345\215\225/Solution6.java" @@ -4,7 +4,7 @@ import java.util.LinkedList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution6 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution1.java" index 7f8649c2..d1cefea3 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution1.java" @@ -2,7 +2,7 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.*; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.*; class Solution1 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution2.java" index ed5052aa..14367309 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution2.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution2.java" @@ -4,7 +4,7 @@ import java.util.LinkedList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.*; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.*; class Solution2 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution3.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution3.java" index f4821091..5fc5055d 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution3.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution3.java" @@ -5,7 +5,7 @@ import java.util.LinkedList; import java.util.Queue; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.*; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.*; class Solution3 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution4.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution4.java" index 5ee78c33..2697a199 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution4.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution4.java" @@ -2,8 +2,8 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.printLevelOrder; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.printLevelOrder; class Solution4 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution5.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution5.java" index ce96bb96..60e8195f 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution5.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution5.java" @@ -2,8 +2,8 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.printLevelOrder; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.printLevelOrder; class Solution5 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_112_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_112_\347\256\200\345\215\225/Solution1.java" index 09dc5a43..8d057a72 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_112_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_112_\347\256\200\345\215\225/Solution1.java" @@ -2,7 +2,7 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution1 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_112_\347\256\200\345\215\225/Solution5.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_112_\347\256\200\345\215\225/Solution5.java" index e80d242d..b8b5f2b4 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_112_\347\256\200\345\215\225/Solution5.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_112_\347\256\200\345\215\225/Solution5.java" @@ -5,7 +5,7 @@ import java.util.LinkedList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution5 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_III_437_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_III_437_\347\256\200\345\215\225/Solution1.java" index 7af0f8e7..b786a6bc 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_III_437_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_III_437_\347\256\200\345\215\225/Solution1.java" @@ -2,7 +2,7 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution1 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_II_113_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_II_113_\344\270\255\347\255\211/Solution1.java" index 1d781e66..704f3ab1 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_II_113_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_II_113_\344\270\255\347\255\211/Solution1.java" @@ -5,8 +5,8 @@ import java.util.ArrayList; import java.util.List; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; class Solution1 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_II_113_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_II_113_\344\270\255\347\255\211/Solution2.java" index 6f147ec6..c9a5f6ff 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_II_113_\344\270\255\347\255\211/Solution2.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\350\267\257\345\276\204\346\200\273\345\222\214_II_113_\344\270\255\347\255\211/Solution2.java" @@ -6,8 +6,8 @@ import java.util.LinkedList; import java.util.List; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; class Solution2 { static class DTO { diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221_98_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221_98_\344\270\255\347\255\211/Solution1.java" index 5c7c3353..5722bed9 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221_98_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221_98_\344\270\255\347\255\211/Solution1.java" @@ -4,7 +4,7 @@ import java.util.LinkedList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution1 { /** diff --git "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221_98_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221_98_\344\270\255\347\255\211/Solution2.java" index 48bdd6be..dbd6dc14 100644 --- "a/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221_98_\344\270\255\347\255\211/Solution2.java" +++ "b/algorithms/leetcode/binarytree/src/main/java/cn/lastwhisper/leetcode/binarytree/\351\252\214\350\257\201\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221_98_\344\270\255\347\255\211/Solution2.java" @@ -2,7 +2,7 @@ import cn.lastwhisper.leetcode.common.tree.TreeNode; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution2 { /** diff --git "a/algorithms/leetcode/dfsbfs/src/main/java/cn/lastwhisper/leetcode/dfsbfs/\345\234\260\345\233\276\345\210\206\346\236\220_1162_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/dfsbfs/src/main/java/cn/lastwhisper/leetcode/dfsbfs/\345\234\260\345\233\276\345\210\206\346\236\220_1162_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..4a36d1f8 --- /dev/null +++ "b/algorithms/leetcode/dfsbfs/src/main/java/cn/lastwhisper/leetcode/dfsbfs/\345\234\260\345\233\276\345\210\206\346\236\220_1162_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,55 @@ +package cn.lastwhisper.leetcode.dfsbfs.地图分析_1162_中等; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/as-far-from-land-as-possible/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:广度优先搜索 + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public int maxDistance(int[][] grid) { + int max = 0; + + //boolean[][] visited = new boolean[grid.length][grid[0].length]; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + if (grid[i][j] == 1) { + max = Math.max(dfs(grid, i, j), max); + } + } + } + return max; + } + + public int dfs(int[][] grid, int i, int j) { + int max = 0; + for (int k = 0; k < grid.length; k++) { + for (int l = 0; l < grid[0].length; l++) { + //if (k == i && l == j) { + // continue; + //} + if (grid[k][l] == 0) { + max = Math.max(manhattanDistance(i, k, j, l), max); + } + } + } + return max; + } + + /** + * 曼哈顿距离 + */ + public int manhattanDistance(int x0, int x1, int y0, int y1) { + return Math.abs(x0 - x1) + Math.abs(y0 - y1); + } + + public static void main(String[] args) { + Assert.assertEquals(2, new Solution1().maxDistance(new int[][]{{1, 0, 1}, {0, 0, 0}, {1, 0, 1}})); + } +} \ No newline at end of file diff --git a/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/knapsack01/knapsack01.md b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/knapsack01/knapsack01.md index a1a0eb40..7431ee35 100644 --- a/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/knapsack01/knapsack01.md +++ b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/knapsack01/knapsack01.md @@ -7,9 +7,9 @@ -| | 0 | 1 | 2 | 3 | 4 | 5 | -| ---- | ---- | ---- | ---- | ---- | ---- | ---- | -| 0 | 0 | 6 | 6 | 6 | 6 | 6 | -| 1 | 0 | 6 | 10 | 16 | 16 | 16 | -| 2 | 0 | 6 | 10 | 16 | 18 | 22 | +| 物品编号\背包容量 | 0 | 1 | 2 | 3 | 4 | 5 | +|-----------| ---- | ---- | ---- | ---- | ---- | ---- | +| 0 | 0 | 6 | 6 | 6 | 6 | 6 | +| 1 | 0 | 6 | 10 | 16 | 16 | 16 | +| 2 | 0 | 6 | 10 | 16 | 18 | 22 | diff --git "a/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214_120_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214_120_\344\270\255\347\255\211/Solution1.java" index fb1cbef6..a2ac0362 100644 --- "a/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214_120_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214_120_\344\270\255\347\255\211/Solution1.java" @@ -2,7 +2,7 @@ import java.util.List; -import static cn.lastwhisper.leetcode.common.matrix.ArrayUtils.createList; +import static cn.lastwhisper.leetcode.common.array.ArrayUtil.createList; class Solution1 { /** diff --git "a/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214_120_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214_120_\344\270\255\347\255\211/Solution2.java" index 91279018..3a96c641 100644 --- "a/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214_120_\344\270\255\347\255\211/Solution2.java" +++ "b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214_120_\344\270\255\347\255\211/Solution2.java" @@ -2,7 +2,7 @@ import java.util.List; -import static cn.lastwhisper.leetcode.common.matrix.ArrayUtils.createList; +import static cn.lastwhisper.leetcode.common.array.ArrayUtil.createList; class Solution2 { /** diff --git "a/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214_120_\344\270\255\347\255\211/Solution3.java" "b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214_120_\344\270\255\347\255\211/Solution3.java" index d2726401..912548cd 100644 --- "a/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214_120_\344\270\255\347\255\211/Solution3.java" +++ "b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214_120_\344\270\255\347\255\211/Solution3.java" @@ -2,7 +2,7 @@ import java.util.List; -import static cn.lastwhisper.leetcode.common.matrix.ArrayUtils.createList; +import static cn.lastwhisper.leetcode.common.array.ArrayUtil.createList; class Solution3 { /** diff --git "a/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214_120_\344\270\255\347\255\211/Solution4.java" "b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214_120_\344\270\255\347\255\211/Solution4.java" index 49e986d7..d71d3786 100644 --- "a/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214_120_\344\270\255\347\255\211/Solution4.java" +++ "b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\344\270\211\350\247\222\345\275\242\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214_120_\344\270\255\347\255\211/Solution4.java" @@ -2,7 +2,7 @@ import java.util.List; -import static cn.lastwhisper.leetcode.common.matrix.ArrayUtils.createList; +import static cn.lastwhisper.leetcode.common.array.ArrayUtil.createList; class Solution4 { /** diff --git "a/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\346\211\223\345\256\266\345\212\253\350\210\215_198_\347\256\200\345\215\225/recursion/Solution1.java" "b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\346\211\223\345\256\266\345\212\253\350\210\215_198_\347\256\200\345\215\225/recursion/Solution1.java" index af58b48a..9a0af284 100644 --- "a/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\346\211\223\345\256\266\345\212\253\350\210\215_198_\347\256\200\345\215\225/recursion/Solution1.java" +++ "b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\346\211\223\345\256\266\345\212\253\350\210\215_198_\347\256\200\345\215\225/recursion/Solution1.java" @@ -22,16 +22,16 @@ public int tryRob(int index, int[] nums) { int max = 0, res; for (int i = index; i < nums.length; i++) { res = nums[i] + tryRob(i + 2, nums); - System.out.println("结果值:" + res); max = Math.max(max, res); + System.out.println("max:" + max + " res:" + res); } return max; } public static void main(String[] args) { - //System.out.println(new Solution1().rob(new int[]{2, 1, 1, 2})); - System.out.println(new Solution1().rob(new int[]{2, 7, 9, 3, 1})); + System.out.println(new Solution1().rob(new int[]{2, 1, 1, 2})); +// System.out.println(new Solution1().rob(new int[]{2, 7, 9, 3, 1})); //System.out.println(new Solution1().rob(new int[]{1, 2, 3, 1})); } } \ No newline at end of file diff --git "a/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227_1143_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227_1143_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..57e78b76 --- /dev/null +++ "b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227_1143_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,39 @@ +package cn.lastwhisper.leetcode.dynamic.最长公共子序列_1143_中等; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/longest-common-subsequence/ + * 题号:1143/最长公共子序列(LCS) + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:暴力搜索 + * ------------------------------------------------------------------- + * 时间复杂度:O(n^2) + * 空间复杂度:O(n) + */ + public int longestCommonSubsequence(String text1, String text2) { + return dfs(text1, text2, text1.length() - 1, text2.length() - 1); + } + + public int dfs(String text1, String text2, int i, int j) { + if (i == -1 || j == -1) { + return 0; + } + if (text1.charAt(i) == text2.charAt(j)) { + // 这边找到一个 lcs 的元素,继续往前找 + return dfs(text1, text2, i - 1, j - 1) + 1; + } else { + // 谁能让 lcs 最长,就听谁的 + return Math.max(dfs(text1, text2, i - 1, j), dfs(text1, text2, i, j - 1)); + } + } + + public static void main(String[] args) { + Assert.assertEquals(3, new Solution1().longestCommonSubsequence("abcde", "ace")); + Assert.assertEquals(3, new Solution1().longestCommonSubsequence("abc", "abc")); + Assert.assertEquals(0, new Solution1().longestCommonSubsequence("abc", "def")); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227_1143_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227_1143_\344\270\255\347\255\211/Solution2.java" new file mode 100644 index 00000000..2467ad54 --- /dev/null +++ "b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227_1143_\344\270\255\347\255\211/Solution2.java" @@ -0,0 +1,49 @@ +package cn.lastwhisper.leetcode.dynamic.最长公共子序列_1143_中等; + +import org.junit.Assert; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/longest-common-subsequence/ + * 题号:1143/最长公共子序列(LCS) + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:动态规划(自顶向下) + * 一、状态定义:dp[i][j]表示,对于 s1[1..i] 和 s2[1..j],它们的 LCS 长度是 dp[i][j]。 + * 二、初始状态: + * 三、转换方程: + * + * + * https://leetcode-cn.com/problems/longest-common-subsequence/solution/dong-tai-gui-hua-zhi-zui-chang-gong-gong-zi-xu-lie/ + * https://www.jianshu.com/p/6451410be00a + * ------------------------------------------------------------------- + * 时间复杂度:O(n^2) + * 空间复杂度:O(n) + */ + public int longestCommonSubsequence(String text1, String text2) { + int m = text1.length() + 1, n = text2.length() + 1; + int[][] dp = new int[m][n]; + + for (int i = 1; i < m; i++) { + for (int j = 1; j < n; j++) { + if (text1.charAt(i - 1) == text2.charAt(j - 1)) { + // 这边找到一个 lcs 的元素,继续往前找 + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + // 谁能让 lcs 最长,就听谁的 + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + } + } + } + + return dp[m - 1][n - 1]; + } + + public static void main(String[] args) { + Assert.assertEquals(4, new Solution1().longestCommonSubsequence("google", "elgoog")); + //Assert.assertEquals(3, new Solution3().longestCommonSubsequence("abcde", "ace")); + //Assert.assertEquals(3, new Solution3().longestCommonSubsequence("abc", "abc")); + //Assert.assertEquals(0, new Solution3().longestCommonSubsequence("abc", "def")); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\347\210\254\346\245\274\346\242\257_70_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\347\210\254\346\245\274\346\242\257_70_\347\256\200\345\215\225/Solution1.java" index a1260432..999e9afe 100644 --- "a/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\347\210\254\346\245\274\346\242\257_70_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/dynamic/src/main/java/cn/lastwhisper/leetcode/dynamic/\347\210\254\346\245\274\346\242\257_70_\347\256\200\345\215\225/Solution1.java" @@ -15,7 +15,6 @@ public int climbStairs(int n) { if (n == 0 || n == 1) { return 1; } - return climbStairs(n - 1) + climbStairs(n - 2); } diff --git "a/algorithms/leetcode/hashtable/src/main/java/cn/lastwhisper/leetcode/hashtable/\346\213\274\345\206\231\345\215\225\350\257\215_1160_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/hashtable/src/main/java/cn/lastwhisper/leetcode/hashtable/\346\213\274\345\206\231\345\215\225\350\257\215_1160_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..2f759693 --- /dev/null +++ "b/algorithms/leetcode/hashtable/src/main/java/cn/lastwhisper/leetcode/hashtable/\346\213\274\345\206\231\345\215\225\350\257\215_1160_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,51 @@ +package cn.lastwhisper.leetcode.hashtable.拼写单词_1160_简单; + +import org.junit.Assert; + +import java.util.Arrays; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/find-words-that-can-be-formed-by-characters/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度:O(n^2) + * 空间复杂度:O(n) + */ + public int countCharacters(String[] words, String chars) { + int[] charsFreq = new int[26]; + // 统计频率 + for (int i = 0; i < chars.length(); i++) { + charsFreq[chars.charAt(i) - 'a']++; + } + int ans = 0; + + int[] wordFreq = new int[26]; + for (String word : words) { + // 字母表必须比单词长,字母只许出现一次 + if (chars.length() >= word.length()) { + Arrays.fill(wordFreq, 0); + boolean flag = true; + for (int i = 0; i < word.length(); i++) { + wordFreq[word.charAt(i) - 'a']++; + // 先加,在比较 + if (wordFreq[word.charAt(i) - 'a'] > charsFreq[word.charAt(i) - 'a']) { + flag = false; + break; + } + } + if (flag) { + ans += word.length(); + } + } + } + return ans; + } + + public static void main(String[] args) { + Assert.assertEquals(6, new Solution1().countCharacters(new String[]{"cat", "bt", "hat", "tree"}, "atach")); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/hashtable/src/main/java/cn/lastwhisper/leetcode/hashtable/\351\225\277\345\233\236\346\226\207\344\270\262_409_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/hashtable/src/main/java/cn/lastwhisper/leetcode/hashtable/\351\225\277\345\233\236\346\226\207\344\270\262_409_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..ffe0ae4c --- /dev/null +++ "b/algorithms/leetcode/hashtable/src/main/java/cn/lastwhisper/leetcode/hashtable/\351\225\277\345\233\236\346\226\207\344\270\262_409_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,43 @@ +package cn.lastwhisper.leetcode.hashtable.长回文串_409_简单; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/longest-palindrome/ + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + * ------------------------------------------------------------------- + */ + public int longestPalindrome(String s) { + int[] freq = new int[58]; + for (int i = 0; i < s.length(); i++) { + freq[s.charAt(i) - 'A']++; + } + int ans = 0; + for (int num : freq) { + // 偶数直接可以组成回文串,奇数取最大偶数组成回文串 + //不等价 if (num != 0) ans += num;return ans ; + //简写 if (num != 0) ans += num - (num & 1); + if (num != 0) { + if (num % 2 == 0) { + ans += num; + } else { + ans += num - 1;//大于1的奇数串只取偶数个,return补偿 + } + } + } + return ans < s.length() ? ans + 1 : ans; + } + + public static void main(String[] args) { + //Assert.assertEquals(7, new Solution1().longestPalindrome("abccccdd")); + Assert.assertEquals(3, new Solution1().longestPalindrome("ccc")); + } + +} \ No newline at end of file diff --git a/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/array/ArrayUtil.java b/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/array/ArrayUtil.java new file mode 100644 index 00000000..70e5f2bc --- /dev/null +++ b/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/array/ArrayUtil.java @@ -0,0 +1,72 @@ +package cn.lastwhisper.leetcode.common.array; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author lastwhisper + * @date 2020/2/4 + */ +public class ArrayUtil { + + /** + * {"ab","cd"}=> + * 创建二维字符数组 + */ + public static char[][] createCharArrays(String[] arr) { + int m = arr.length, n = arr[0].length(); + char[][] chars = new char[m][n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + chars[i][j] = arr[i].charAt(j); + } + } + return chars; + } + + /** + * {{"a","b","c","d"}}=> + * 创建二维字符数组 + */ + public static char[][] createCharArrays(String[][] arr) { + int m = arr.length, n = arr[0].length; + char[][] chars = new char[m][n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + chars[i][j] = arr[i][j].charAt(0); + } + } + return chars; + } + + /** + * 创建二维数组 + */ + public static int[][] createIntArrays(String[] arr) { + int m = arr.length, n = arr[0].length(); + int[][] ints = new int[m][n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + ints[i][j] = arr[i].charAt(j) - '0'; + } + } + return ints; + } + + + /** + * 创建list + */ + public static List> createList(int[][] arrays) { + List> lists = new ArrayList<>(arrays.length); + for (int[] array : arrays) { + List list = new ArrayList<>(array.length); + for (int num : array) { + list.add(num); + } + lists.add(list); + } + return lists; + } +} diff --git a/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/LinkedListUtil.java b/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/LinkedListUtil.java index 41e6bdaa..de66fc6c 100644 --- a/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/LinkedListUtil.java +++ b/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/LinkedListUtil.java @@ -106,65 +106,6 @@ public static List createIntersectListNode( return listNodes; } - private static ListNode createListNode(String arr) { - if (arr == null) { - return null; - } - ListNode head = new ListNode(arr.charAt(0) - '0'); - ListNode current = head; - - for (int i = 1; i < arr.length(); i++) { - current.next = new ListNode(arr.charAt(i) - '0'); - current = current.next; - } - return head; - } - - /** - * 反序创建链表 - */ - private static ListNode createReverseListNode(String arr) { - if (arr == null) { - return null; - } - - ListNode head = new ListNode(arr.charAt(arr.length() - 1) - '0'); - ListNode current = head; - - for (int i = arr.length() - 2; i >= 0; i--) { - current.next = new ListNode(arr.charAt(i) - '0'); - current = current.next; - } - return head; - } - - /** - * 两个字符串整数相加 - */ - public String add(String a, String b) { - StringBuilder sb = new StringBuilder(); - // 进位 - int carry = 0; - int aIndex = a.length() - 1, bIndex = b.length() - 1; - - while (aIndex >= 0 || bIndex >= 0) { - int x, y, sum; - x = aIndex >= 0 ? a.charAt(aIndex) - '0' : 0; - y = bIndex >= 0 ? b.charAt(bIndex) - '0' : 0; - - sum = carry + x + y; - carry = sum / 10; - sb.append(sum % 10); - - aIndex--; - bIndex--; - } - - if (carry > 0) { - sb.append(carry); - } - return sb.toString(); - } /** * 打印单链表 @@ -192,85 +133,6 @@ private static String appendVal(ListNode head) { return sb.toString(); } - /** - * 反转链表 - */ - public static ListNode reverseListNode(ListNode head) { - ListNode prev = null; - ListNode current = head; - ListNode next = null; - - while (current != null) { - next = current.next; - - current.next = prev; - prev = current; - current = next; - } - return prev; - } - - /** - * 交替合并两个链表,返回新的链表 - */ - public static ListNode alterNoteMerge(ListNode l1, ListNode l2) { - - return null; - } - - /** - * 交替合并两个链表,到第一个链表 - * https://leetcode-cn.com/problems/reorder-list - */ - public static void alterNoteMergeOne(ListNode firstHead, ListNode secondHead) { - ListNode firstNext; - ListNode secondNext; - - while (secondHead != null) { - // 1.记录两个链表的next节点 - firstNext = firstHead.next; - secondNext = secondHead.next; - // 2.将链表1的当前节点指向链表2的当前节点,链表2的当前节点指向链表1的下一个节点 - // 左链表:1->2->3 右链表:5->4 - // 合并后的链表1:1->5->2 - firstHead.next = secondHead; - secondHead.next = firstNext; - // 3.将之前保存的next更新为当前节点,继续循环 - firstHead = firstNext; - secondHead = secondNext; - // 防止奇数节点链表成环 https://leetcode-cn.com/problems/reorder-list/ - if (secondHead == null) { - firstHead.next = null; - } - } - } - - /** - * 找到链表中间的前一个节点 - */ - public static ListNode middleBeforeNode(ListNode head) { - ListNode fast = head; - ListNode slow = head; - while (fast.next != null && fast.next.next != null) { - fast = fast.next.next; - slow = slow.next; - } - return slow; - } - - /** - * 找到链表中间的一个节点 - * https://leetcode-cn.com/problems/middle-of-the-linked-list/ - */ - public static ListNode middleNode(ListNode head) { - ListNode fast = head; - ListNode slow = head; - while (fast != null && fast.next != null) { - fast = fast.next.next; - slow = slow.next; - } - return slow; - } public static void main(String[] args) { //printListNode(createListNode(1, 2, 3, 4, 5, 6, 7)); diff --git a/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/matrix/ArrayUtils.java b/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/matrix/ArrayUtils.java deleted file mode 100644 index d4338cc6..00000000 --- a/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/matrix/ArrayUtils.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.lastwhisper.leetcode.common.matrix; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author lastwhisper - * @date 2020/2/4 - */ -public class ArrayUtils { - - /** - * {"ab","cd"}=> - * 创建二维字符数组 - */ - public static char[][] createCharArrays(String[] arr) { - int m = arr.length, n = arr[0].length(); - char[][] chars = new char[m][n]; - for (int i = 0; i < m; i++) { - for (int j = 0; j < n; j++) { - chars[i][j] = arr[i].charAt(j); - } - } - return chars; - } - - /** - * {{"a","b","c","d"}}=> - * 创建二维字符数组 - */ - public static char[][] createCharArrays(String[][] arr) { - int m = arr.length, n = arr[0].length; - char[][] chars = new char[m][n]; - for (int i = 0; i < m; i++) { - for (int j = 0; j < n; j++) { - chars[i][j] = arr[i][j].charAt(0); - } - } - return chars; - } - - /** - * 创建二维数组 - */ - public static int[][] createIntArrays(String[] arr) { - int m = arr.length, n = arr[0].length(); - int[][] ints = new int[m][n]; - for (int i = 0; i < m; i++) { - for (int j = 0; j < n; j++) { - ints[i][j] = arr[i].charAt(j) - '0'; - } - } - return ints; - } - - - /** - * 创建list - */ - public static List> createList(int[][] arrays) { - List> lists = new ArrayList<>(arrays.length); - for (int[] array : arrays) { - List list = new ArrayList<>(array.length); - for (int num : array) { - list.add(num); - } - lists.add(list); - } - return lists; - } -} diff --git a/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/print/PrintUtil.java b/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/print/PrintUtil.java new file mode 100644 index 00000000..cbed2538 --- /dev/null +++ b/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/print/PrintUtil.java @@ -0,0 +1,93 @@ +package cn.lastwhisper.leetcode.common.print; + +import java.util.Collection; +import java.util.List; + + +/** + * 打印工具类 + * @author lastwhisper + * @date 2020/2/1 + */ +public class PrintUtil { + + /** + * 层次打印二维数组 + */ + public static void printLists(List> lists) { + System.out.println("["); + int counter1 = 1; + for (List list : lists) { + System.out.print("\t[\""); + int counter2 = 1; + for (Integer i : list) { + if (counter2 != list.size()) { + System.out.print(i + "\",\""); + } else { + System.out.print(i); + } + counter2++; + } + if (counter1 != lists.size()) { + System.out.print("\"],\n"); + } else { + System.out.print("\"]\n"); + } + counter1++; + } + System.out.println("]"); + } + + public static void printStringLists(List> lists) { + System.out.println("["); + int counter1 = 1; + for (List list : lists) { + System.out.print("\t[\""); + int counter2 = 1; + for (String i : list) { + if (counter2 != list.size()) { + System.out.print(i + "\",\""); + } else { + System.out.print(i ); + } + counter2++; + } + if (counter1 != lists.size()) { + System.out.print("\"],\n"); + } else { + System.out.print("\"]\n"); + } + counter1++; + } + System.out.println("]"); + } + + /** + * 打印数组 + */ + public static void printList(Collection collection) { + System.out.println(collection2String(collection)); + } + + /** + * 将Collection扁平化迭代成String + */ + public static String collection2String(Collection collection) { + StringBuilder sb = new StringBuilder(); + try { + sb.append("[\""); + int counter = 1; + for (Object object : collection) { + sb.append(object); + if (counter != collection.size()) { + sb.append("\",\""); + } + counter++; + } + sb.append("\"]"); + } catch (Exception e) { + e.printStackTrace(); + } + return sb.toString(); + } +} diff --git a/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/tree/TreeUtil.java b/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/tree/TreeUtil.java new file mode 100644 index 00000000..b3a6dbab --- /dev/null +++ b/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/tree/TreeUtil.java @@ -0,0 +1,258 @@ +package cn.lastwhisper.leetcode.common.tree; + +import javafx.util.Pair; + +import java.util.*; + +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; + +/** + * 树相关工具类 + * @author lastwhisper + * @date 1/16/2020 + */ +public class TreeUtil { + + /** + * 根据数组创建二叉树 + * 一、[5,4,8,11,null,13,4,7,2,null,null,null,1] + * 5 + * / \ + * 4 8 + * / / \ + * 11 13 4 + * / \ \ + * 7 2 1 + * 二、[1,null,2,3] + * 1 + * \ + * 2 + * / + * 3 + * https://blog.csdn.net/lenfranky/article/details/84444816 + * @param array 数组 + */ + public static TreeNode createTree(Integer... array) { + if (array.length == 0) return new TreeNode(0); + Deque nodeQueue = new LinkedList<>(); + // 创建一个根节点 + TreeNode root = new TreeNode(array[0]); + nodeQueue.offer(root); + TreeNode current; + // 记录当前行节点的数量(注意不一定是2的幂,而是上一行中非空节点的数量乘2) + int lineNodeNum = 2; + // 记录当前行中数字在数组中的开始位置 + int startIndex = 1; + // 记录数组中剩余的元素的数量 + int restLength = array.length - 1; + + while (restLength > 0) { + // 只有最后一行可以不满,其余行必须是满的 +// // 若输入的数组的数量是错误的,直接跳出程序 +// if (restLength < lineNodeNum) { +// System.out.println("Wrong Input!"); +// return new TreeNode(0); +// } + for (int i = startIndex; i < startIndex + lineNodeNum; i = i + 2) { + // 说明已经将nums中的数字用完,此时应停止遍历,并可以直接返回root + if (i == array.length) return root; + current = nodeQueue.poll(); + if (array[i] != null) { + current.left = new TreeNode(array[i]); + nodeQueue.offer(current.left); + } + // 同上,说明已经将nums中的数字用完,此时应停止遍历,并可以直接返回root + if (i + 1 == array.length) return root; + if (array[i + 1] != null) { + current.right = new TreeNode(array[i + 1]); + nodeQueue.offer(current.right); + } + } + startIndex += lineNodeNum; + restLength -= lineNodeNum; + lineNodeNum = nodeQueue.size() * 2; + } + + return root; + } + + /** + * 二叉树层次遍历 + */ + public static List> levelOrder(TreeNode root) { + List> result = new ArrayList<>(); + if (root == null) + return result; + + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + // 遍历每层的数据 + int size = queue.size(); + List list = new ArrayList<>(); + while (size > 0) { + root = queue.poll(); + list.add(root.val); + if (root.left != null) { + queue.add(root.left); + } + if (root.right != null) { + queue.add(root.right); + } + size--; + } + result.add(list); + } + return result; + } + + /** + * 相同的树 + * + * + * 输入: 1 1 + * / \ / \ + * 2 3 2 3 + * + * [1,2,3], [1,2,3] + * + * 输出: true + */ + public static boolean isSameTree(TreeNode p, TreeNode q) { + LinkedList queue = new LinkedList<>(); + queue.add(p); + queue.add(q); + while (!queue.isEmpty()) { + p = queue.poll(); + q = queue.poll(); + + if (p == null && q == null) continue; + if (p == null || q == null) return false; + if (p.val != q.val) return false; + + queue.add(p.left); + queue.add(q.left); + queue.add(p.right); + queue.add(q.right); + } + return true; + } + + /** + * 完全二叉树的左子树或右子树的高度 + * + * @param root 根节点的左子树或右子树 + * @return int 高度 + */ + private int countLevel(TreeNode root) { + int level = 0; + while (root != null) { + level++; + root = root.left; + } + return level; + } + + /** + * 所有节点之和 + * + * @param root + * @return int + */ + public int sumOfLeaves(TreeNode root) { + if (root == null) { + return 0; + } + return sumOfLeaves(root.left) + sumOfLeaves(root.right) + root.val; + } + + /** + * 二叉树根节点至叶子节点的最高高度 + * + * @param root 根节点 + * @return int 高度 + */ + public int maxDepth(TreeNode root) { + LinkedList> stack = new LinkedList<>(); + if (root != null) { + stack.push(new Pair<>(root, 0)); + } + int maxDepth = 0; + // stack模拟递归系统栈 + while (!stack.isEmpty()) { + Pair pair = stack.poll(); + root = pair.getKey(); + Integer height = pair.getValue(); + // dfs过程中更新最大深度 + maxDepth = Math.max(maxDepth, height); + if (root != null) { + stack.push(new Pair<>(root.right, height + 1)); + stack.push(new Pair<>(root.left, height + 1)); + } + } + return maxDepth; + } + + /** + * 二叉树根节点至叶子节点的最小高度 + * + * @param root 根节点 + * @return int 高度 + */ + public int minDepth(TreeNode root) { + if (root == null) { + return 0; + } + LinkedList> queue = new LinkedList<>(); + queue.add(new Pair<>(root, 1)); + + // 当前深度 + int currentDepth = 0; + Pair pair = null; + while (!queue.isEmpty()) { + pair = queue.poll(); + root = pair.getKey(); + currentDepth = pair.getValue(); + // 找到层中第一个叶子节点 + if (root.left == null && root.right == null) { + break; + } + if (root.left != null) { + queue.add(new Pair<>(root.left, currentDepth + 1)); + } + if (root.right != null) { + queue.add(new Pair<>(root.right, currentDepth + 1)); + } + + } + return currentDepth; + } + + /** + * 反转二叉树 + * + * @param root 根节点 + */ + public TreeNode invertTree(TreeNode root) { + if (root == null) + return null; + // 翻转当前节点的左右子节点 + TreeNode tempNode = root.left; + root.left = invertTree(root.right); + root.right = invertTree(tempNode); + return root; + } + + /** + * 输出二叉树层次遍历的结果 + */ + public static void printLevelOrder(TreeNode root) { + printLists(levelOrder(root)); + } + + public static void main(String[] args) { + printLevelOrder(createTree(1, null, 2, 3)); + //printLevelOrder(createTree(5, 4, 8, 11, null, 13, 4, 7, 2, null, null, null, 1)); + //printLevelOrder(createTree(1,2,3,null,4,5,null)); + } +} diff --git a/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/tree/TrieNode.java b/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/tree/TrieNode.java new file mode 100644 index 00000000..f2f2ceea --- /dev/null +++ b/algorithms/leetcode/leetcode-common/src/main/java/cn/lastwhisper/leetcode/common/tree/TrieNode.java @@ -0,0 +1,34 @@ +package cn.lastwhisper.leetcode.common.tree; + +public class TrieNode { + + private final int R = 26; + // 不存储真实的值,TrieNode[]中不为null表示存在 + private TrieNode[] links; + private boolean isEnd; + + public TrieNode() { + links = new TrieNode[R]; + } + + + public boolean containsKey(char ch) { + return links[ch - 'a'] != null; + } + + public TrieNode get(char ch) { + return links[ch - 'a']; + } + + public void put(char ch, TrieNode node) { + links[ch - 'a'] = node; + } + + public void setEnd() { + isEnd = true; + } + + public boolean isEnd() { + return isEnd; + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/leetcode\345\244\247\347\272\262.md" "b/algorithms/leetcode/leetcode\345\244\247\347\272\262.md" new file mode 100644 index 00000000..c2f29500 --- /dev/null +++ "b/algorithms/leetcode/leetcode\345\244\247\347\272\262.md" @@ -0,0 +1,4 @@ +双指针(快慢指针) 283、27、26、80、202 +滑动窗口 209、3、438、76 +对撞指针 167、125、344、345、11 +快速排序 75、 diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\344\270\244\344\270\244\344\272\244\346\215\242\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_24_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\344\270\244\344\270\244\344\272\244\346\215\242\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_24_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..32309b48 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\344\270\244\344\270\244\344\272\244\346\215\242\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_24_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,42 @@ +package cn.lastwhisper.leetcode.common.linkedlist.两两交换链表中的节点_24_中等; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/swap-nodes-in-pairs/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public ListNode swapPairs(ListNode head) { + + ListNode dummyHead = new ListNode(0); + dummyHead.next = head; + + ListNode p = dummyHead; + while(p.next != null && p.next.next != null ){ + ListNode node1 = p.next; + ListNode node2 = node1.next; + ListNode next = node2.next; + node2.next = node1; + node1.next = next; + p.next = node2; + p = node1; + } + + return dummyHead.next; + } + + public static void main(String[] args) { + int[] arr = {1, 2, 3, 4}; + printListNode(new Solution1().swapPairs(createListNode(arr))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_2_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_2_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..e47d6612 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_2_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,64 @@ +package cn.lastwhisper.leetcode.common.linkedlist.两数相加_2_中等; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/add-two-numbers/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:将链表转成正常的数字后,相加,然后反转; + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ + public ListNode addTwoNumbers(ListNode l1, ListNode l2) { + StringBuilder numStr1 = new StringBuilder(); + StringBuilder numStr2 = new StringBuilder(); + + while (l1 != null) { + numStr1.append(l1.val); + l1 = l1.next; + } + while (l2 != null) { + numStr2.append(l2.val); + l2 = l2.next; + } + java.math.BigInteger num1 = new java.math.BigInteger(numStr1.reverse().toString()); + java.math.BigInteger num2 = new java.math.BigInteger(numStr2.reverse().toString()); + + String sum = String.valueOf(num1.add(num2)); + + return createReverseListNode(sum); + } + + private static ListNode createReverseListNode(String arr) { + if (arr == null) { + return null; + } + ListNode head = new ListNode(arr.charAt(arr.length() - 1) - '0'); + ListNode current = head; + + for (int i = arr.length() - 2; i >= 0; i--) { + current.next = new ListNode(arr.charAt(i) - '0'); + current = current.next; + } + return head; + } + + + public static void main(String[] args) { + //int[] l1 = {1, 8}; + //int[] l2 = {0}; + + int[] l1 = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + int[] l2 = {5, 6, 4}; + printListNode(new Solution1().addTwoNumbers(createListNode(l1), createListNode(l2))); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_2_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_2_\344\270\255\347\255\211/Solution2.java" new file mode 100644 index 00000000..58d964cf --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_2_\344\270\255\347\255\211/Solution2.java" @@ -0,0 +1,54 @@ +package cn.lastwhisper.leetcode.common.linkedlist.两数相加_2_中等; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/add-two-numbers/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:整数逆序存储在链表中,正好可以正序相加 + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public ListNode addTwoNumbers(ListNode l1, ListNode l2) { + ListNode vHead = new ListNode(0); + ListNode current = vHead; + int carry = 0; + while (l1 != null || l2 != null) { + // num1、num2表示当前位的值,sum表示当前位的值+上一组进位值 + int num1, num2, sum; + num1 = l1 != null ? l1.val : 0; + num2 = l2 != null ? l2.val : 0; + + sum = carry + num1 + num2; + carry = sum / 10;//进位 + current.next = new ListNode(sum % 10);//当前位的值 + + current = current.next; + if (l1 != null) l1 = l1.next; + if (l2 != null) l2 = l2.next; + } + if (carry > 0) { + current.next = new ListNode(carry); + } + return vHead.next; + } + + public static void main(String[] args) { + //int[] arr1 = {2, 4, 3}; + //int[] arr2 = {5, 6, 4}; + + //int[] arr1 = {1, 8}; + //int[] arr2 = {0}; + + int[] arr1 = {1, 8}; + int[] arr2 = {1, 9}; + printListNode(new Solution2().addTwoNumbers(createListNode(arr1), createListNode(arr2))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_II_445_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_II_445_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..c13d8ec8 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_II_445_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,84 @@ +package cn.lastwhisper.leetcode.common.linkedlist.两数相加_II_445_中等; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/add-two-numbers-ii/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:字符串相加 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ + public ListNode addTwoNumbers(ListNode l1, ListNode l2) { + StringBuilder numStr1 = new StringBuilder(); + StringBuilder numStr2 = new StringBuilder(); + ListNode current1 = l1, current2 = l2; + while (current1 != null) { + numStr1.append(current1.val); + current1 = current1.next; + } + while (current2 != null) { + numStr2.append(current2.val); + current2 = current2.next; + } + + String sum = add(numStr1.toString(), numStr2.toString()); + + return createReverseListNode(sum); + } + + // 字符串相加 + public String add(String a, String b) { + StringBuilder sb = new StringBuilder(); + // 进位 + int carry = 0; + int aIndex = a.length() - 1, bIndex = b.length() - 1; + + while (aIndex >= 0 || bIndex >= 0) { + int x, y, sum; + x = aIndex >= 0 ? a.charAt(aIndex) - '0' : 0; + y = bIndex >= 0 ? b.charAt(bIndex) - '0' : 0; + + sum = carry + x + y; + carry = sum / 10; + sb.append(sum % 10); + + aIndex--; + bIndex--; + } + + if (carry > 0) { + sb.append(carry); + } + return sb.toString(); + } + + // 按字符串创建反序链表 + private static ListNode createReverseListNode(String arr) { + if (arr == null) { + return null; + } + + ListNode head = new ListNode(arr.charAt(arr.length() - 1) - '0'); + ListNode current = head; + + for (int i = arr.length() - 2; i >= 0; i--) { + current.next = new ListNode(arr.charAt(i) - '0'); + current = current.next; + } + return head; + } + + public static void main(String[] args) { + int[] num1 = {7, 2, 4, 3}; + int[] num2 = {5, 6, 4}; + printListNode(new Solution1().addTwoNumbers(createListNode(num1), createListNode(num2))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\206\351\232\224\351\223\276\350\241\250_86_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\206\351\232\224\351\223\276\350\241\250_86_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..59386b30 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\206\351\232\224\351\223\276\350\241\250_86_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,58 @@ +package cn.lastwhisper.leetcode.common.linkedlist.分隔链表_86_中等; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/partition-list/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public ListNode partition(ListNode head, int x) { + + if (head == null) { + return null; + } + + ListNode greaterNode = new ListNode(-1); + ListNode lessNode = new ListNode(0); + ListNode currentGreater = greaterNode; + ListNode currentLess = lessNode; + + while (head != null) { + if (head.val < x) { + currentLess.next = head; + currentLess = currentLess.next; + // 防止出现环形链表 + if (head.next == null) { + currentGreater.next = null; + } + } else { + currentGreater.next = head; + currentGreater = currentGreater.next; + if (head.next == null) { + currentLess.next = null; + } + } + head = head.next; + } + currentLess.next = greaterNode.next; + + return lessNode.next; + } + + public static void main(String[] args) { + int[] arr = {1,4,3,2,5,2}; + int x = 3; + + printListNode(new Solution1().partition(createListNode(arr), x)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..050e2bd5 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,57 @@ +package cn.lastwhisper.leetcode.common.linkedlist.删除排序链表中的重复元素_83_简单; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import java.util.HashSet; +import java.util.Set; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/ + * ------------------------------------------------------------------- + * 思考: + * 数据特征: + * 输入:链表、**升序**、所有整数 + * ------------------------------------------------------------------- + * 思路:遍历链表并使用Hash表判断是否重复,对重复节点使用链表删除法 + * prev指针移动规则: + * 出现重复时,删除重复节点,不后移 + * 不重复时,向后移一位即可(current永远是prev的后一位) + * current指针移动规则: + * 每步都要后移一位 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + * ------------------------------------------------------------------- + */ + public ListNode deleteDuplicates(ListNode head) { + if (head == null || head.next == null) + return head; + + Set set = new HashSet<>(); + ListNode prev = null; + ListNode current = head; + while (current != null) { + if (set.contains(current.val)) { + // 出现重复值时删除current节点,current节点没有指向即为删除 + prev.next = current.next; + } else { + set.add(current.val); + // 无重复,prev指针后移 + prev = current; + } + current = current.next; + } + return head; + } + + public static void main(String[] args) { + int[] arr = {1, 1, 1}; + //int[] arr = {1, 1, 2, 4}; + + printListNode(new Solution1().deleteDuplicates(createListNode(arr))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..c7f64729 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,49 @@ +package cn.lastwhisper.leetcode.common.linkedlist.删除排序链表中的重复元素_83_简单; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/ + * ------------------------------------------------------------------- + * 思考: + * 数据特征: + * 输入:链表、**升序**、所有整数 + * ------------------------------------------------------------------- + * 思路:链表数据升序,这个条件很重要,可以使用两个指针,current指向当前节点、next指向下一个节点 + * 判断当前节点和下一个节点是否相同,相同删除,不相同同时后移 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + * ------------------------------------------------------------------- + */ + public ListNode deleteDuplicates(ListNode head) { + if (head == null || head.next == null) + return head; + + ListNode current = head; + ListNode next = head.next; + while (next != null) { + if (next.val == current.val) { + // 出现重复删除节点,并后移next节点 + current.next = next.next; + } else { + // 无重复同时后移 + current = next; + } + next = next.next; + } + return head; + } + + public static void main(String[] args) { + int[] arr = {1, 1, 1}; + //int[] arr = {1, 1, 2, 4}; + //int[] arr = {1, 2, 3, 3, 4}; + + printListNode(new Solution2().deleteDuplicates(createListNode(arr))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution3.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution3.java" new file mode 100644 index 00000000..f1cd9f7b --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution3.java" @@ -0,0 +1,47 @@ +package cn.lastwhisper.leetcode.common.linkedlist.删除排序链表中的重复元素_83_简单; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution3 { + /** + * 题目地址:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/ + * ------------------------------------------------------------------- + * 思考: + * 数据特征: + * 输入:链表、**升序**、所有整数 + * ------------------------------------------------------------------- + * 思路:将思路2的遍历改成递归 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + * ------------------------------------------------------------------- + */ + public ListNode deleteDuplicates(ListNode head) { + if (head == null || head.next == null) + return head; + ListNode next = head.next; + /* + * 外层循环可以根据数据规则添加 + * 比如{1,2,3,4,4,4,5,6,7,8,9,9,9,9},有规则重复位置 + * 此时可以用if探测是否进入规则重复位置 + */ + //if (next.val == head.val) { + // next = next.next; + while (next != null && next.val == head.val) + next = next.next; + //} + head.next = deleteDuplicates(next); + return head; + } + + public static void main(String[] args) { + //int[] arr = {1, 1, 1}; + //int[] arr = {1, 1, 2, 4}; + int[] arr = {1, 2, 3, 3, 4}; + + printListNode(new Solution3().deleteDuplicates(createListNode(arr))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_II_82_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_II_82_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..556b2c77 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_II_82_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,73 @@ +package cn.lastwhisper.leetcode.common.linkedlist.删除排序链表中的重复元素_II_82_中等; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/ + * ------------------------------------------------------------------- + * 思考: + * 数据特征: + * 输入:链表、**升序**、所有整数 + * ------------------------------------------------------------------- + * 思路:分为三种情况 + * (1)1,2,2,3 + * (2)1,1,1,1 + * (3)1,1,2,3 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public ListNode deleteDuplicates(ListNode head) { + if (head == null || head.next == null) + return head; + + ListNode prev = null; + ListNode current = head; + ListNode next = head.next; + + while (next != null) { + if (current.val == next.val) { + // 删除第2个重复节点 + current.next = next.next; + next = next.next; + // 删除第2+个重复节点 + while (next != null && current.val == next.val) { + current.next = next.next; + next = next.next; + } + // prev!=null说明[m..n]出现重复 + if (prev != null) { + // 删除第1个重复节点 + prev.next = current.next; + } else { + // prev==null说明从[1..m]都是重复的,[m..n]还不好说 + head = current.next; + } + } else { + // 无重复时prev后移 + prev = current; + } + // 1,1,1这种情况,next=null + if (next == null) { + break; + } + // 不管是否重复current、next都必须后移 + current = next; + next = next.next; + } + return head; + } + + public static void main(String[] args) { + + //int[] arr = {1, 2, 3, 3, 4, 4, 5}; + //int[] arr = {1, 1, 1}; + int[] arr = {1, 1, 1, 2, 3}; + + printListNode(new Solution1().deleteDuplicates(createListNode(arr))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_237_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_237_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..02ab538c --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_237_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,38 @@ +package cn.lastwhisper.leetcode.common.linkedlist.删除链表中的节点_237_简单; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/delete-node-in-a-linked-list/ + * ------------------------------------------------------------------- + * 思考:删除节点的两种思路 + * ------------------------------------------------------------------- + * 思路:将下一个节点值给当前节点,删除下一个节点 + * ------------------------------------------------------------------- + * 时间复杂度:O(1) + * 空间复杂度:O(1) + */ + public void deleteNode(ListNode node) { + ListNode next = node.next; + node.val = next.val; + node.next = next.next; + } + + public static void main(String[] args) { + ListNode head = new ListNode(4); + ListNode listNode1 = new ListNode(5); + ListNode listNode2 = new ListNode(1); + ListNode listNode3 = new ListNode(9); + head.next = listNode1; + listNode1.next = listNode2; + listNode2.next = listNode3; + + printListNode("删除前:\t", head); + new Solution1().deleteNode(listNode1); + printListNode("删除后:\t", head); + + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271_19_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271_19_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..01351ab7 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271_19_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,48 @@ +package cn.lastwhisper.leetcode.common.linkedlist.删除链表的倒数第N个节点_19_中等; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/ + * ------------------------------------------------------------------- + * 思考:特殊节点,头节点、尾节点 + * ------------------------------------------------------------------- + * 思路:虚拟头节点+快慢指针 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public ListNode removeNthFromEnd(ListNode head, int n) { + // 虚拟头节点解决删除头节点问题 + ListNode dummyNode = new ListNode(0); + dummyNode.next = head; + + ListNode fast = dummyNode; + ListNode slow = dummyNode; + for (int i = 0; i < n; i++) { + fast = fast.next; + } + + while (fast != null && fast.next != null) { + fast = fast.next; + slow = slow.next; + } + slow.next = slow.next.next; + + return dummyNode.next; + } + + public static void main(String[] args) { + int[] arr = {1, 2, 3, 4, 5}; + int n = 2; + + //int[] arr = {1}; + //int n =1; + + printListNode(new Solution1().removeNthFromEnd(createListNode(arr), n)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..bd018759 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,55 @@ +package cn.lastwhisper.leetcode.common.linkedlist.反转链表_206_简单; + +import cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil; +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { val = x; } + * } + */ +public class Solution1 { + + /** + * 题目地址:https://leetcode-cn.com/problems/reverse-linked-list/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:iteratively + * 需要三个指针prev、current、next帮助反转 + * prev指向前一个节点 + * current指向当前正在反转的节点 + * next指向下一个待反转的节点 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + * ------------------------------------------------------------------- + * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户 + * 内存消耗 :37.3 MB, 在所有 Java 提交中击败了24.92%的用户 + */ + public ListNode reverseList(ListNode head) { + + ListNode prev = null; + ListNode current = head; + ListNode next; + + while (current != null) { + next = current.next; + // 反转 + current.next = prev; + // 后移 + prev = current; + current = next; + } + + return prev; + } + + public static void main(String[] args) { + LinkedListUtil.printListNode(new Solution1().reverseList( + LinkedListUtil.createListNode(1, 2, 3, 4, 5, 6))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..878b27f3 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,48 @@ +package cn.lastwhisper.leetcode.common.linkedlist.反转链表_206_简单; + +import cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil; +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { val = x; } + * } + */ +public class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/reverse-linked-list/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:recursive + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) - 注意,递归是占用空间的,占用空间的大小和递归深度成正比 + * ------------------------------------------------------------------- + * 执行用时 :1 ms, 在所有 Java 提交中击败了7.79%的用户 + * 内存消耗 :37.4 MB, 在所有 Java 提交中击败了22.92%的用户 + */ + public ListNode reverseList(ListNode head) { + // 递归终止条件 + if (head == null || head.next == null) + return head; + + //与head关联 + ListNode rhead = reverseList(head.next); + + // 每次反转链表末尾的两个节点 + // head->next此刻指向head后面的链表的尾节点 + // head->next->next = head把head节点放在了尾部 + head.next.next = head; + head.next = null; + + return rhead; + } + + public static void main(String[] args) { + LinkedListUtil.printListNode(new Solution2().reverseList(LinkedListUtil.createListNode(new int[]{1, 2, 3,}))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_II_92_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_II_92_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..24e93aa8 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_II_92_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,68 @@ +package cn.lastwhisper.leetcode.common.linkedlist.反转链表_II_92_中等; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/reverse-linked-list-ii/ + * ------------------------------------------------------------------- + * 思考: + * m大于n怎么办? + * m、n为负数怎么办? + * m、n超过链表长度怎么办? + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public ListNode reverseBetween(ListNode head, int m, int n) { + if (head == null || head.next == null) + return head; + + ListNode vNode = new ListNode(-1); + vNode.next = head; + + // 保存反转前的前一个节点 + ListNode startNode = vNode; + for (int i = 0; i < m - 1; i++) { + startNode = startNode.next; + } + // 保存反转前的头节点 + ListNode mHead = startNode.next; + + // 反转需要的中间节点 + ListNode prev = null; + ListNode current = mHead; + ListNode next; + + for (int i = m; i < n+1; i++) { + // 保存next + next = current.next; + // 反转 + current.next = prev; + // prev、current后移 + prev = current; + current = next; + } + + // 反转前的前一个节点指向,反转后的头节点 + startNode.next = prev; + // 反转前的头节点指向,反转后的endNode + mHead.next = current; + + return vNode.next; + } + + public static void main(String[] args) { + //int[] arr = {1, 2, 3, 4, 5}; + //int m = 2, n = 4; + int[] arr = {3, 5}; + int m = 1, n = 2; + + printListNode(new Solution1().reverseBetween(createListNode(arr), m, n)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..6b493f80 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,52 @@ +package cn.lastwhisper.leetcode.common.linkedlist.合并两个有序链表_21_简单; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/merge-two-sorted-lists/submissions/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:设置一个虚拟头节点vNode,边遍历两个链表边比较节点大小, + * vNode指向小的那个节点,遍历完后,返回vNode.next + * ------------------------------------------------------------------- + * 时间复杂度:O(n+m),每次迭代都会添加一个链表节点,循环次数为两个链表总长度 + * 空间复杂度:O(1) + */ + public ListNode mergeTwoLists(ListNode l1, ListNode l2) { + + // 虚拟头节点,这个点不能动 + ListNode vNode = new ListNode(-1); + + // currentv负责穿针引线,l1、l2负责遍历 + ListNode currentv = vNode; + + // 将l1、l2按照升序链接到vNode上 + while (l1 != null && l2 != null) { + if (l1.val <= l2.val) { + currentv.next = l1; + l1 = l1.next; + } else { + currentv.next = l2; + l2 = l2.next; + } + currentv = currentv.next; + } + // l1、l2某个不为空,直接链接上 + currentv.next = l1 == null ? l2 : l1; + + return vNode.next; + } + + public static void main(String[] args) { + ListNode head1 = createListNode(1, 2, 4); + ListNode head2 = createListNode(1, 3, 4, 5); + printListNode(head1); + printListNode(head2); + printListNode(new Solution1().mergeTwoLists(head1, head2)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..21bf176a --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,44 @@ +package cn.lastwhisper.leetcode.common.linkedlist.合并两个有序链表_21_简单; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/merge-two-sorted-lists/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度:O(m+n) + * 空间复杂度:O(m+n),递归深度 + */ + public ListNode mergeTwoLists(ListNode l1, ListNode l2) { + if (l1 == null) { + return l2; + } + if (l2 == null) { + return l1; + } + + if (l1.val < l2.val) { + l1.next = mergeTwoLists(l1.next, l2); + return l1; + } else { + l2.next = mergeTwoLists(l1, l2.next); + return l2; + } + + } + + public static void main(String[] args) { + ListNode head1 = createListNode(1, 2, 4); + ListNode head2 = createListNode(1, 3, 4, 5); + printListNode(head1); + printListNode(head2); + printListNode(new Solution2().mergeTwoLists(head1, head2)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\233\236\346\226\207\351\223\276\350\241\250_234_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\233\236\346\226\207\351\223\276\350\241\250_234_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..d2411e97 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\233\236\346\226\207\351\223\276\350\241\250_234_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,76 @@ +package cn.lastwhisper.leetcode.common.linkedlist.回文链表_234_简单; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/palindrome-linked-list/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:使用快慢指针遍历到链表的中间节点,反转头节点到中间节点这部分链表, + * 从中间节点开始遍历,比较反转链表 + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public boolean isPalindrome(ListNode head) { + if (head == null) return true; + // 找到链表中间节点 + ListNode slow = endOfFirstHalf(head); + // 反转链表 + ListNode reverseHead = reverseListNode(slow.next); + + ListNode firstHead = head; + + while (reverseHead != null && firstHead != null) { + if (reverseHead.val != firstHead.val) { + return false; + } + reverseHead = reverseHead.next; + firstHead = firstHead.next; + } + + // 包含单个节点的情况 + return true; + } + + private ListNode endOfFirstHalf(ListNode head) { + ListNode fast = head; + ListNode slow = head; + while (fast.next != null && fast.next.next != null) { + fast = fast.next.next; + slow = slow.next; + } + return slow; + } + + /** + * 反转链表 + */ + private static ListNode reverseListNode(ListNode head) { + ListNode prev = null; + ListNode current = head; + ListNode next = null; + + while (current != null) { + next = current.next; + + current.next = prev; + prev = current; + current = next; + } + return prev; + } + + public static void main(String[] args) { + //int[] arr = {1, 2, 3, 2, 1}; + //int[] arr = {1, 2, 2, 1}; + //int[] arr = {1, 2}; + //int[] arr = {1}; + int[] arr = {1, 0, 1}; + System.out.println(new Solution1().isPalindrome(createListNode(arr))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\245\207\345\201\266\351\223\276\350\241\250_328_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\245\207\345\201\266\351\223\276\350\241\250_328_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..e6a82e4b --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\345\245\207\345\201\266\351\223\276\350\241\250_328_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,62 @@ +package cn.lastwhisper.leetcode.common.linkedlist.奇偶链表_328_中等; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/odd-even-linked-list/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:建立两个奇偶虚拟头节点,遍历输入链表,将满足条件的节点, + * 挂载到奇偶节点上,最后将奇偶链表拼接 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public ListNode oddEvenList(ListNode head) { + if (head == null) { + return null; + } + + ListNode oddNode = new ListNode(-1); + ListNode evenNode = new ListNode(0); + ListNode currentOdd = oddNode; + ListNode currentEven = evenNode; + + int index = 1; + + while (head != null) { + if (index % 2 == 0) { //将index改成head.val,就是按值进行奇偶链表 + currentEven.next = head; + currentEven = currentEven.next; + /* + * 如果最后一个节点是偶数节点,将当前奇数节点的next置为null, + * 因为奇数节点的next可能指向偶数节点,但是head遍历完了,这个next无法更新, + * 会出现环形链表 + */ + if (head.next == null) { + currentOdd.next = null; + } + } else { + currentOdd.next = head; + currentOdd = currentOdd.next; + if (head.next == null) { + currentEven.next = null; + } + } + head = head.next; + index++; + } + currentOdd.next = evenNode.next; + + return oddNode.next; + } + + public static void main(String[] args) { + printListNode(new Solution1().oddEvenList(createListNode(1, 2, 3, 4, 5))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\216\257\345\275\242\351\223\276\350\241\250_141_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\216\257\345\275\242\351\223\276\350\241\250_141_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..ed1b4bf1 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\216\257\345\275\242\351\223\276\350\241\250_141_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,43 @@ +package cn.lastwhisper.leetcode.common.linkedlist.环形链表_141_简单; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createLoopListNode; + +public class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/linked-list-cycle/submissions/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:快慢指针(龟兔赛跑) + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public boolean hasCycle(ListNode head) { + if (head == null||head.next == null) { + return false; + } + ListNode fast = head; + ListNode slow = head; + + while (fast != null && fast.next != null) { + fast = fast.next.next; + slow = slow.next; + if (fast == slow) { + return true; + } + } + + return false; + } + + + public static void main(String[] args) { + int pos = 1; + int[] arr = {3, 2, 0, -4}; + ListNode loopListNode = createLoopListNode(pos, arr); + System.out.println(new Solution1().hasCycle(loopListNode)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\216\257\345\275\242\351\223\276\350\241\250_141_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\216\257\345\275\242\351\223\276\350\241\250_141_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..fb2e0bab --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\216\257\345\275\242\351\223\276\350\241\250_141_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,43 @@ +package cn.lastwhisper.leetcode.common.linkedlist.环形链表_141_简单; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import java.util.HashSet; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createLoopListNode; + +public class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/linked-list-cycle/submissions/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:hash表 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ + public boolean hasCycle(ListNode head) { + if (head == null || head.next == null) { + return false; + } + HashSet set = new HashSet<>(); + while (head != null) { + if (set.contains(head)) { + return true; + } + set.add(head); + head = head.next; + } + + return false; + } + + + public static void main(String[] args) { + int pos = 1; + int[] arr = {3, 2, 0, -4}; + ListNode loopListNode = createLoopListNode(pos, arr); + System.out.println(new Solution2().hasCycle(loopListNode)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\233\270\344\272\244\351\223\276\350\241\250_160_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\233\270\344\272\244\351\223\276\350\241\250_160_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..a5407716 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\233\270\344\272\244\351\223\276\350\241\250_160_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,33 @@ +package cn.lastwhisper.leetcode.common.linkedlist.相交链表_160_简单; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +public class Solution1 { + /** + * 题目地址: + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public ListNode getIntersectionNode(ListNode headA, ListNode headB) { + /* + 定义两个指针, 第一轮让两个到达末尾的节点指向另一个链表的头部, 最后如果相遇则为交点(在第一轮移动中恰好抹除了长度差) + 两个指针等于移动了相同的距离, 有交点就返回, 无交点就是各走了两条指针的长度 + **/ + if (headA == null || headB == null) return null; + ListNode pA = headA, pB = headB; + // 在这里第一轮体现在pA和pB第一次到达尾部会移向另一链表的表头, 而第二轮体现在如果pA或pB相交就返回交点, 不相交最后就是null==null + while (pA != pB) { + pA = pA == null ? headB : pA.next; + pB = pB == null ? headA : pB.next; + } + return pA; + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\233\270\344\272\244\351\223\276\350\241\250_160_\347\256\200\345\215\225/\345\217\202\350\200\203" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\233\270\344\272\244\351\223\276\350\241\250_160_\347\256\200\345\215\225/\345\217\202\350\200\203" similarity index 100% rename from "algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\233\270\344\272\244\351\223\276\350\241\250_160_\347\256\200\345\215\225/\345\217\202\350\200\203" rename to "algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\233\270\344\272\244\351\223\276\350\241\250_160_\347\256\200\345\215\225/\345\217\202\350\200\203" diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\247\273\351\231\244\351\223\276\350\241\250\345\205\203\347\264\240_203_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\247\273\351\231\244\351\223\276\350\241\250\345\205\203\347\264\240_203_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..ebabad40 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\247\273\351\231\244\351\223\276\350\241\250\345\205\203\347\264\240_203_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,61 @@ +package cn.lastwhisper.leetcode.common.linkedlist.移除链表元素_203_简单; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/remove-linked-list-elements/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:设置虚拟头节点 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public ListNode removeElements(ListNode head, int val) { + if (head == null) + return null; + + //虚拟头节点 + ListNode vNode = new ListNode(-1); + vNode.next = head; + + // 前节点 + ListNode prev = vNode; + // 当前节点 + ListNode current = head; + + while (current != null) { + if (current.val == val) { + prev.next = current.next; + } else { + prev = prev.next; + } + current = current.next; + } + + return vNode.next; + } + + public static void main(String[] args) { + // example + int[] arr = {1, 2, 6, 3, 4, 5, 6}; + int x = 6; + + // error example + //int[] arr = {1}; + //int x = 1; + + //int[] arr = {1}; + //int x = 2; + + //int[] arr = {1, 1}; + //int x = 1; + + printListNode(new Solution1().removeElements(createListNode(arr), x)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\247\273\351\231\244\351\223\276\350\241\250\345\205\203\347\264\240_203_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\247\273\351\231\244\351\223\276\350\241\250\345\205\203\347\264\240_203_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..01785c68 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\347\247\273\351\231\244\351\223\276\350\241\250\345\205\203\347\264\240_203_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,60 @@ +package cn.lastwhisper.leetcode.common.linkedlist.移除链表元素_203_简单; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/remove-linked-list-elements/ + * ------------------------------------------------------------------- + * 思考:不设置虚拟头节点 + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public ListNode removeElements(ListNode head, int val) { + if (head == null) + return null; + // 前节点 + ListNode prev = null; + // 当前节点 + ListNode current = head; + while (current != null) { + if (current.val == val) { + // 找到目标值之后分为两种情况 + if (prev != null) { + prev.next = current.next; + } else { + head = current.next; + } + } else { + prev = current; + } + current = current.next; + } + + return head; + } + + public static void main(String[] args) { + // example + //int[] arr = {1, 2, 6, 3, 4, 5, 6}; + //int x = 6; + + // error example + //int[] arr = {1}; + //int x = 1; + + //int[] arr = {1}; + //int x = 2; + + int[] arr = {1, 1}; + int x = 1; + + printListNode(new Solution2().removeElements(createListNode(arr), x)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\350\256\276\350\256\241\350\267\263\350\241\250_1206_\345\233\260\351\232\276/Skiplist.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\350\256\276\350\256\241\350\267\263\350\241\250_1206_\345\233\260\351\232\276/Skiplist.java" similarity index 94% rename from "algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\350\256\276\350\256\241\350\267\263\350\241\250_1206_\345\233\260\351\232\276/Skiplist.java" rename to "algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\350\256\276\350\256\241\350\267\263\350\241\250_1206_\345\233\260\351\232\276/Skiplist.java" index 83d88e52..d7ffab90 100644 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\350\256\276\350\256\241\350\267\263\350\241\250_1206_\345\233\260\351\232\276/Skiplist.java" +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\350\256\276\350\256\241\350\267\263\350\241\250_1206_\345\233\260\351\232\276/Skiplist.java" @@ -1,4 +1,4 @@ -package cn.lastwhisper.leetcode.linkedlist.设计跳表_1206_困难; +package cn.lastwhisper.leetcode.common.linkedlist.设计跳表_1206_困难; public class Skiplist { /** diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\351\207\215\346\216\222\351\223\276\350\241\250_143_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\351\207\215\346\216\222\351\223\276\350\241\250_143_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..b7101ae0 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\351\207\215\346\216\222\351\223\276\350\241\250_143_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,99 @@ +package cn.lastwhisper.leetcode.common.linkedlist.重排链表_143_中等; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; +import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/reorder-list/ + * ------------------------------------------------------------------- + * 思考: + * 奇数与偶数链表情况不同,奇数链表会成环 + * ------------------------------------------------------------------- + * 思路:找到链表中间节点,然后对剩余链表进行reverse,将两个链表合并即可 + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(1) + */ + public void reorderList(ListNode head) { + // 过滤空值 + if (head == null) { + return; + } + // 1、找到中间节点的前一个节点(找前一个节点是为了切断两个链表的联系) + ListNode middleBeforeNode = middleBeforeNode(head); + // 2、反转以中间节点为首之后的链表 + ListNode secondHead = reverseListNode(middleBeforeNode.next); + // 切断两个链表的联系,防止链表成环 + middleBeforeNode.next = null; + // 3、合并链表 + alterNoteMergeOne(head, secondHead); + } + + public static void alterNoteMergeOne(ListNode firstHead, ListNode secondHead) { + ListNode firstNext; + ListNode secondNext; + + while (secondHead != null) { + // 1.记录两个链表的next节点 + firstNext = firstHead.next; + secondNext = secondHead.next; + // 2.将链表1的当前节点指向链表2的当前节点,链表2的当前节点指向链表1的下一个节点 + // 链表1:1->2->3 链表2:5->4 + // 合并后的链表1:1->5->2 + firstHead.next = secondHead; + secondHead.next = firstNext; + // 3.将之前保存的next更新为当前节点,继续循环 + firstHead = firstNext; + secondHead = secondNext; + // 防止奇数节点链表成环 https://leetcode-cn.com/problems/reorder-list/ + if (secondHead == null) { + firstHead.next = null; + } + } + } + + /** + * 找到链表中间的前一个节点 + */ + public static ListNode middleBeforeNode(ListNode head) { + ListNode fast = head; + ListNode slow = head; + while (fast.next != null && fast.next.next != null) { + fast = fast.next.next; + slow = slow.next; + } + return slow; + } + + /** + * 反转链表 + */ + public static ListNode reverseListNode(ListNode head) { + ListNode prev = null; + ListNode current = head; + ListNode next = null; + + while (current != null) { + next = current.next; + + current.next = prev; + prev = current; + current = next; + } + return prev; + } + + public static void main(String[] args) { + // 偶数没问题 + int[] arr = {1, 2, 3, 4, 5, 6}; + // 奇数有问题 + //int[] arr = {1, 2, 3, 4, 5}; + ListNode head = createListNode(arr); + printListNode("重排前:\t", head); + new Solution1().reorderList(head); + printListNode("重排后:\t", head); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\351\223\276\350\241\250\347\232\204\344\270\255\351\227\264\347\273\223\347\202\271_876_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\351\223\276\350\241\250\347\232\204\344\270\255\351\227\264\347\273\223\347\202\271_876_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..4b128317 --- /dev/null +++ "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/common/linkedlist/\351\223\276\350\241\250\347\232\204\344\270\255\351\227\264\347\273\223\347\202\271_876_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,25 @@ +package cn.lastwhisper.leetcode.common.linkedlist.链表的中间节点_876_简单; + +import cn.lastwhisper.leetcode.common.linkedlist.ListNode; + +class Solution { + /** + * 题目地址:https://leetcode-cn.com/problems/middle-of-the-linked-list/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public ListNode middleNode(ListNode head) { + ListNode fast = head; + ListNode slow = head; + while (fast != null && fast.next != null) { + fast = fast.next.next; + slow = slow.next; + } + return slow; + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\344\270\244\344\270\244\344\272\244\346\215\242\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_24_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\344\270\244\344\270\244\344\272\244\346\215\242\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_24_\344\270\255\347\255\211/Solution1.java" deleted file mode 100644 index 89d40eef..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\344\270\244\344\270\244\344\272\244\346\215\242\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_24_\344\270\255\347\255\211/Solution1.java" +++ /dev/null @@ -1,42 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.两两交换链表中的节点_24_中等; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/swap-nodes-in-pairs/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路: - * ------------------------------------------------------------------- - * 时间复杂度: - * 空间复杂度: - */ - public ListNode swapPairs(ListNode head) { - - ListNode dummyHead = new ListNode(0); - dummyHead.next = head; - - ListNode p = dummyHead; - while(p.next != null && p.next.next != null ){ - ListNode node1 = p.next; - ListNode node2 = node1.next; - ListNode next = node2.next; - node2.next = node1; - node1.next = next; - p.next = node2; - p = node1; - } - - return dummyHead.next; - } - - public static void main(String[] args) { - int[] arr = {1, 2, 3, 4}; - printListNode(new Solution1().swapPairs(createListNode(arr))); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_2_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_2_\344\270\255\347\255\211/Solution1.java" deleted file mode 100644 index 385770a9..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_2_\344\270\255\347\255\211/Solution1.java" +++ /dev/null @@ -1,64 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.两数相加_2_中等; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/add-two-numbers/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路:将链表转成正常的数字后,相加,然后反转; - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(n) - */ - public ListNode addTwoNumbers(ListNode l1, ListNode l2) { - StringBuilder numStr1 = new StringBuilder(); - StringBuilder numStr2 = new StringBuilder(); - - while (l1 != null) { - numStr1.append(l1.val); - l1 = l1.next; - } - while (l2 != null) { - numStr2.append(l2.val); - l2 = l2.next; - } - java.math.BigInteger num1 = new java.math.BigInteger(numStr1.reverse().toString()); - java.math.BigInteger num2 = new java.math.BigInteger(numStr2.reverse().toString()); - - String sum = String.valueOf(num1.add(num2)); - - return createReverseListNode(sum); - } - - private static ListNode createReverseListNode(String arr) { - if (arr == null) { - return null; - } - ListNode head = new ListNode(arr.charAt(arr.length() - 1) - '0'); - ListNode current = head; - - for (int i = arr.length() - 2; i >= 0; i--) { - current.next = new ListNode(arr.charAt(i) - '0'); - current = current.next; - } - return head; - } - - - public static void main(String[] args) { - //int[] l1 = {1, 8}; - //int[] l2 = {0}; - - int[] l1 = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; - int[] l2 = {5, 6, 4}; - printListNode(new Solution1().addTwoNumbers(createListNode(l1), createListNode(l2))); - } - -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_2_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_2_\344\270\255\347\255\211/Solution2.java" deleted file mode 100644 index 5ce0b06a..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_2_\344\270\255\347\255\211/Solution2.java" +++ /dev/null @@ -1,54 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.两数相加_2_中等; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution2 { - /** - * 题目地址:https://leetcode-cn.com/problems/add-two-numbers/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路:整数逆序存储在链表中,正好可以正序相加 - * ------------------------------------------------------------------- - * 时间复杂度: - * 空间复杂度: - */ - public ListNode addTwoNumbers(ListNode l1, ListNode l2) { - ListNode vHead = new ListNode(0); - ListNode current = vHead; - int carry = 0; - while (l1 != null || l2 != null) { - // num1、num2表示当前位的值,sum表示当前位的值+上一组进位值 - int num1, num2, sum; - num1 = l1 != null ? l1.val : 0; - num2 = l2 != null ? l2.val : 0; - - sum = carry + num1 + num2; - carry = sum / 10;//进位 - current.next = new ListNode(sum % 10);//当前位的值 - - current = current.next; - if (l1 != null) l1 = l1.next; - if (l2 != null) l2 = l2.next; - } - if (carry > 0) { - current.next = new ListNode(carry); - } - return vHead.next; - } - - public static void main(String[] args) { - //int[] arr1 = {2, 4, 3}; - //int[] arr2 = {5, 6, 4}; - - //int[] arr1 = {1, 8}; - //int[] arr2 = {0}; - - int[] arr1 = {1, 8}; - int[] arr2 = {1, 9}; - printListNode(new Solution2().addTwoNumbers(createListNode(arr1), createListNode(arr2))); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_II_445_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_II_445_\344\270\255\347\255\211/Solution1.java" deleted file mode 100644 index 0442ad71..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\344\270\244\346\225\260\347\233\270\345\212\240_II_445_\344\270\255\347\255\211/Solution1.java" +++ /dev/null @@ -1,84 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.两数相加_II_445_中等; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/add-two-numbers-ii/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路:字符串相加 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(n) - */ - public ListNode addTwoNumbers(ListNode l1, ListNode l2) { - StringBuilder numStr1 = new StringBuilder(); - StringBuilder numStr2 = new StringBuilder(); - ListNode current1 = l1, current2 = l2; - while (current1 != null) { - numStr1.append(current1.val); - current1 = current1.next; - } - while (current2 != null) { - numStr2.append(current2.val); - current2 = current2.next; - } - - String sum = add(numStr1.toString(), numStr2.toString()); - - return createReverseListNode(sum); - } - - // 字符串相加 - public String add(String a, String b) { - StringBuilder sb = new StringBuilder(); - // 进位 - int carry = 0; - int aIndex = a.length() - 1, bIndex = b.length() - 1; - - while (aIndex >= 0 || bIndex >= 0) { - int x, y, sum; - x = aIndex >= 0 ? a.charAt(aIndex) - '0' : 0; - y = bIndex >= 0 ? b.charAt(bIndex) - '0' : 0; - - sum = carry + x + y; - carry = sum / 10; - sb.append(sum % 10); - - aIndex--; - bIndex--; - } - - if (carry > 0) { - sb.append(carry); - } - return sb.toString(); - } - - // 按字符串创建反序链表 - private static ListNode createReverseListNode(String arr) { - if (arr == null) { - return null; - } - - ListNode head = new ListNode(arr.charAt(arr.length() - 1) - '0'); - ListNode current = head; - - for (int i = arr.length() - 2; i >= 0; i--) { - current.next = new ListNode(arr.charAt(i) - '0'); - current = current.next; - } - return head; - } - - public static void main(String[] args) { - int[] num1 = {7, 2, 4, 3}; - int[] num2 = {5, 6, 4}; - printListNode(new Solution1().addTwoNumbers(createListNode(num1), createListNode(num2))); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\206\351\232\224\351\223\276\350\241\250_86_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\206\351\232\224\351\223\276\350\241\250_86_\344\270\255\347\255\211/Solution1.java" deleted file mode 100644 index 5d1ace26..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\206\351\232\224\351\223\276\350\241\250_86_\344\270\255\347\255\211/Solution1.java" +++ /dev/null @@ -1,58 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.分隔链表_86_中等; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/partition-list/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路: - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(1) - */ - public ListNode partition(ListNode head, int x) { - - if (head == null) { - return null; - } - - ListNode greaterNode = new ListNode(-1); - ListNode lessNode = new ListNode(0); - ListNode currentGreater = greaterNode; - ListNode currentLess = lessNode; - - while (head != null) { - if (head.val < x) { - currentLess.next = head; - currentLess = currentLess.next; - // 防止出现环形链表 - if (head.next == null) { - currentGreater.next = null; - } - } else { - currentGreater.next = head; - currentGreater = currentGreater.next; - if (head.next == null) { - currentLess.next = null; - } - } - head = head.next; - } - currentLess.next = greaterNode.next; - - return lessNode.next; - } - - public static void main(String[] args) { - int[] arr = {1,4,3,2,5,2}; - int x = 3; - - printListNode(new Solution1().partition(createListNode(arr), x)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution1.java" deleted file mode 100644 index 9e3374b2..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution1.java" +++ /dev/null @@ -1,57 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.删除排序链表中的重复元素_83_简单; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import java.util.HashSet; -import java.util.Set; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/ - * ------------------------------------------------------------------- - * 思考: - * 数据特征: - * 输入:链表、**升序**、所有整数 - * ------------------------------------------------------------------- - * 思路:遍历链表并使用Hash表判断是否重复,对重复节点使用链表删除法 - * prev指针移动规则: - * 出现重复时,删除重复节点,不后移 - * 不重复时,向后移一位即可(current永远是prev的后一位) - * current指针移动规则: - * 每步都要后移一位 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(n) - * ------------------------------------------------------------------- - */ - public ListNode deleteDuplicates(ListNode head) { - if (head == null || head.next == null) - return head; - - Set set = new HashSet<>(); - ListNode prev = null; - ListNode current = head; - while (current != null) { - if (set.contains(current.val)) { - // 出现重复值时删除current节点,current节点没有指向即为删除 - prev.next = current.next; - } else { - set.add(current.val); - // 无重复,prev指针后移 - prev = current; - } - current = current.next; - } - return head; - } - - public static void main(String[] args) { - int[] arr = {1, 1, 1}; - //int[] arr = {1, 1, 2, 4}; - - printListNode(new Solution1().deleteDuplicates(createListNode(arr))); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution2.java" deleted file mode 100644 index bd8b8678..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution2.java" +++ /dev/null @@ -1,49 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.删除排序链表中的重复元素_83_简单; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution2 { - /** - * 题目地址:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/ - * ------------------------------------------------------------------- - * 思考: - * 数据特征: - * 输入:链表、**升序**、所有整数 - * ------------------------------------------------------------------- - * 思路:链表数据升序,这个条件很重要,可以使用两个指针,current指向当前节点、next指向下一个节点 - * 判断当前节点和下一个节点是否相同,相同删除,不相同同时后移 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(1) - * ------------------------------------------------------------------- - */ - public ListNode deleteDuplicates(ListNode head) { - if (head == null || head.next == null) - return head; - - ListNode current = head; - ListNode next = head.next; - while (next != null) { - if (next.val == current.val) { - // 出现重复删除节点,并后移next节点 - current.next = next.next; - } else { - // 无重复同时后移 - current = next; - } - next = next.next; - } - return head; - } - - public static void main(String[] args) { - int[] arr = {1, 1, 1}; - //int[] arr = {1, 1, 2, 4}; - //int[] arr = {1, 2, 3, 3, 4}; - - printListNode(new Solution2().deleteDuplicates(createListNode(arr))); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution3.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution3.java" deleted file mode 100644 index 5b23e32b..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_83_\347\256\200\345\215\225/Solution3.java" +++ /dev/null @@ -1,47 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.删除排序链表中的重复元素_83_简单; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution3 { - /** - * 题目地址:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/ - * ------------------------------------------------------------------- - * 思考: - * 数据特征: - * 输入:链表、**升序**、所有整数 - * ------------------------------------------------------------------- - * 思路:将思路2的遍历改成递归 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(n) - * ------------------------------------------------------------------- - */ - public ListNode deleteDuplicates(ListNode head) { - if (head == null || head.next == null) - return head; - ListNode next = head.next; - /* - * 外层循环可以根据数据规则添加 - * 比如{1,2,3,4,4,4,5,6,7,8,9,9,9,9},有规则重复位置 - * 此时可以用if探测是否进入规则重复位置 - */ - //if (next.val == head.val) { - // next = next.next; - while (next != null && next.val == head.val) - next = next.next; - //} - head.next = deleteDuplicates(next); - return head; - } - - public static void main(String[] args) { - //int[] arr = {1, 1, 1}; - //int[] arr = {1, 1, 2, 4}; - int[] arr = {1, 2, 3, 3, 4}; - - printListNode(new Solution3().deleteDuplicates(createListNode(arr))); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_II_82_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_II_82_\344\270\255\347\255\211/Solution1.java" deleted file mode 100644 index 32287b4a..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\346\216\222\345\272\217\351\223\276\350\241\250\344\270\255\347\232\204\351\207\215\345\244\215\345\205\203\347\264\240_II_82_\344\270\255\347\255\211/Solution1.java" +++ /dev/null @@ -1,73 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.删除排序链表中的重复元素_II_82_中等; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/ - * ------------------------------------------------------------------- - * 思考: - * 数据特征: - * 输入:链表、**升序**、所有整数 - * ------------------------------------------------------------------- - * 思路:分为三种情况 - * (1)1,2,2,3 - * (2)1,1,1,1 - * (3)1,1,2,3 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(1) - */ - public ListNode deleteDuplicates(ListNode head) { - if (head == null || head.next == null) - return head; - - ListNode prev = null; - ListNode current = head; - ListNode next = head.next; - - while (next != null) { - if (current.val == next.val) { - // 删除第2个重复节点 - current.next = next.next; - next = next.next; - // 删除第2+个重复节点 - while (next != null && current.val == next.val) { - current.next = next.next; - next = next.next; - } - // prev!=null说明[m..n]出现重复 - if (prev != null) { - // 删除第1个重复节点 - prev.next = current.next; - } else { - // prev==null说明从[1..m]都是重复的,[m..n]还不好说 - head = current.next; - } - } else { - // 无重复时prev后移 - prev = current; - } - // 1,1,1这种情况,next=null - if (next == null) { - break; - } - // 不管是否重复current、next都必须后移 - current = next; - next = next.next; - } - return head; - } - - public static void main(String[] args) { - - //int[] arr = {1, 2, 3, 3, 4, 4, 5}; - //int[] arr = {1, 1, 1}; - int[] arr = {1, 1, 1, 2, 3}; - - printListNode(new Solution1().deleteDuplicates(createListNode(arr))); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_237_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_237_\347\256\200\345\215\225/Solution1.java" deleted file mode 100644 index 97d03f31..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_237_\347\256\200\345\215\225/Solution1.java" +++ /dev/null @@ -1,38 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.删除链表中的节点_237_简单; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/delete-node-in-a-linked-list/ - * ------------------------------------------------------------------- - * 思考:删除节点的两种思路 - * ------------------------------------------------------------------- - * 思路:将下一个节点值给当前节点,删除下一个节点 - * ------------------------------------------------------------------- - * 时间复杂度:O(1) - * 空间复杂度:O(1) - */ - public void deleteNode(ListNode node) { - ListNode next = node.next; - node.val = next.val; - node.next = next.next; - } - - public static void main(String[] args) { - ListNode head = new ListNode(4); - ListNode listNode1 = new ListNode(5); - ListNode listNode2 = new ListNode(1); - ListNode listNode3 = new ListNode(9); - head.next = listNode1; - listNode1.next = listNode2; - listNode2.next = listNode3; - - printListNode("删除前:\t", head); - new Solution1().deleteNode(listNode1); - printListNode("删除后:\t", head); - - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271_19_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271_19_\344\270\255\347\255\211/Solution1.java" deleted file mode 100644 index 609f2eab..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271_19_\344\270\255\347\255\211/Solution1.java" +++ /dev/null @@ -1,48 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.删除链表的倒数第N个节点_19_中等; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/ - * ------------------------------------------------------------------- - * 思考:特殊节点,头节点、尾节点 - * ------------------------------------------------------------------- - * 思路:虚拟头节点+快慢指针 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(1) - */ - public ListNode removeNthFromEnd(ListNode head, int n) { - // 虚拟头节点解决删除头节点问题 - ListNode dummyNode = new ListNode(0); - dummyNode.next = head; - - ListNode fast = dummyNode; - ListNode slow = dummyNode; - for (int i = 0; i < n; i++) { - fast = fast.next; - } - - while (fast != null && fast.next != null) { - fast = fast.next; - slow = slow.next; - } - slow.next = slow.next.next; - - return dummyNode.next; - } - - public static void main(String[] args) { - int[] arr = {1, 2, 3, 4, 5}; - int n = 2; - - //int[] arr = {1}; - //int n =1; - - printListNode(new Solution1().removeNthFromEnd(createListNode(arr), n)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution1.java" deleted file mode 100644 index e7a22362..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution1.java" +++ /dev/null @@ -1,55 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.反转链表_206_简单; - -import cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil; -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -/** - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode(int x) { val = x; } - * } - */ -public class Solution1 { - - /** - * 题目地址:https://leetcode-cn.com/problems/reverse-linked-list/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路:iteratively - * 需要三个指针prev、current、next帮助反转 - * prev指向前一个节点 - * current指向当前正在反转的节点 - * next指向下一个待反转的节点 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(1) - * ------------------------------------------------------------------- - * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户 - * 内存消耗 :37.3 MB, 在所有 Java 提交中击败了24.92%的用户 - */ - public ListNode reverseList(ListNode head) { - - ListNode prev = null; - ListNode current = head; - ListNode next; - - while (current != null) { - next = current.next; - // 反转 - current.next = prev; - // 后移 - prev = current; - current = next; - } - - return prev; - } - - public static void main(String[] args) { - LinkedListUtil.printListNode(new Solution1().reverseList( - LinkedListUtil.createListNode(1, 2, 3, 4, 5, 6))); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution2.java" deleted file mode 100644 index 9d88eb30..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution2.java" +++ /dev/null @@ -1,48 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.反转链表_206_简单; - -import cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil; -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -/** - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode(int x) { val = x; } - * } - */ -public class Solution2 { - /** - * 题目地址:https://leetcode-cn.com/problems/reverse-linked-list/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路:recursive - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(n) - 注意,递归是占用空间的,占用空间的大小和递归深度成正比 - * ------------------------------------------------------------------- - * 执行用时 :1 ms, 在所有 Java 提交中击败了7.79%的用户 - * 内存消耗 :37.4 MB, 在所有 Java 提交中击败了22.92%的用户 - */ - public ListNode reverseList(ListNode head) { - // 递归终止条件 - if (head == null || head.next == null) - return head; - - //与head关联 - ListNode rhead = reverseList(head.next); - - // 每次反转链表末尾的两个节点 - // head->next此刻指向head后面的链表的尾节点 - // head->next->next = head把head节点放在了尾部 - head.next.next = head; - head.next = null; - - return rhead; - } - - public static void main(String[] args) { - LinkedListUtil.printListNode(new Solution2().reverseList(LinkedListUtil.createListNode(new int[]{1, 2, 3,}))); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_II_92_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_II_92_\344\270\255\347\255\211/Solution1.java" deleted file mode 100644 index a3b3f353..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\217\215\350\275\254\351\223\276\350\241\250_II_92_\344\270\255\347\255\211/Solution1.java" +++ /dev/null @@ -1,68 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.反转链表_II_92_中等; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/reverse-linked-list-ii/ - * ------------------------------------------------------------------- - * 思考: - * m大于n怎么办? - * m、n为负数怎么办? - * m、n超过链表长度怎么办? - * ------------------------------------------------------------------- - * 思路: - * ------------------------------------------------------------------- - * 时间复杂度: - * 空间复杂度: - */ - public ListNode reverseBetween(ListNode head, int m, int n) { - if (head == null || head.next == null) - return head; - - ListNode vNode = new ListNode(-1); - vNode.next = head; - - // 保存反转前的前一个节点 - ListNode startNode = vNode; - for (int i = 0; i < m - 1; i++) { - startNode = startNode.next; - } - // 保存反转前的头节点 - ListNode mHead = startNode.next; - - // 反转需要的中间节点 - ListNode prev = null; - ListNode current = mHead; - ListNode next; - - for (int i = m; i < n+1; i++) { - // 保存next - next = current.next; - // 反转 - current.next = prev; - // prev、current后移 - prev = current; - current = next; - } - - // 反转前的前一个节点指向,反转后的头节点 - startNode.next = prev; - // 反转前的头节点指向,反转后的endNode - mHead.next = current; - - return vNode.next; - } - - public static void main(String[] args) { - //int[] arr = {1, 2, 3, 4, 5}; - //int m = 2, n = 4; - int[] arr = {3, 5}; - int m = 1, n = 2; - - printListNode(new Solution1().reverseBetween(createListNode(arr), m, n)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\347\256\200\345\215\225/Solution1.java" deleted file mode 100644 index e327f4b2..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\347\256\200\345\215\225/Solution1.java" +++ /dev/null @@ -1,52 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.合并两个有序链表_21_简单; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/merge-two-sorted-lists/submissions/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路:设置一个虚拟头节点vNode,边遍历两个链表边比较节点大小, - * vNode指向小的那个节点,遍历完后,返回vNode.next - * ------------------------------------------------------------------- - * 时间复杂度:O(n+m),每次迭代都会添加一个链表节点,循环次数为两个链表总长度 - * 空间复杂度:O(1) - */ - public ListNode mergeTwoLists(ListNode l1, ListNode l2) { - - // 虚拟头节点,这个点不能动 - ListNode vNode = new ListNode(-1); - - // currentv负责穿针引线,l1、l2负责遍历 - ListNode currentv = vNode; - - // 将l1、l2按照升序链接到vNode上 - while (l1 != null && l2 != null) { - if (l1.val <= l2.val) { - currentv.next = l1; - l1 = l1.next; - } else { - currentv.next = l2; - l2 = l2.next; - } - currentv = currentv.next; - } - // l1、l2某个不为空,直接链接上 - currentv.next = l1 == null ? l2 : l1; - - return vNode.next; - } - - public static void main(String[] args) { - ListNode head1 = createListNode(1, 2, 4); - ListNode head2 = createListNode(1, 3, 4, 5); - printListNode(head1); - printListNode(head2); - printListNode(new Solution1().mergeTwoLists(head1, head2)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\347\256\200\345\215\225/Solution2.java" deleted file mode 100644 index 1f044606..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\347\256\200\345\215\225/Solution2.java" +++ /dev/null @@ -1,44 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.合并两个有序链表_21_简单; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution2 { - /** - * 题目地址:https://leetcode-cn.com/problems/merge-two-sorted-lists/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路: - * ------------------------------------------------------------------- - * 时间复杂度:O(m+n) - * 空间复杂度:O(m+n),递归深度 - */ - public ListNode mergeTwoLists(ListNode l1, ListNode l2) { - if (l1 == null) { - return l2; - } - if (l2 == null) { - return l1; - } - - if (l1.val < l2.val) { - l1.next = mergeTwoLists(l1.next, l2); - return l1; - } else { - l2.next = mergeTwoLists(l1, l2.next); - return l2; - } - - } - - public static void main(String[] args) { - ListNode head1 = createListNode(1, 2, 4); - ListNode head2 = createListNode(1, 3, 4, 5); - printListNode(head1); - printListNode(head2); - printListNode(new Solution2().mergeTwoLists(head1, head2)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\233\236\346\226\207\351\223\276\350\241\250_234_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\233\236\346\226\207\351\223\276\350\241\250_234_\347\256\200\345\215\225/Solution1.java" deleted file mode 100644 index 10c81ceb..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\233\236\346\226\207\351\223\276\350\241\250_234_\347\256\200\345\215\225/Solution1.java" +++ /dev/null @@ -1,76 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.回文链表_234_简单; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/palindrome-linked-list/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路:使用快慢指针遍历到链表的中间节点,反转头节点到中间节点这部分链表, - * 从中间节点开始遍历,比较反转链表 - * ------------------------------------------------------------------- - * 时间复杂度: - * 空间复杂度: - */ - public boolean isPalindrome(ListNode head) { - if (head == null) return true; - // 找到链表中间节点 - ListNode slow = endOfFirstHalf(head); - // 反转链表 - ListNode reverseHead = reverseListNode(slow.next); - - ListNode firstHead = head; - - while (reverseHead != null && firstHead != null) { - if (reverseHead.val != firstHead.val) { - return false; - } - reverseHead = reverseHead.next; - firstHead = firstHead.next; - } - - // 包含单个节点的情况 - return true; - } - - private ListNode endOfFirstHalf(ListNode head) { - ListNode fast = head; - ListNode slow = head; - while (fast.next != null && fast.next.next != null) { - fast = fast.next.next; - slow = slow.next; - } - return slow; - } - - /** - * 反转链表 - */ - private static ListNode reverseListNode(ListNode head) { - ListNode prev = null; - ListNode current = head; - ListNode next = null; - - while (current != null) { - next = current.next; - - current.next = prev; - prev = current; - current = next; - } - return prev; - } - - public static void main(String[] args) { - //int[] arr = {1, 2, 3, 2, 1}; - //int[] arr = {1, 2, 2, 1}; - //int[] arr = {1, 2}; - //int[] arr = {1}; - int[] arr = {1, 0, 1}; - System.out.println(new Solution1().isPalindrome(createListNode(arr))); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\245\207\345\201\266\351\223\276\350\241\250_328_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\245\207\345\201\266\351\223\276\350\241\250_328_\344\270\255\347\255\211/Solution1.java" deleted file mode 100644 index dcaa7e67..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\345\245\207\345\201\266\351\223\276\350\241\250_328_\344\270\255\347\255\211/Solution1.java" +++ /dev/null @@ -1,62 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.奇偶链表_328_中等; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/odd-even-linked-list/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路:建立两个奇偶虚拟头节点,遍历输入链表,将满足条件的节点, - * 挂载到奇偶节点上,最后将奇偶链表拼接 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(1) - */ - public ListNode oddEvenList(ListNode head) { - if (head == null) { - return null; - } - - ListNode oddNode = new ListNode(-1); - ListNode evenNode = new ListNode(0); - ListNode currentOdd = oddNode; - ListNode currentEven = evenNode; - - int index = 1; - - while (head != null) { - if (index % 2 == 0) { //将index改成head.val,就是按值进行奇偶链表 - currentEven.next = head; - currentEven = currentEven.next; - /* - * 如果最后一个节点是偶数节点,将当前奇数节点的next置为null, - * 因为奇数节点的next可能指向偶数节点,但是head遍历完了,这个next无法更新, - * 会出现环形链表 - */ - if (head.next == null) { - currentOdd.next = null; - } - } else { - currentOdd.next = head; - currentOdd = currentOdd.next; - if (head.next == null) { - currentEven.next = null; - } - } - head = head.next; - index++; - } - currentOdd.next = evenNode.next; - - return oddNode.next; - } - - public static void main(String[] args) { - printListNode(new Solution1().oddEvenList(createListNode(1, 2, 3, 4, 5))); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\216\257\345\275\242\351\223\276\350\241\250_141_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\216\257\345\275\242\351\223\276\350\241\250_141_\347\256\200\345\215\225/Solution1.java" deleted file mode 100644 index 6d1e5e66..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\216\257\345\275\242\351\223\276\350\241\250_141_\347\256\200\345\215\225/Solution1.java" +++ /dev/null @@ -1,43 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.环形链表_141_简单; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createLoopListNode; - -public class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/linked-list-cycle/submissions/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路:快慢指针(龟兔赛跑) - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(1) - */ - public boolean hasCycle(ListNode head) { - if (head == null||head.next == null) { - return false; - } - ListNode fast = head; - ListNode slow = head; - - while (fast != null && fast.next != null) { - fast = fast.next.next; - slow = slow.next; - if (fast == slow) { - return true; - } - } - - return false; - } - - - public static void main(String[] args) { - int pos = 1; - int[] arr = {3, 2, 0, -4}; - ListNode loopListNode = createLoopListNode(pos, arr); - System.out.println(new Solution1().hasCycle(loopListNode)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\216\257\345\275\242\351\223\276\350\241\250_141_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\216\257\345\275\242\351\223\276\350\241\250_141_\347\256\200\345\215\225/Solution2.java" deleted file mode 100644 index 4a9c264d..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\216\257\345\275\242\351\223\276\350\241\250_141_\347\256\200\345\215\225/Solution2.java" +++ /dev/null @@ -1,43 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.环形链表_141_简单; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import java.util.HashSet; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createLoopListNode; - -public class Solution2 { - /** - * 题目地址:https://leetcode-cn.com/problems/linked-list-cycle/submissions/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路:hash表 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(n) - */ - public boolean hasCycle(ListNode head) { - if (head == null || head.next == null) { - return false; - } - HashSet set = new HashSet<>(); - while (head != null) { - if (set.contains(head)) { - return true; - } - set.add(head); - head = head.next; - } - - return false; - } - - - public static void main(String[] args) { - int pos = 1; - int[] arr = {3, 2, 0, -4}; - ListNode loopListNode = createLoopListNode(pos, arr); - System.out.println(new Solution2().hasCycle(loopListNode)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\233\270\344\272\244\351\223\276\350\241\250_160_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\233\270\344\272\244\351\223\276\350\241\250_160_\347\256\200\345\215\225/Solution1.java" deleted file mode 100644 index 281472ce..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\233\270\344\272\244\351\223\276\350\241\250_160_\347\256\200\345\215\225/Solution1.java" +++ /dev/null @@ -1,33 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.相交链表_160_简单; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -public class Solution1 { - /** - * 题目地址: - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路: - * ------------------------------------------------------------------- - * 时间复杂度: - * 空间复杂度: - */ - public ListNode getIntersectionNode(ListNode headA, ListNode headB) { - /* - 定义两个指针, 第一轮让两个到达末尾的节点指向另一个链表的头部, 最后如果相遇则为交点(在第一轮移动中恰好抹除了长度差) - 两个指针等于移动了相同的距离, 有交点就返回, 无交点就是各走了两条指针的长度 - **/ - if (headA == null || headB == null) return null; - ListNode pA = headA, pB = headB; - // 在这里第一轮体现在pA和pB第一次到达尾部会移向另一链表的表头, 而第二轮体现在如果pA或pB相交就返回交点, 不相交最后就是null==null - while (pA != pB) { - pA = pA == null ? headB : pA.next; - pB = pB == null ? headA : pB.next; - } - return pA; - } - -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\247\273\351\231\244\351\223\276\350\241\250\345\205\203\347\264\240_203_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\247\273\351\231\244\351\223\276\350\241\250\345\205\203\347\264\240_203_\347\256\200\345\215\225/Solution1.java" deleted file mode 100644 index 8c0b63a1..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\247\273\351\231\244\351\223\276\350\241\250\345\205\203\347\264\240_203_\347\256\200\345\215\225/Solution1.java" +++ /dev/null @@ -1,61 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.移除链表元素_203_简单; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/remove-linked-list-elements/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路:设置虚拟头节点 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(1) - */ - public ListNode removeElements(ListNode head, int val) { - if (head == null) - return null; - - //虚拟头节点 - ListNode vNode = new ListNode(-1); - vNode.next = head; - - // 前节点 - ListNode prev = vNode; - // 当前节点 - ListNode current = head; - - while (current != null) { - if (current.val == val) { - prev.next = current.next; - } else { - prev = prev.next; - } - current = current.next; - } - - return vNode.next; - } - - public static void main(String[] args) { - // example - int[] arr = {1, 2, 6, 3, 4, 5, 6}; - int x = 6; - - // error example - //int[] arr = {1}; - //int x = 1; - - //int[] arr = {1}; - //int x = 2; - - //int[] arr = {1, 1}; - //int x = 1; - - printListNode(new Solution1().removeElements(createListNode(arr), x)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\247\273\351\231\244\351\223\276\350\241\250\345\205\203\347\264\240_203_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\247\273\351\231\244\351\223\276\350\241\250\345\205\203\347\264\240_203_\347\256\200\345\215\225/Solution2.java" deleted file mode 100644 index 74d69f16..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\347\247\273\351\231\244\351\223\276\350\241\250\345\205\203\347\264\240_203_\347\256\200\345\215\225/Solution2.java" +++ /dev/null @@ -1,60 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.移除链表元素_203_简单; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution2 { - /** - * 题目地址:https://leetcode-cn.com/problems/remove-linked-list-elements/ - * ------------------------------------------------------------------- - * 思考:不设置虚拟头节点 - * ------------------------------------------------------------------- - * 思路: - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(1) - */ - public ListNode removeElements(ListNode head, int val) { - if (head == null) - return null; - // 前节点 - ListNode prev = null; - // 当前节点 - ListNode current = head; - while (current != null) { - if (current.val == val) { - // 找到目标值之后分为两种情况 - if (prev != null) { - prev.next = current.next; - } else { - head = current.next; - } - } else { - prev = current; - } - current = current.next; - } - - return head; - } - - public static void main(String[] args) { - // example - //int[] arr = {1, 2, 6, 3, 4, 5, 6}; - //int x = 6; - - // error example - //int[] arr = {1}; - //int x = 1; - - //int[] arr = {1}; - //int x = 2; - - int[] arr = {1, 1}; - int x = 1; - - printListNode(new Solution2().removeElements(createListNode(arr), x)); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\351\207\215\346\216\222\351\223\276\350\241\250_143_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\351\207\215\346\216\222\351\223\276\350\241\250_143_\344\270\255\347\255\211/Solution1.java" deleted file mode 100644 index 02e87897..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\351\207\215\346\216\222\351\223\276\350\241\250_143_\344\270\255\347\255\211/Solution1.java" +++ /dev/null @@ -1,99 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.重排链表_143_中等; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.createListNode; -import static cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil.printListNode; - -class Solution1 { - /** - * 题目地址:https://leetcode-cn.com/problems/reorder-list/ - * ------------------------------------------------------------------- - * 思考: - * 奇数与偶数链表情况不同,奇数链表会成环 - * ------------------------------------------------------------------- - * 思路:找到链表中间节点,然后对剩余链表进行reverse,将两个链表合并即可 - * ------------------------------------------------------------------- - * 时间复杂度:O(n) - * 空间复杂度:O(1) - */ - public void reorderList(ListNode head) { - // 过滤空值 - if (head == null) { - return; - } - // 1、找到中间节点的前一个节点(找前一个节点是为了切断两个链表的联系) - ListNode middleBeforeNode = middleBeforeNode(head); - // 2、反转以中间节点为首之后的链表 - ListNode secondHead = reverseListNode(middleBeforeNode.next); - // 切断两个链表的联系,防止链表成环 - middleBeforeNode.next = null; - // 3、合并链表 - alterNoteMergeOne(head, secondHead); - } - - public static void alterNoteMergeOne(ListNode firstHead, ListNode secondHead) { - ListNode firstNext; - ListNode secondNext; - - while (secondHead != null) { - // 1.记录两个链表的next节点 - firstNext = firstHead.next; - secondNext = secondHead.next; - // 2.将链表1的当前节点指向链表2的当前节点,链表2的当前节点指向链表1的下一个节点 - // 链表1:1->2->3 链表2:5->4 - // 合并后的链表1:1->5->2 - firstHead.next = secondHead; - secondHead.next = firstNext; - // 3.将之前保存的next更新为当前节点,继续循环 - firstHead = firstNext; - secondHead = secondNext; - // 防止奇数节点链表成环 https://leetcode-cn.com/problems/reorder-list/ - if (secondHead == null) { - firstHead.next = null; - } - } - } - - /** - * 找到链表中间的前一个节点 - */ - public static ListNode middleBeforeNode(ListNode head) { - ListNode fast = head; - ListNode slow = head; - while (fast.next != null && fast.next.next != null) { - fast = fast.next.next; - slow = slow.next; - } - return slow; - } - - /** - * 反转链表 - */ - public static ListNode reverseListNode(ListNode head) { - ListNode prev = null; - ListNode current = head; - ListNode next = null; - - while (current != null) { - next = current.next; - - current.next = prev; - prev = current; - current = next; - } - return prev; - } - - public static void main(String[] args) { - // 偶数没问题 - int[] arr = {1, 2, 3, 4, 5, 6}; - // 奇数有问题 - //int[] arr = {1, 2, 3, 4, 5}; - ListNode head = createListNode(arr); - printListNode("重排前:\t", head); - new Solution1().reorderList(head); - printListNode("重排后:\t", head); - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\351\223\276\350\241\250\347\232\204\344\270\255\351\227\264\347\273\223\347\202\271_876_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\351\223\276\350\241\250\347\232\204\344\270\255\351\227\264\347\273\223\347\202\271_876_\347\256\200\345\215\225/Solution.java" deleted file mode 100644 index 8ab7e4d0..00000000 --- "a/algorithms/leetcode/linkedlist/src/main/java/cn/lastwhisper/leetcode/linkedlist/\351\223\276\350\241\250\347\232\204\344\270\255\351\227\264\347\273\223\347\202\271_876_\347\256\200\345\215\225/Solution.java" +++ /dev/null @@ -1,25 +0,0 @@ -package cn.lastwhisper.leetcode.linkedlist.链表的中间节点_876_简单; - -import cn.lastwhisper.leetcode.common.linkedlist.ListNode; - -class Solution { - /** - * 题目地址:https://leetcode-cn.com/problems/middle-of-the-linked-list/ - * ------------------------------------------------------------------- - * 思考: - * ------------------------------------------------------------------- - * 思路: - * ------------------------------------------------------------------- - * 时间复杂度: - * 空间复杂度: - */ - public ListNode middleNode(ListNode head) { - ListNode fast = head; - ListNode slow = head; - while (fast != null && fast.next != null) { - fast = fast.next.next; - slow = slow.next; - } - return slow; - } -} \ No newline at end of file diff --git "a/algorithms/leetcode/other/src/main/java/cn/lastwhisper/leetcode/other/LRU\347\274\223\345\255\230\346\234\272\345\210\266_146_\344\270\255\347\255\211/LRUCache.java" "b/algorithms/leetcode/other/src/main/java/cn/lastwhisper/leetcode/other/LRU\347\274\223\345\255\230\346\234\272\345\210\266_146_\344\270\255\347\255\211/LRUCache.java" index ce97dcb2..fefbcba8 100644 --- "a/algorithms/leetcode/other/src/main/java/cn/lastwhisper/leetcode/other/LRU\347\274\223\345\255\230\346\234\272\345\210\266_146_\344\270\255\347\255\211/LRUCache.java" +++ "b/algorithms/leetcode/other/src/main/java/cn/lastwhisper/leetcode/other/LRU\347\274\223\345\255\230\346\234\272\345\210\266_146_\344\270\255\347\255\211/LRUCache.java" @@ -26,7 +26,17 @@ public LRUCache(int capacity) { cache = new DoubleList(); } - private class DoubleList implements Iterable { + private static class Node { + public int key, val; + public Node next, prev; + + public Node(int k, int v) { + this.key = k; + this.val = v; + } + } + + private static class DoubleList implements Iterable { private Node head, tail; // 头尾虚节点 private int size; // 链表元素数 @@ -91,16 +101,6 @@ public Iterator iterator() { } - private class Node { - public int key, val; - public Node next, prev; - - public Node(int k, int v) { - this.key = k; - this.val = v; - } - } - public int get(int key) { if (!map.containsKey(key)) return -1; diff --git a/algorithms/leetcode/readme.md b/algorithms/leetcode/readme.md index 2e38bfde..b5f83969 100644 --- a/algorithms/leetcode/readme.md +++ b/algorithms/leetcode/readme.md @@ -1,6 +1,6 @@ -## 课程练习题目录 +``# 分类 + -课程练习题的参考答案可以在我的 [**Leetcode题解代码仓**](https://github.com/liuyubobobo/Play-Leetcode) 中查询参考代码。如果在我的题解代码仓中没有你想要的问题的相应的代码,可以随时在课程问答区留言索要相应代码和简单的算法思路说明:) - array 数组 - hashtable 查找表 @@ -10,7 +10,6 @@ - recursion-backtracking 递归与回溯 - dynamic 动态规划 - greedy 贪心 - - binarysearch 二分查找 - bitoperation 位运算 - dfsbfs 深度宽度搜索 @@ -19,7 +18,7 @@ - string 字符串 - union-find 并查集 - +# 第一遍 | 章节 | 讲解例题 | 课程练习题 | | ------------------------------------------------------------ | ---------- | ----------------------- | @@ -30,7 +29,7 @@ | 3-2 改变变量定义,依然可以写出正确的算法 | [无] | [无] | | 3-3 在LeetCode上解决第一个问题 Move Zeros | ~~283~~ | [无] | | 3-4 即使简单的问题,也有很多优化的思路 | ~~283~~ | ~~27 26 80~~ | -| 3-5 三路快排partition思路的应用 Sort Color | ~~75~~剑指40 | ~~88 215~~ | +| 3-5 三路快排partition思路的应用 Sort Color | ~~75~~ of40 | ~~88 215~~ | | 3-6 对撞指针 Two Sum II - Input Array is Sorted | ~~167~~ | ~~125 344 345 11~~ | | 3-7 滑动窗口 Minimum Size Subarray Sum | ~~209 3~~ | ~~438 76~~ | | 3-8 其他 | | 1013 | @@ -91,3 +90,79 @@ | 10-2 贪心算法与动态规划的关系 Non-overlapping Intervals | 435 | [无] | | 10-3 贪心选择性质的证明 | [无] | [无] | +# 第二遍 + +2022年4月21日 + +| 章节 | 讲解例题 | 课程练习题 | +| ------------------------------------------------------------ | ---------------- | ----------------------------------- | +| **第一章 算法面试到底是什么鬼?** | [无] | [无] | +| **第二章 面试中的复杂度分析** | [无] | [无] | +| **第三章 数组中的问题最常见** | | | +| 3-1 从二分查找法看如何写出正确的程序 | [无] | [无] | +| 3-2 改变变量定义,依然可以写出正确的算法 | [无] | [无] | +| 3-3 在LeetCode上解决第一个问题 Move Zeros | ~~283~~ | [无] | +| 3-4 即使简单的问题,也有很多优化的思路 | ~~283~~ | ~~27 26 80~~ | +| 3-5 三路快排partition思路的应用 Sort Color | ~~75~~ of40 | ~~88 215~~ | +| 3-6 对撞指针 Two Sum II - Input Array is Sorted | ~~167~~ | ~~125 344 345 11~~ | +| 3-7 滑动窗口 Minimum Size Subarray Sum | ~~209 3~~ | ~~438 76~~ | +| 3-8 其他 | | 1013 | +| **第四章 查找表相关问题** | | | +| 4-1 set的使用 Intersection of Two Arrays | ~~349~~ | [无] | +| 4-2 map的使用 Intersection of Two Arrays II | ~~350~~ | [无] | +| 4-3 set和map不同底层实现的区别 | ~~349 350~~ | ~~136 242 202 290 205 451~~ | +| 4-4 使用查找表的经典问题 Two Sum | ~~1~~ | ~~15 18 16~~ | +| 4-5 灵活选择键值 4Sum II | ~~454~~ | ~~49~~ | +| 4-6 灵活选择键值 Number of Boomerangs | ~~447~~ | ~~*149~~ **719** | +| 4-7 查找表和滑动窗口 Contain Duplicate II | ~~219~~ | | +| 4-8 二分搜索树底层实现的顺序性 Contain Duplicate III | ~~*220~~ | [无] | +| **第五章 在链表中穿针引线** | | | +| 5-1 链表,在节点间穿针引线 Reverse Linked List | ~~206~~ | ~~*92~~ | +| 5-2 测试你的链表程序 | ~~206~~ | ~~83~~ ~~86~~ ~~328~~ ~~2 445~~ | +| 5-3 设立链表的虚拟头节点 Remove Linked List Elements | ~~203~~ | ~~82~~ ~~*21(递归)~~ | +| 5-4 复杂的穿针引线 Swap Nodes in Pairs | ~~*24~~ | **25 147 148** | +| 5-5 不仅仅是穿针引线 Delete Node in a Linked List | ~~237~~ | [无] | +| 5-6 链表与双指针 Remove Nth Node Form End of List | ~~19~~ | **61** ~~143 234~~ | +| 额外刷题 | **160** | ~~876~~ | +| **第六章 栈、队列、优先队列** | | | +| 6-1 栈的基础应用 Valid Parentheses | ~~20~~ | ~~150 71~~ | +| 6-2 栈和递归的紧密关系 Binary Tree Preorder, Inorder and Postorder Traversal | ~~144 94 145~~ | [无] | +| 6-3 运用栈模拟递归 | ~~*144 94 145~~ | **341** | +| 6-4 队列的典型应用 Binary Tree Level Order Traversal | ~~102~~ | ~~107 103 199~~ **346** | +| 6-5 BFS和图的最短路径 Perfect Squares | ~~*279~~ | **127 126** **286** | +| 6-6 优先队列 | [无] | [无] | +| 6-7 优先队列相关的算法问题 Top K Frequent Elements | ~~347~~ | ~~23~~ | +| **第七章 二叉树和递归** | | | +| 7-1 二叉树天然的递归结构 | ~~*104(重点看)~~ | ~~*111(重点看)~~ | +| 7-2 一个简单的二叉树问题引发的血案 Invert Binary Tree | ~~*226~~ | ~~100 101 222 *110~~ | +| 7-3 注意递归的终止条件 Path Sum | ~~112~~ | ~~404~~ | +| 7-4 定义递归问题 Binary Tree Path | ~~257~~ | ~~113 129 222~~ | +| 7-5 稍复杂的递归逻辑 Path Sum III | ~~437~~ | [无] | +| 7-6 二分搜索树中的问题 Lowest Common Ancestor of a Binary Search Tree | ~~783 235~~ | ~~*98~~ **450 108 230 236 530** | +| **第八章 递归和回溯法** | | | +| 8-1 树形问题 Letter Combinations of a Phone Number | ~~*17~~ | [无] | +| 8-2 什么是回溯 | ~~17~~ | ~~*93~~ 131 | +| 8-3 排列问题 Permutations | ~~*46~~ | ~~*47~~ | +| 8-4 组合问题 Combinations | ~~*77~~ | [无] | +| 8-5 回溯法解决组合问题的优化 | ~~*77~~ | ~~39~~ ~~40~~ 216 **78 90** ~~401~~ | +| 8-6 二维平面上的回溯法 Word Search | ~~79~~ | [无] | +| 8-7 floodfill算法,一类经典问题 Number of Islands | ~~200~~ | 130 417 | +| 8-8 回溯法是经典人工智能的基础 N Queens | ~~51~~ | ~~52~~ 37 | +| **第九章 动态规划基础** | | | +| 9-1 什么是动态规划 | [无] | [无] | +| 9-2 第一个动态规划问题 Climbing Stairs | ~~70~~ | ~~120~~ ~~64~~ | +| 9-3 发现重叠子问题 Integer Break | ~~*343~~ | ~~*279 *91 62 *63~~ | +| 9-4 状态的定义和状态转移 House Robber | ~~198~~ | 213 337 309 | +| 9-5 0-1背包问题 | [无] | [无] | +| 9-6 0-1背包问题的优化和变种 | [无] | [无] | +| 9-7 面试中的0-1背包问题 Partition Equal Subset Sum | ~~*416~~ | ~~*322~~ 377 474 139 494 | +| 9-8 LIS问题 Longest Increasing Subsequence | ~~300~~ | 376 | +| 9-9 LCS,最短路,求动态规划的具体解以及更多 | [无] | [无] | +| 其他 | ~~53~~ | [无] | +| **第十章 贪心算法** | | | +| 10-1 贪心基础 Assign Cookies | ~~455~~ | ~~392~~ | +| 10-2 贪心算法与动态规划的关系 Non-overlapping Intervals | 435 | [无] | +| 10-3 贪心选择性质的证明 | [无] | [无] | + + + diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/N\347\232\207\345\220\216_51_\345\233\260\351\232\276/Solution1.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/N\347\232\207\345\220\216_51_\345\233\260\351\232\276/Solution1.java" index 33f49459..a5db15e7 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/N\347\232\207\345\220\216_51_\345\233\260\351\232\276/Solution1.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/N\347\232\207\345\220\216_51_\345\233\260\351\232\276/Solution1.java" @@ -4,7 +4,7 @@ import java.util.Arrays; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printStringLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printStringLists; class Solution1 { /** diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/N\347\232\207\345\220\216_51_\345\233\260\351\232\276/Solution2.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/N\347\232\207\345\220\216_51_\345\233\260\351\232\276/Solution2.java" index 776c1040..82a0bf06 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/N\347\232\207\345\220\216_51_\345\233\260\351\232\276/Solution2.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/N\347\232\207\345\220\216_51_\345\233\260\351\232\276/Solution2.java" @@ -4,7 +4,7 @@ import java.util.LinkedList; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printStringLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printStringLists; class Solution2 { /** diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\344\272\214\350\277\233\345\210\266\346\211\213\350\241\250_401_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\344\272\214\350\277\233\345\210\266\346\211\213\350\241\250_401_\347\256\200\345\215\225/Solution1.java" index 5a1d55a3..8b6a396f 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\344\272\214\350\277\233\345\210\266\346\211\213\350\241\250_401_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\344\272\214\350\277\233\345\210\266\346\211\213\350\241\250_401_\347\256\200\345\215\225/Solution1.java" @@ -3,7 +3,7 @@ import java.util.ArrayList; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printList; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printList; class Solution1 { /** diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\344\272\214\350\277\233\345\210\266\346\211\213\350\241\250_401_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\344\272\214\350\277\233\345\210\266\346\211\213\350\241\250_401_\347\256\200\345\215\225/Solution2.java" index a239968f..17ef599c 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\344\272\214\350\277\233\345\210\266\346\211\213\350\241\250_401_\347\256\200\345\215\225/Solution2.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\344\272\214\350\277\233\345\210\266\346\211\213\350\241\250_401_\347\256\200\345\215\225/Solution2.java" @@ -3,7 +3,7 @@ import java.util.ArrayList; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printList; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printList; class Solution2 { /** diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\344\272\214\350\277\233\345\210\266\346\211\213\350\241\250_401_\347\256\200\345\215\225/Solution3.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\344\272\214\350\277\233\345\210\266\346\211\213\350\241\250_401_\347\256\200\345\215\225/Solution3.java" index 7ef90c9e..fb65748a 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\344\272\214\350\277\233\345\210\266\346\211\213\350\241\250_401_\347\256\200\345\215\225/Solution3.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\344\272\214\350\277\233\345\210\266\346\211\213\350\241\250_401_\347\256\200\345\215\225/Solution3.java" @@ -3,7 +3,7 @@ import java.util.ArrayList; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printList; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printList; class Solution3 { /** diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution1.java" index a5cc5722..ebd5f4b3 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution1.java" @@ -3,8 +3,8 @@ import java.util.ArrayList; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.collection2String; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.collection2String; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; class Solution1 { static Integer count = 0; diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution2.java" index bd9d0644..34fd2e06 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution2.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution2.java" @@ -3,7 +3,7 @@ import java.util.ArrayList; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; class Solution2 { /** diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution3.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution3.java" index 2c120ee2..74642a5a 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution3.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution3.java" @@ -5,7 +5,7 @@ import java.util.Deque; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; public class Solution3 { diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_II_47_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_II_47_\344\270\255\347\255\211/Solution1.java" index 0f3ca51e..303e3f1b 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_II_47_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_II_47_\344\270\255\347\255\211/Solution1.java" @@ -4,7 +4,7 @@ import java.util.Arrays; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; class Solution1 { /** diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_II_47_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_II_47_\344\270\255\347\255\211/Solution2.java" index ae0dcbbd..d5da862e 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_II_47_\344\270\255\347\255\211/Solution2.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\205\250\346\216\222\345\210\227_II_47_\344\270\255\347\255\211/Solution2.java" @@ -4,7 +4,7 @@ import java.util.Arrays; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; class Solution2 { /** diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\244\215\345\216\237IP\345\234\260\345\235\200_93_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\244\215\345\216\237IP\345\234\260\345\235\200_93_\344\270\255\347\255\211/Solution1.java" index e7be4641..2b7cf53d 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\244\215\345\216\237IP\345\234\260\345\235\200_93_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\345\244\215\345\216\237IP\345\234\260\345\235\200_93_\344\270\255\347\255\211/Solution1.java" @@ -3,7 +3,7 @@ import java.util.ArrayList; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printList; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printList; class Solution1 { /** diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\345\255\227\346\257\215\347\273\204\345\220\210_17_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\345\255\227\346\257\215\347\273\204\345\220\210_17_\344\270\255\347\255\211/Solution1.java" index 30322ba5..42e63980 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\345\255\227\346\257\215\347\273\204\345\220\210_17_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\345\255\227\346\257\215\347\273\204\345\220\210_17_\344\270\255\347\255\211/Solution1.java" @@ -3,8 +3,7 @@ import java.util.ArrayList; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printList; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printList; class Solution1 { private String[] letterMap = { diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210_77_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210_77_\344\270\255\347\255\211/Solution1.java" index 4e0ecafa..ce63d033 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210_77_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210_77_\344\270\255\347\255\211/Solution1.java" @@ -3,8 +3,7 @@ import java.util.ArrayList; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.collection2String; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; class Solution1 { static int count = 0; diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210_77_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210_77_\344\270\255\347\255\211/Solution2.java" index 7de6a296..36ae5123 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210_77_\344\270\255\347\255\211/Solution2.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210_77_\344\270\255\347\255\211/Solution2.java" @@ -3,7 +3,7 @@ import java.util.ArrayList; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; class Solution2 { /** diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210\346\200\273\345\222\214_39_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210\346\200\273\345\222\214_39_\344\270\255\347\255\211/Solution1.java" index 82a3016b..c45dcea4 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210\346\200\273\345\222\214_39_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210\346\200\273\345\222\214_39_\344\270\255\347\255\211/Solution1.java" @@ -4,7 +4,7 @@ import java.util.Arrays; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; class Solution1 { /** diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210\346\200\273\345\222\214_39_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210\346\200\273\345\222\214_39_\344\270\255\347\255\211/Solution2.java" index 43b8a8a6..39e16a3d 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210\346\200\273\345\222\214_39_\344\270\255\347\255\211/Solution2.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210\346\200\273\345\222\214_39_\344\270\255\347\255\211/Solution2.java" @@ -3,8 +3,7 @@ import java.util.ArrayList; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.collection2String; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; class Solution2 { static int count = 0; diff --git "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210\346\200\273\345\222\214_II_40_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210\346\200\273\345\222\214_II_40_\344\270\255\347\255\211/Solution1.java" index 139548fd..1ee372c5 100644 --- "a/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210\346\200\273\345\222\214_II_40_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/leetcode/recursion-backtracking/src/main/java/cn/lastwhisper/leetcode/recurionbacktracking/\347\273\204\345\220\210\346\200\273\345\222\214_II_40_\344\270\255\347\255\211/Solution1.java" @@ -4,7 +4,7 @@ import java.util.Arrays; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; class Solution1 { /** diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206_94_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206_94_\344\270\255\347\255\211/Solution2.java" index cee09fc6..68042732 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206_94_\344\270\255\347\255\211/Solution2.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206_94_\344\270\255\347\255\211/Solution2.java" @@ -1,7 +1,7 @@ package cn.lastwhisper.leetcode.stackqueue.二叉树的中序遍历_94_中等; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; import java.util.ArrayList; import java.util.LinkedList; @@ -36,7 +36,7 @@ public List inorderTraversal(TreeNode root) { } public static void main(String[] args) { - TreeNode tree = TreeUtils.createTree(); + TreeNode tree = TreeUtil.createTree(); new Solution2().inorderTraversal(tree).forEach(node -> { System.out.print(node + ","); }); diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206_94_\344\270\255\347\255\211/Solution3.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206_94_\344\270\255\347\255\211/Solution3.java" index e73814fd..54f3b9d9 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206_94_\344\270\255\347\255\211/Solution3.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206_94_\344\270\255\347\255\211/Solution3.java" @@ -6,9 +6,8 @@ import java.util.LinkedList; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printList; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution3 { /** diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206_94_\344\270\255\347\255\211/SolutionCommand.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206_94_\344\270\255\347\255\211/SolutionCommand.java" index 4514de15..6af7494e 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206_94_\344\270\255\347\255\211/SolutionCommand.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\344\270\255\345\272\217\351\201\215\345\216\206_94_\344\270\255\347\255\211/SolutionCommand.java" @@ -1,7 +1,7 @@ package cn.lastwhisper.leetcode.stackqueue.二叉树的中序遍历_94_中等; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; import java.util.ArrayList; import java.util.List; @@ -56,7 +56,7 @@ public List inorderTraversal(TreeNode root) { } public static void main(String[] args) { - TreeNode tree = TreeUtils.createTree(); + TreeNode tree = TreeUtil.createTree(); new SolutionCommand().inorderTraversal(tree).forEach(node -> { System.out.print(node + ","); diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/Solution1.java" index aafdbc40..0c5d6130 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/Solution1.java" @@ -1,7 +1,7 @@ package cn.lastwhisper.leetcode.stackqueue.二叉树的前序遍历_144_中等; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; import java.util.ArrayList; import java.util.List; @@ -26,7 +26,7 @@ public List preorderTraversal(TreeNode root) { } public static void main(String[] args) { - TreeNode root = TreeUtils.createTree(); + TreeNode root = TreeUtil.createTree(); new Solution1().preorderTraversal(root).forEach(node -> { System.out.print(node + ","); }); diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/Solution2.java" index 4f3a9622..a7aaae17 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/Solution2.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/Solution2.java" @@ -1,12 +1,11 @@ package cn.lastwhisper.leetcode.stackqueue.二叉树的前序遍历_144_中等; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; -import java.util.Stack; class Solution2 { /** @@ -37,7 +36,7 @@ public List preorderTraversal(TreeNode root) { } public static void main(String[] args) { - TreeNode tree = TreeUtils.createTree(); + TreeNode tree = TreeUtil.createTree(); new Solution2().preorderTraversal(tree).forEach(node -> { System.out.print(node + ","); diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/Solution3.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/Solution3.java" index 4f4c0597..a45a5bf4 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/Solution3.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/Solution3.java" @@ -1,7 +1,7 @@ package cn.lastwhisper.leetcode.stackqueue.二叉树的前序遍历_144_中等; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; import java.util.ArrayList; import java.util.List; @@ -36,7 +36,7 @@ public List preorderTraversal(TreeNode root) { } public static void main(String[] args) { - TreeNode tree = TreeUtils.createTree(); + TreeNode tree = TreeUtil.createTree(); new Solution3().preorderTraversal(tree).forEach(node -> { System.out.print(node + ","); diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/Solution4.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/Solution4.java" index 6981a8da..e544bc16 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/Solution4.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/Solution4.java" @@ -1,7 +1,7 @@ package cn.lastwhisper.leetcode.stackqueue.二叉树的前序遍历_144_中等; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; import java.util.ArrayList; import java.util.List; @@ -36,7 +36,7 @@ public List preorderTraversal(TreeNode root) { } public static void main(String[] args) { - TreeNode tree = TreeUtils.createTree(); + TreeNode tree = TreeUtil.createTree(); new Solution4().preorderTraversal(tree).forEach(node -> { System.out.print(node + ","); diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/SolutionCommand.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/SolutionCommand.java" index 6e8b828a..94ae45d9 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/SolutionCommand.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\344\270\255\347\255\211/SolutionCommand.java" @@ -1,7 +1,7 @@ package cn.lastwhisper.leetcode.stackqueue.二叉树的前序遍历_144_中等; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; import java.util.LinkedList; import java.util.List; @@ -61,7 +61,7 @@ public List preorderTraversal(TreeNode root) { } public static void main(String[] args) { - TreeNode tree = TreeUtils.createTree(); + TreeNode tree = TreeUtil.createTree(); new SolutionCommand().preorderTraversal(tree).forEach(node -> { System.out.print(node + ","); diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\217\263\350\247\206\345\233\276_199_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\217\263\350\247\206\345\233\276_199_\344\270\255\347\255\211/Solution1.java" index 45715044..df9b3776 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\217\263\350\247\206\345\233\276_199_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\217\263\350\247\206\345\233\276_199_\344\270\255\347\255\211/Solution1.java" @@ -7,7 +7,7 @@ import java.util.List; import java.util.Queue; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution1 { /** diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206_145_\345\233\260\351\232\276/Solution2.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206_145_\345\233\260\351\232\276/Solution2.java" index 2407a28b..bbdb8a73 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206_145_\345\233\260\351\232\276/Solution2.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206_145_\345\233\260\351\232\276/Solution2.java" @@ -5,8 +5,8 @@ import java.util.LinkedList; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printList; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution2 { /** diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206_145_\345\233\260\351\232\276/Solution3.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206_145_\345\233\260\351\232\276/Solution3.java" index 5798e5f6..6b82a187 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206_145_\345\233\260\351\232\276/Solution3.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206_145_\345\233\260\351\232\276/Solution3.java" @@ -4,9 +4,8 @@ import java.util.*; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printList; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution3 { /** diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206_145_\345\233\260\351\232\276/Solution4.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206_145_\345\233\260\351\232\276/Solution4.java" index 6d6644dd..6127892a 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206_145_\345\233\260\351\232\276/Solution4.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206_145_\345\233\260\351\232\276/Solution4.java" @@ -6,8 +6,8 @@ import java.util.List; import java.util.Stack; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printList; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution4 { /** diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206_145_\345\233\260\351\232\276/SolutionCommand.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206_145_\345\233\260\351\232\276/SolutionCommand.java" index 621587b9..eadbc3d3 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206_145_\345\233\260\351\232\276/SolutionCommand.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\220\216\345\272\217\351\201\215\345\216\206_145_\345\233\260\351\232\276/SolutionCommand.java" @@ -1,15 +1,13 @@ package cn.lastwhisper.leetcode.stackqueue.二叉树的后序遍历_145_困难; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; import java.util.ArrayList; import java.util.List; import java.util.Stack; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printList; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printList; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class SolutionCommand { static class Command { diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_102_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_102_\344\270\255\347\255\211/Solution1.java" index 754d00d2..68b45503 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_102_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_102_\344\270\255\347\255\211/Solution1.java" @@ -7,8 +7,8 @@ import java.util.List; import java.util.Queue; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution1 { /** diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_102_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_102_\344\270\255\347\255\211/Solution2.java" index 716f90c0..4e50312b 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_102_\344\270\255\347\255\211/Solution2.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_102_\344\270\255\347\255\211/Solution2.java" @@ -7,8 +7,8 @@ import java.util.List; import java.util.Queue; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; class Solution2 { diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_102_\344\270\255\347\255\211/Solution3.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_102_\344\270\255\347\255\211/Solution3.java" index aa3bf0e9..7dfb382b 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_102_\344\270\255\347\255\211/Solution3.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_102_\344\270\255\347\255\211/Solution3.java" @@ -5,8 +5,8 @@ import java.util.ArrayList; import java.util.List; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.*; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.*; class Solution3 { diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_II_107_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_II_107_\347\256\200\345\215\225/Solution1.java" index c216e691..17ba88e5 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_II_107_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_II_107_\347\256\200\345\215\225/Solution1.java" @@ -4,8 +4,8 @@ import java.util.*; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; class Solution1 { /** diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_II_107_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_II_107_\347\256\200\345\215\225/Solution2.java" index 8a0302fe..4c0e7eee 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_II_107_\347\256\200\345\215\225/Solution2.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206_II_107_\347\256\200\345\215\225/Solution2.java" @@ -4,8 +4,8 @@ import java.util.*; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; class Solution2 { /** diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\351\224\257\351\275\277\345\275\242\345\261\202\346\254\241\351\201\215\345\216\206_103_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\351\224\257\351\275\277\345\275\242\345\261\202\346\254\241\351\201\215\345\216\206_103_\344\270\255\347\255\211/Solution1.java" index fc99bd7e..93f5da81 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\351\224\257\351\275\277\345\275\242\345\261\202\346\254\241\351\201\215\345\216\206_103_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\351\224\257\351\275\277\345\275\242\345\261\202\346\254\241\351\201\215\345\216\206_103_\344\270\255\347\255\211/Solution1.java" @@ -7,8 +7,8 @@ import java.util.List; import java.util.Queue; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; class Solution1 { /** diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\351\224\257\351\275\277\345\275\242\345\261\202\346\254\241\351\201\215\345\216\206_103_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\351\224\257\351\275\277\345\275\242\345\261\202\346\254\241\351\201\215\345\216\206_103_\344\270\255\347\255\211/Solution2.java" index 393f10fe..734e8133 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\351\224\257\351\275\277\345\275\242\345\261\202\346\254\241\351\201\215\345\216\206_103_\344\270\255\347\255\211/Solution2.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\344\272\214\345\217\211\346\240\221\347\232\204\351\224\257\351\275\277\345\275\242\345\261\202\346\254\241\351\201\215\345\216\206_103_\344\270\255\347\255\211/Solution2.java" @@ -5,8 +5,8 @@ import java.util.ArrayList; import java.util.List; -import static cn.lastwhisper.leetcode.common.tree.TreeUtils.createTree; -import static cn.lastwhisper.leetcode.common.print.PrintUtils.printLists; +import static cn.lastwhisper.leetcode.common.tree.TreeUtil.createTree; +import static cn.lastwhisper.leetcode.common.print.PrintUtil.printLists; class Solution2 { /** diff --git "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\346\234\211\346\225\210\347\232\204\346\213\254\345\217\267_20_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\346\234\211\346\225\210\347\232\204\346\213\254\345\217\267_20_\347\256\200\345\215\225/Solution1.java" index 93798275..5b927530 100644 --- "a/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\346\234\211\346\225\210\347\232\204\346\213\254\345\217\267_20_\347\256\200\345\215\225/Solution1.java" +++ "b/algorithms/leetcode/stackqueue/src/main/java/cn/lastwhisper/leetcode/stackqueue/\346\234\211\346\225\210\347\232\204\346\213\254\345\217\267_20_\347\256\200\345\215\225/Solution1.java" @@ -1,6 +1,6 @@ package cn.lastwhisper.leetcode.stackqueue.有效的括号_20_简单; -import java.util.Stack; +import java.util.LinkedList; class Solution1 { /** @@ -19,21 +19,18 @@ class Solution1 { * 空间复杂度:O(1) */ public boolean isValid(String s) { - //if ("".equals(s)) { - // return true; - //} if (s.length() % 2 != 0) { return false; } - Stack stack = new Stack<>(); + LinkedList stack = new LinkedList<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == '(' || c == '{' || c == '[') { stack.push(c); } else { // "})" - if (stack.empty()) { + if (stack.isEmpty()) { return false; } if (!match(stack.pop(), c)) { @@ -41,8 +38,8 @@ public boolean isValid(String s) { } } } - // 两种情况""、"((" - return stack.empty(); + // 两种情况""=true、"(("=false + return stack.isEmpty(); } /** diff --git "a/algorithms/leetcode/string/src/main/java/cn/lastwhisper/leetcode/string/\347\277\273\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215_151_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode/string/src/main/java/cn/lastwhisper/leetcode/string/\347\277\273\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215_151_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..2f0af73c --- /dev/null +++ "b/algorithms/leetcode/string/src/main/java/cn/lastwhisper/leetcode/string/\347\277\273\350\275\254\345\255\227\347\254\246\344\270\262\351\207\214\347\232\204\345\215\225\350\257\215_151_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,37 @@ +package cn.lastwhisper.leetcode.string.翻转字符串里的单词_151_中等; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/reverse-words-in-a-string/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public String reverseWords(String s) { + s = s.trim(); + String[] arr = s.split(" "); + for (int i = 0; i < arr.length / 2; i++) { + String temp = arr[i]; + arr[i] = arr[arr.length - i - 1]; + arr[arr.length - i - 1] = temp; + } + StringBuilder sb = new StringBuilder(); + for (String s1 : arr) { + if(!"".equals(s1)){ + sb.append(s1); + sb.append(" "); + } + } + return sb.toString().trim(); + } + + public static void main(String[] args) { + Assert.assertEquals("example good a", new Solution1().reverseWords("a good example")); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/string/src/main/java/cn/lastwhisper/leetcode/string/\351\235\242\350\257\225\351\242\23001_06_\345\255\227\347\254\246\344\270\262\345\216\213\347\274\251_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode/string/src/main/java/cn/lastwhisper/leetcode/string/\351\235\242\350\257\225\351\242\23001_06_\345\255\227\347\254\246\344\270\262\345\216\213\347\274\251_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..40d49463 --- /dev/null +++ "b/algorithms/leetcode/string/src/main/java/cn/lastwhisper/leetcode/string/\351\235\242\350\257\225\351\242\23001_06_\345\255\227\347\254\246\344\270\262\345\216\213\347\274\251_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,39 @@ +package cn.lastwhisper.leetcode.string.面试题01_06_字符串压缩_简单; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/compress-string-lcci/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ + public String compressString(String S) { + StringBuilder compress = new StringBuilder(); + int count = 1; + char prev = ' '; + for (char c : S.toCharArray()) { + if (prev == c) {//重复 + count++; + } else if (prev != ' ') {//遇到新的 + compress.append(count); + count = 1; + } + if (count == 1) {//第一次出现 + compress.append(c); + } + prev = c; + } + compress.append(count); + return compress.length() >= S.length() ? S : compress.toString(); + } + + public static void main(String[] args) { + Assert.assertEquals("a2b1c5a3", new Solution1().compressString("aabcccccaaa")); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/week/src/main/java/cn/lastwhisper/leetcode/week/one183/\345\260\206\344\272\214\350\277\233\345\210\266\350\241\250\347\244\272\345\207\217\345\210\2601\347\232\204\346\255\245\351\252\244\346\225\260_5377_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode/week/src/main/java/cn/lastwhisper/leetcode/week/one183/\345\260\206\344\272\214\350\277\233\345\210\266\350\241\250\347\244\272\345\207\217\345\210\2601\347\232\204\346\255\245\351\252\244\346\225\260_5377_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..c71e8c21 --- /dev/null +++ "b/algorithms/leetcode/week/src/main/java/cn/lastwhisper/leetcode/week/one183/\345\260\206\344\272\214\350\277\233\345\210\266\350\241\250\347\244\272\345\207\217\345\210\2601\347\232\204\346\255\245\351\252\244\346\225\260_5377_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,47 @@ +package cn.lastwhisper.leetcode.week.one183.将二进制表示减到1的步骤数_5377_中等; + +import org.junit.Assert; + +import java.math.BigInteger; +import java.util.LinkedList; + +class Solution { + + public int numSteps(String s) { + BigInteger num = convert(s); + System.out.println(num.toString()); + BigInteger two = BigInteger.valueOf(2); + int count = 0; + while (num.compareTo(BigInteger.ONE) != 0) { + if (num.remainder(two).compareTo(BigInteger.ZERO) == 0) { + num = num.divide(two); + } else { + num = num.add(BigInteger.ONE); + } + count++; + } + return count; + } + + private BigInteger convert(String s) { + LinkedList stack = new LinkedList<>(); + for (int i = 0; i < s.length(); i++) { + stack.push(s.charAt(i) - '0'); + } + BigInteger sum = BigInteger.ZERO; + int i = 0; + BigInteger two = BigInteger.valueOf(2); + while (!stack.isEmpty()) { + BigInteger temp = BigInteger.valueOf(stack.pop()); + sum = sum.add(temp.multiply(two.pow(i++))); + } + return sum; + } + + public static void main(String[] args) { + //Assert.assertEquals(6, new Solution().numSteps("1101")); + //Assert.assertEquals(20, new Solution().numSteps("111111001110101")); + //Assert.assertEquals(85, new Solution().numSteps("1111011110000011100000110001011011110010111001010111110001")); + Assert.assertEquals(85, new Solution().numSteps("1111110011101010110011100100101110010100101110111010111110110010")); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode/week/src/main/java/cn/lastwhisper/leetcode/week/one183/\351\235\236\351\200\222\345\242\236\351\241\272\345\272\217\347\232\204\346\234\200\345\260\217\345\255\220\345\272\217\345\210\227_5376_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode/week/src/main/java/cn/lastwhisper/leetcode/week/one183/\351\235\236\351\200\222\345\242\236\351\241\272\345\272\217\347\232\204\346\234\200\345\260\217\345\255\220\345\272\217\345\210\227_5376_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..db685d75 --- /dev/null +++ "b/algorithms/leetcode/week/src/main/java/cn/lastwhisper/leetcode/week/one183/\351\235\236\351\200\222\345\242\236\351\241\272\345\272\217\347\232\204\346\234\200\345\260\217\345\255\220\345\272\217\345\210\227_5376_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,36 @@ +package cn.lastwhisper.leetcode.week.one183.非递增顺序的最小子序列_5376_简单; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +class Solution { + + public List minSubsequence(int[] nums) { + int sum = 0; + for (int num : nums) { + sum += num; + } + Integer[] arr = new Integer[nums.length]; + for (int i = 0; i < nums.length; i++) { + arr[i] = nums[i]; + } + Arrays.sort(arr, (o1, o2) -> o2 - o1); + + List ans = new ArrayList<>(); + int nowSum = 0; + for (Integer num : arr) { + nowSum += num; + ans.add(num); + if (nowSum > (sum - nowSum)) { + break; + } + } + return ans; + } + + public static void main(String[] args) { + new Solution().minSubsequence(new int[]{4, 3, 10, 9, 8}).forEach(System.out::print); + } + +} \ No newline at end of file diff --git a/algorithms/leetcode2/README.md b/algorithms/leetcode2/README.md new file mode 100644 index 00000000..43591dac --- /dev/null +++ b/algorithms/leetcode2/README.md @@ -0,0 +1,20 @@ +2刷力扣 + +```java +/** + * 思考: + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度:O(n^2) + * 空间复杂度:O(1) + */ + + +``` + +- greedy 贪心 +- point 双指针 + + + diff --git a/algorithms/leetcode2/backtracking/pom.xml b/algorithms/leetcode2/backtracking/pom.xml new file mode 100644 index 00000000..d5561633 --- /dev/null +++ b/algorithms/leetcode2/backtracking/pom.xml @@ -0,0 +1,19 @@ + + + + leetcode2 + cn.cucnhang + 1.0-SNAPSHOT + + 4.0.0 + + backtracking + + + 8 + 8 + + + \ No newline at end of file diff --git "a/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/N\347\232\207\345\220\216_51_\345\233\260\351\232\276/Solution.java" "b/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/N\347\232\207\345\220\216_51_\345\233\260\351\232\276/Solution.java" new file mode 100644 index 00000000..16dda701 --- /dev/null +++ "b/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/N\347\232\207\345\220\216_51_\345\233\260\351\232\276/Solution.java" @@ -0,0 +1,86 @@ +package cn.cunchang.N皇后_51_困难; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @author cunchang + * @date 2022/7/1 5:33 PM + */ +class Solution { + List> result = new ArrayList<>(); + public List> solveNQueens(int n) { + char[][] chessboard = new char[n][n]; + + for (char[] chess : chessboard) { + Arrays.fill(chess,'.'); + } + + solveNQueens0(chessboard, 0); + return result; + } + + private void solveNQueens0(char[][] chessboard, int row) { + if (row == chessboard.length) { + List subResult = getSubResult(chessboard); + result.add(subResult); + return; + } + int col = chessboard[row].length; + for (int i = 0; i < col; i++) { + // 排除不合规 + if (!valid(chessboard, row, i)) { + continue; + } + // 放棋子 + chessboard[row][i] = 'Q'; + // 尝试下一列 + solveNQueens0(chessboard, row + 1); + // 撤销操作 + chessboard[row][i] = '.'; + } + } + + private List getSubResult(char[][] chessboard) { + List subResult = new ArrayList<>(chessboard.length); + for (int i = 0; i < chessboard.length; i++) { + StringBuilder rowStr = new StringBuilder(); + for (int j = 0; j < chessboard.length; j++) { + rowStr.append(chessboard[i][j]); + } + subResult.add(rowStr.toString()); + } + return subResult; + } + + private boolean valid(char[][] chessboard, int row, int col) { + + // row之前是否同列 + for (int i = 0; i <= row; i++) { + if (chessboard[i][col] == 'Q') { + return false; + } + } + + // 左对角线;行列坐标减一 + for (int i = row, j = col; i >= 0 && j >= 0; i--, j--) { + if (chessboard[i][j] == 'Q') { + return false; + } + } + + // 右对角线;行坐标减一,列坐标加一 + for (int i = row, j = col; i >= 0 && j < chessboard[0].length; i--, j++) { + if (chessboard[i][j] == 'Q') { + return false; + } + } + + return true; + } + + public static void main(String[] args) { + System.out.println(new Solution().solveNQueens(10)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\205\250\346\216\222\345\210\227II_47_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\205\250\346\216\222\345\210\227II_47_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..5db95256 --- /dev/null +++ "b/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\205\250\346\216\222\345\210\227II_47_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,57 @@ +package cn.cunchang.全排列II_47_中等; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +/** + * @author cunchang + * @date 2022/7/2 4:02 PM + */ +class Solution { + List> result = new ArrayList<>(); + + public List> permuteUnique(int[] nums) { + // 记录「路径」 + LinkedList subResult = new LinkedList<>(); + // 「路径」中的元素会被标记为 true,避免重复使用 + boolean[] visited = new boolean[nums.length]; + // 保证有序 + Arrays.sort(nums); + permute0(nums, subResult, visited); + return result; + } + + private void permute0(int[] nums, LinkedList subResult, boolean[] visited) { + // 回溯结束,记录结果 + if (nums.length == subResult.size()) { + result.add(new ArrayList<>(subResult)); + } + // 记录上一次选择的值 + int prev = Integer.MIN_VALUE; + // 遍历选择列表 + for (int i = 0; i < nums.length; i++) { + if (visited[i]) { + continue; + } + // 选择值相同,则不选 + if (prev == nums[i]) { + continue; + } + prev = nums[i]; + // 选择值 + subResult.add(nums[i]); + visited[i] = true; + permute0(nums, subResult, visited); + // 撤销选择 + subResult.removeLast(); + visited[i] = false; + } + } + + public static void main(String[] args) { + System.out.println(new Solution().permuteUnique(new int[]{1, 2, 1})); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..171a593e --- /dev/null +++ "b/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,43 @@ +package cn.cunchang.全排列_46_中等; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +class Solution { + List> result = new ArrayList<>(); + + public List> permute(int[] num) { + // 记录「路径」 + LinkedList subResult = new LinkedList<>(); + // 「路径」中的元素会被标记为 true,避免重复使用 + boolean[] visited = new boolean[num.length]; + permute0(num, subResult, visited); + return result; + } + + private void permute0(int[] num, LinkedList subResult, boolean[] visited) { + // 回溯结束,记录结果 + if (num.length == subResult.size()) { + result.add(new ArrayList<>(subResult)); + } + // 遍历选择列表 + for (int i = 0; i < num.length; i++) { + if (visited[i]) { + continue; + } + // 选择值 + subResult.add(num[i]); + visited[i] = true; + permute0(num, subResult, visited); + // 撤销选择 + subResult.removeLast(); + visited[i] = false; + } + } + + public static void main(String[] args) { + System.out.println(new Solution().permute(new int[]{1, 2, 3})); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution2.java" new file mode 100644 index 00000000..fc69920f --- /dev/null +++ "b/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\205\250\346\216\222\345\210\227_46_\344\270\255\347\255\211/Solution2.java" @@ -0,0 +1,49 @@ +package cn.cunchang.全排列_46_中等; + +import java.util.ArrayList; +import java.util.List; + +class Solution2 { + List> result = new ArrayList<>(); + + public List> permute(int[] num) { + // 记录「路径」 + List subResult = new ArrayList<>(); + // 「路径」中的元素会被标记为 true,避免重复使用 + boolean[] visited = new boolean[num.length]; + permute0(num, subResult, visited, 0); + return result; + } + + /** + * + * @param num 数字序列 + * @param subResult 当前路径排列 + * @param visited 保存访问过的下标 + * @param idx idx用于撤销当前操作 + */ + private void permute0(int[] num, List subResult, boolean[] visited, int idx) { + // 回溯结束,记录结果 + if (num.length == subResult.size()) { + result.add(new ArrayList<>(subResult)); + } + // 遍历选择列表 + for (int i = 0; i < num.length; i++) { + if (visited[i]) { + continue; + } + // 选择值 + subResult.add(num[i]); + visited[i] = true; + permute0(num, subResult, visited, idx + 1); + // 撤销选择 + subResult.remove(idx); + visited[i] = false; + } + } + + public static void main(String[] args) { + System.out.println(new Solution2().permute(new int[]{1, 2, 3})); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\210\222\345\210\206\344\270\272k\344\270\252\347\233\270\347\255\211\347\232\204\345\255\220\351\233\206_698_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\210\222\345\210\206\344\270\272k\344\270\252\347\233\270\347\255\211\347\232\204\345\255\220\351\233\206_698_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..7cba38a4 --- /dev/null +++ "b/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\210\222\345\210\206\344\270\272k\344\270\252\347\233\270\347\255\211\347\232\204\345\255\220\351\233\206_698_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,72 @@ +package cn.cunchang.划分为k个相等的子集_698_中等; + +import java.util.Arrays; + +/** + * @author cunchang + * @date 2022/7/2 3:34 PM + */ +class Solution { + public boolean canPartitionKSubsets(int[] nums, int k) { + //因为题目限制条件不用担心溢出 + int sum = 0; + for (int i = 0; i < nums.length; i++) { + sum += nums[i]; + } + if (sum % k != 0) { + return false; + } + //求出子集的和 + sum = sum / k; + //排序 小的放最前面大的放最后面 + Arrays.sort(nums); + //如果子集的和小于数组最大的直接返回false + if (nums[nums.length - 1] > sum) { + return false; + } + //建立一个长度为k的桶 + int[] arr = new int[k]; + //桶的每一个值都是子集的和 + Arrays.fill(arr, sum); + + boolean flag = help(nums, nums.length - 1, arr); + +// System.out.println(Arrays.toString(arr)); + return flag; + } + + /** + * @param nums {1,2,3,3,4,4,5} + * @param cur 6 + * @param arr {5,5,5,5} + */ + boolean help(int[] nums, int cur, int[] arr) { + //已经遍历到了-1说明前面的所有数都正好可以放入桶里,那所有桶的值此时都为0,说明找到了结果,返回true + if (cur < 0) { + return true; + } + //遍历k个桶 + for (int i = 0; i < arr.length; i++) { + //如果正好能放下当前的数或者放下当前的数后,还有机会继续放前面的数(剪枝) + if (arr[i] == nums[cur] || (cur > 0 && arr[i] - nums[cur] >= nums[0])) { + //放当前的数到桶i里 + arr[i] -= nums[cur]; + //开始放下一个数 + if (help(nums, cur - 1, arr)) { + return true; + } + //这个数不该放在桶i中 + //从桶中拿回当前的数 + arr[i] += nums[cur]; + } + } + return false; + } + + public static void main(String[] args) { + int[] nums = {4, 3, 2, 3, 5, 2, 1}; + int k = 4; + System.out.println(new Solution().canPartitionKSubsets(nums, k)); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\255\220\351\233\206II_90_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\255\220\351\233\206II_90_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..174a7fe2 --- /dev/null +++ "b/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\255\220\351\233\206II_90_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,35 @@ +package cn.cunchang.子集II_90_中等; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +/** + * @author cunchang + * @date 2022/7/2 6:33 PM + */ +class Solution { + List> result = new ArrayList<>(); + LinkedList track = new LinkedList<>(); + + public List> subsetsWithDup(int[] nums) { + Arrays.sort(nums); + subsetsWithDup0(nums, 0); + return result; + } + + public void subsetsWithDup0(int[] nums, int idx) { + result.add(new ArrayList<>(track)); + for (int i = idx; i < nums.length; i++) { + // 跟前一个值相同,就需要剪枝 + if (i > idx && nums[i] == nums[i - 1]) { + continue; + } + track.add(nums[i]); + subsetsWithDup0(nums, i + 1); + track.removeLast(); + } + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\255\220\351\233\206_78_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\255\220\351\233\206_78_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..b7a2ea35 --- /dev/null +++ "b/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\345\255\220\351\233\206_78_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,33 @@ +package cn.cunchang.子集_78_中等; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * @author cunchang + * @date 2022/7/2 5:03 PM + */ +class Solution { + + List> result = new ArrayList<>(); + LinkedList track = new LinkedList<>(); + + public List> subsets(int[] nums) { + backtrack(nums, 0); + return result; + } + + public void backtrack(int[] nums, int idx) { + result.add(new LinkedList<>(track)); + // 选择列表中选择 + for (int i = idx; i < nums.length; i++) { + // 做选择 + track.add(nums[i]); + backtrack(nums, i + 1); + // 撤销选择 + track.removeLast(); + } + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\347\273\204\345\220\210_77_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\347\273\204\345\220\210_77_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..49efd6e7 --- /dev/null +++ "b/algorithms/leetcode2/backtracking/src/main/java/cn/cunchang/\347\273\204\345\220\210_77_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,43 @@ +package cn.cunchang.组合_77_中等; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * @author cunchang + * @date 2022/7/2 4:59 PM + */ +class Solution { + List> result = new ArrayList<>(); + LinkedList track = new LinkedList<>(); + + public List> combine(int n, int k) { + int[] nums = new int[n]; + for (int i = 0; i < n; i++) { + nums[i] = i + 1; + } + backtrack(nums, 0, k); + return result; + } + + public void backtrack(int[] nums, int idx, int k) { + if (track.size() == k) { + result.add(new LinkedList<>(track)); + return; + } + // 选择列表中选择 + for (int i = idx; i < nums.length; i++) { + // 做选择 + track.add(nums[i]); + backtrack(nums, i + 1, k); + // 撤销选择 + track.removeLast(); + } + } + + public static void main(String[] args) { + System.out.println(new Solution().combine(4, 2)); + } + +} \ No newline at end of file diff --git a/algorithms/leetcode2/binarysearch/pom.xml b/algorithms/leetcode2/binarysearch/pom.xml new file mode 100644 index 00000000..8cf210a7 --- /dev/null +++ b/algorithms/leetcode2/binarysearch/pom.xml @@ -0,0 +1,15 @@ + + + 4.0.0 + cn.cucnhang + 1.0-SNAPSHOT + binarysearch + + + 8 + 8 + + + \ No newline at end of file diff --git "a/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\344\272\214\345\210\206\346\237\245\346\211\276_704_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\344\272\214\345\210\206\346\237\245\346\211\276_704_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..ae43609a --- /dev/null +++ "b/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\344\272\214\345\210\206\346\237\245\346\211\276_704_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,46 @@ +package cn.cunchang.二分查找_704_简单; + +import org.junit.Assert; + +class Solution { + /** + * 思考: + * ------------------------------------------------------------------- + * 思路: + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public int search(int[] nums, int target) { + int l = 0, r = nums.length-1; // -1是因为最右边不存在的值会超界 + while (l <= r) {// =是因为该值有可能是正确答案 + int mid = (r + l) / 2; + if (nums[mid] > target) {// 中间值大于目标值 + r = mid - 1; // -1是因为该值不符合要求 + } else if (nums[mid] < target) { + l = mid + 1; // +1是因为该值不符合要求 + } else { + return mid; + } + } + return -1; + } + + public static void main(String[] args) { + // 偶数数组 存在 +// Assert.assertEquals(4, new Solution(). +// search(new int[]{-1, 0, 3, 5, 9, 12}, 9)); + // 偶数数组 左边中间不存在 +// Assert.assertEquals(-1, new Solution(). +// search(new int[]{-1, 0, 3, 5, 9, 12}, 2)); + // 偶数数组 最右边不存在 + Assert.assertEquals(-1, new Solution(). + search(new int[]{-1, 0, 3, 5, 9, 12}, 13)); + // 偶数数组 存在 +// Assert.assertEquals(4, new Solution(). +// search(new int[]{-1, 0, 3, 5, 9}, 9)); + // 偶数数组 不存在 +// Assert.assertEquals(-1, new Solution(). +// search(new int[]{-1, 0, 3, 5, 9}, 2)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\345\234\250\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\346\237\245\346\211\276\345\205\203\347\264\240\347\232\204\347\254\254\344\270\200\344\270\252\345\222\214\346\234\200\345\220\216\344\270\200\344\270\252\344\275\215\347\275\256_34_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\345\234\250\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\346\237\245\346\211\276\345\205\203\347\264\240\347\232\204\347\254\254\344\270\200\344\270\252\345\222\214\346\234\200\345\220\216\344\270\200\344\270\252\344\275\215\347\275\256_34_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..c7253abf --- /dev/null +++ "b/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\345\234\250\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\346\237\245\346\211\276\345\205\203\347\264\240\347\232\204\347\254\254\344\270\200\344\270\252\345\222\214\346\234\200\345\220\216\344\270\200\344\270\252\344\275\215\347\275\256_34_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,37 @@ +package cn.cunchang.在排序数组中查找元素的第一个和最后一个位置_34_中等; + +class Solution { + /** + * 找目标值的最左边和目标值+1的最左边 + * 缺点,小数不好使了 + * + */ + public int[] searchRange(int[] nums, int target) { + if (nums == null || nums.length == 0) { + return new int[]{-1, -1}; + } + int l = search(nums, target); + // l >= nums.length ==》超出右边界 searchRange(new int[]{2,2}, 3) + // nums[l] != target ==》找不到 searchRange(new int[]{5, 7, 7, 8, 8, 10}, 6) + if (l >= nums.length || nums[l] != target) { + return new int[]{-1, -1}; + } + int r = search(nums, target + 1) - 1; + return new int[]{l, r}; + } + + + private int search(int[] nums, int target) { + int l = 0, r = nums.length - 1; + while (l <= r) { + int mid = (r + l) / 2; + // 这里与无重复二分不同,=r也减少为了搜索最左边的target + if (nums[mid] >= target) { + r = mid - 1; + } else if (nums[mid] < target) { + l = mid + 1; + } + } + return l; + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\345\234\250\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\346\237\245\346\211\276\345\205\203\347\264\240\347\232\204\347\254\254\344\270\200\344\270\252\345\222\214\346\234\200\345\220\216\344\270\200\344\270\252\344\275\215\347\275\256_34_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\345\234\250\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\346\237\245\346\211\276\345\205\203\347\264\240\347\232\204\347\254\254\344\270\200\344\270\252\345\222\214\346\234\200\345\220\216\344\270\200\344\270\252\344\275\215\347\275\256_34_\344\270\255\347\255\211/Solution2.java" new file mode 100644 index 00000000..ecf93ea1 --- /dev/null +++ "b/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\345\234\250\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\346\237\245\346\211\276\345\205\203\347\264\240\347\232\204\347\254\254\344\270\200\344\270\252\345\222\214\346\234\200\345\220\216\344\270\200\344\270\252\344\275\215\347\275\256_34_\344\270\255\347\255\211/Solution2.java" @@ -0,0 +1,62 @@ +package cn.cunchang.在排序数组中查找元素的第一个和最后一个位置_34_中等; + +import java.util.Arrays; + +class Solution2 { + public int[] searchRange(int[] nums, int target) { + if (nums == null || nums.length == 0) { + return new int[]{-1, -1}; + } + int l = lowerBound(nums, target); + // l >= nums.length ==》超出右边界 searchRange(new int[]{2,2}, 3) + // nums[l] != target ==》找不到 searchRange(new int[]{5, 7, 7, 8, 8, 10}, 6) + if (l >= nums.length || nums[l] != target) { + return new int[]{-1, -1}; + } + int r = upperBound(nums, target) - 1; + return new int[]{l, r}; + } + + private int upperBound(int[] nums, int target) { + int l = 0, r = nums.length - 1; + while (l <= r) { + int mid = (r + l) / 2; + if (nums[mid] > target) { + r = mid - 1; + } else if (nums[mid] <= target) { + // 这里与无重复二分不同,=时l也增加为了缩小左边,搜索最右边的target + l = mid + 1; + } + } + return l; + } + + private int lowerBound(int[] nums, int target) { + int l = 0, r = nums.length - 1; + while (l <= r) { + int mid = (r + l) / 2; + // 这里与无重复二分不同,=时r也减少为了缩小右边,搜索最左边的target + // 这里有个问题就是,会不会跳过目标值比如 {5, 6, 7, 8, 9, 10}, 7;这里会跳过的 + // 但是l = mid + 1又加回来 + if (nums[mid] >= target) { + r = mid - 1; + } else if (nums[mid] < target) { + l = mid + 1; + } + } + return l; + } + + public static void main(String[] args) { +// System.out.println(Arrays.toString(new Solution2(). +// searchRange(new int[]{5, 7, 7, 8, 8, 10}, 8))); +// System.out.println(Arrays.toString(new Solution2(). +// searchRange(new int[]{5, 7, 7, 8, 8, 10}, 6))); +// System.out.println(Arrays.toString(new Solution2(). +// searchRange(new int[]{2, 2}, 3))); + System.out.println(Arrays.toString(new Solution2(). + searchRange(new int[]{5, 6, 7, 8, 9, 10}, 7))); +// System.out.println(Arrays.toString(new Solution2(). +// searchRange(new int[]{5, 6, 7, 8, 9, 10}, 10))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\345\234\250\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\346\237\245\346\211\276\345\205\203\347\264\240\347\232\204\347\254\254\344\270\200\344\270\252\345\222\214\346\234\200\345\220\216\344\270\200\344\270\252\344\275\215\347\275\256_34_\344\270\255\347\255\211/Solution3.java" "b/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\345\234\250\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\346\237\245\346\211\276\345\205\203\347\264\240\347\232\204\347\254\254\344\270\200\344\270\252\345\222\214\346\234\200\345\220\216\344\270\200\344\270\252\344\275\215\347\275\256_34_\344\270\255\347\255\211/Solution3.java" new file mode 100644 index 00000000..aa935a42 --- /dev/null +++ "b/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\345\234\250\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\346\237\245\346\211\276\345\205\203\347\264\240\347\232\204\347\254\254\344\270\200\344\270\252\345\222\214\346\234\200\345\220\216\344\270\200\344\270\252\344\275\215\347\275\256_34_\344\270\255\347\255\211/Solution3.java" @@ -0,0 +1,62 @@ +package cn.cunchang.在排序数组中查找元素的第一个和最后一个位置_34_中等; + +import java.util.Arrays; + +class Solution3 { + public int[] searchRange(double[] nums, double target) { + if (nums == null || nums.length == 0) { + return new int[]{-1, -1}; + } + int l = lowerBound(nums, target); + // l >= nums.length ==》超出右边界 searchRange(new double[]{2,2}, 3) + // nums[l] != target ==》找不到 searchRange(new double[]{5, 7, 7, 8, 8, 10}, 6) + if (l >= nums.length || nums[l] != target) { + return new int[]{-1, -1}; + } + int r = upperBound(nums, target) - 1; + return new int[]{l, r}; + } + + private int upperBound(double[] nums, double target) { + int l = 0, r = nums.length - 1; + while (l <= r) { + int mid = (r + l) / 2; + if (nums[mid] > target) { + r = mid - 1; + } else if (nums[mid] <= target) { + // 这里与无重复二分不同,=时l也增加为了缩小左边,搜索最右边的target + l = mid + 1; + } + } + return l; + } + + private int lowerBound(double[] nums, double target) { + int l = 0, r = nums.length - 1; + while (l <= r) { + int mid = (r + l) / 2; + // 这里与无重复二分不同,=时r也减少为了缩小右边,搜索最左边的target + // 这里有个问题就是,会不会跳过目标值比如 {5, 6, 7, 8, 9, 10}, 7;这里会跳过的 + // 但是l = mid + 1又加回来 + if (nums[mid] >= target) { + r = mid - 1; + } else if (nums[mid] < target) { + l = mid + 1; + } + } + return l; + } + + public static void main(String[] args) { +// System.out.println(Arrays.toString(new Solution2(). +// searchRange(new double[]{5, 7, 7, 8, 8, 10}, 8))); +// System.out.println(Arrays.toString(new Solution2(). +// searchRange(new double[]{5, 7, 7, 8, 8, 10}, 6))); +// System.out.println(Arrays.toString(new Solution2(). +// searchRange(new double[]{2, 2}, 3))); + System.out.println(Arrays.toString(new Solution3(). + searchRange(new double[]{7.5, 7.6, 7.7,7.7, 7.8, 7.9}, 7.7))); +// System.out.println(Arrays.toString(new Solution2(). +// searchRange(new double[]{5, 6, 7, 8, 9, 10}, 10))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\346\220\234\347\264\242\346\227\213\350\275\254\346\216\222\345\272\217\346\225\260\347\273\204_33_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\346\220\234\347\264\242\346\227\213\350\275\254\346\216\222\345\272\217\346\225\260\347\273\204_33_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..6c8f60a0 --- /dev/null +++ "b/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\346\220\234\347\264\242\346\227\213\350\275\254\346\216\222\345\272\217\346\225\260\347\273\204_33_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,42 @@ +package cn.cunchang.搜索旋转排序数组_33_中等; + +import org.junit.Assert; + +class Solution { + public int search(int[] nums, int target) { + int l = 0, r = nums.length - 1; + // 1、找升序部分对升序部分进行二分 + while (l <= r) { + int mid = (l + r) / 2; + if (nums[mid] == target) { + return mid; + } + if (nums[mid] >= nums[l]) { + // 4,5,6,7,0,1,2;7>=4;说明[l,mid]是升序的 + // target在[l,mid]内,对[l,mid]进行二分 + if (target >= nums[l] && target < nums[mid]) { + r = mid - 1; + } else { + l = mid + 1; + } + } else { + // 4,5,6,0,1,2;0<4;说明说明[mid,r]是升序的 + // target在[mid,r]内,对[mid,r]进行二分 + if (target > nums[mid] && target <= nums[r]) { + l = mid + 1; + } else { + r = mid - 1; + } + } + } + return -1; + } + + public static void main(String[] args) { + Assert.assertEquals(5, new Solution().search(new int[]{4, 5, 6, 7, 8, 0, 1, 2, 3}, 0)); +// Assert.assertEquals(4, new Solution().search(new int[]{4, 5, 6, 7, 0, 1, 2}, 0)); +// Assert.assertEquals(-1, new Solution().search(new int[]{4, 5, 6, 7, 0, 1, 2}, 3)); + + + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\346\220\234\347\264\242\346\227\213\350\275\254\346\216\222\345\272\217\346\225\260\347\273\204_II_81_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\346\220\234\347\264\242\346\227\213\350\275\254\346\216\222\345\272\217\346\225\260\347\273\204_II_81_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..d2767e3e --- /dev/null +++ "b/algorithms/leetcode2/binarysearch/src/main/java/cn/cunchang/\346\220\234\347\264\242\346\227\213\350\275\254\346\216\222\345\272\217\346\225\260\347\273\204_II_81_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,36 @@ +package cn.cunchang.搜索旋转排序数组_II_81_中等; + +class Solution { + public boolean search(int[] nums, int target) { + int l = 0, r = nums.length - 1; + // 1、找升序部分对升序部分进行二分 + while (l <= r) { + int mid = (l + r) / 2; + if (nums[mid] == target) { + return true; + } + if (nums[mid] == nums[l]) { + // 无法判断哪个区间是增序的 + l++; + } else if (nums[mid] >= nums[l]) { + // 4,5,6,7,0,1,2;7>=4;说明[l,mid]是升序的 + // target在[l,mid]内,对[l,mid]进行二分 + if (target >= nums[l] && target < nums[mid]) { + r = mid - 1; + } else { + l = mid + 1; + } + } else { + // 4,5,6,0,1,2;0<4;说明说明[mid,r]是升序的 + // target在[mid,r]内,对[mid,r]进行二分 + if (target > nums[mid] && target <= nums[r]) { + l = mid + 1; + } else { + r = mid - 1; + } + } + } + return false; + } + +} \ No newline at end of file diff --git a/algorithms/leetcode2/dfsbfs/pom.xml b/algorithms/leetcode2/dfsbfs/pom.xml new file mode 100644 index 00000000..53da35d3 --- /dev/null +++ b/algorithms/leetcode2/dfsbfs/pom.xml @@ -0,0 +1,15 @@ + + + 4.0.0 + + dfsbfs + cn.cucnhang + 1.0-SNAPSHOT + + 8 + 8 + + + \ No newline at end of file diff --git "a/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\345\244\252\345\271\263\346\264\213\345\244\247\350\245\277\346\264\213\346\265\201\346\260\264\351\227\256\351\242\230_417_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\345\244\252\345\271\263\346\264\213\345\244\247\350\245\277\346\264\213\346\265\201\346\260\264\351\227\256\351\242\230_417_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..50802ac1 --- /dev/null +++ "b/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\345\244\252\345\271\263\346\264\213\345\244\247\350\245\277\346\264\213\346\265\201\346\260\264\351\227\256\351\242\230_417_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,65 @@ +package cn.cunchang.太平洋大西洋流水问题_417_中等; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +class Solution { + public List> pacificAtlantic(int[][] heights) { + int m = heights.length; + int n = heights[0].length; + int[][] enableAo = new int[m][n];//太平洋的节点记录矩阵 + int[][] enablePa = new int[m][n];//大西洋的节点记录矩阵 + //1. 从上下边界开始两大洋的回流搜索,变动的是列 + for (int i = 0; i < n; i++) { + // 最上面一列,dfs太平洋 + dfs(heights, enablePa, 0, i); + // 最下面一列,dfs大西洋 + dfs(heights, enableAo, m - 1, i); + } + //2. 从左右边界开始两大洋的回流搜索,变动的是行 + for (int i = 0; i < m; i++) { + // 最左面一行,dfs太平洋 + dfs(heights, enablePa, i, 0); + // 最右面一行,dfs大西洋 + dfs(heights, enableAo, i, n - 1); + } + //3. 输出交叠的坐标 + List> cnt = new ArrayList<>(); + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (enableAo[i][j] == 1 && enablePa[i][j] == 1) { + cnt.add(Arrays.asList(i, j)); + } + } + } + return cnt; + } + + public static void dfs(int[][] heights, int[][] tmp, int curI, int curJ) { + //标记可以从海洋流回经过的节点 + tmp[curI][curJ] = 1; + //开始深度优先搜索当前坐标的4个方向 + //1. 设置更新的坐标 + int[] di = new int[]{1, -1, 0, 0};//上下移动 + int[] dj = new int[]{0, 0, 1, -1};//左右移动 + //2. 更新坐标并递归搜索 + for (int index = 0; index < 4; index++) { + int newI = curI + di[index]; + int newJ = curJ + dj[index]; + //判断下标是否越界 + if (newI < 0 || newJ < 0 || newI >= heights.length || newJ >= heights[0].length) { + continue; + } + if (heights[curI][curJ] <= heights[newI][newJ] && tmp[newI][newJ] != 1) { + dfs(heights, tmp, newI, newJ); + } + } + } + + public static void main(String[] args) { + int[][] heights = {{1, 2, 2, 3, 5}, {3, 2, 3, 4, 4}, {2, 4, 5, 3, 1}, {6, 7, 1, 4, 5}, {5, 1, 1, 2, 4}}; + System.out.println(new Solution().pacificAtlantic(heights)); + } + +} diff --git "a/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\345\244\252\345\271\263\346\264\213\345\244\247\350\245\277\346\264\213\346\265\201\346\260\264\351\227\256\351\242\230_417_\344\270\255\347\255\211/Solution_my.java" "b/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\345\244\252\345\271\263\346\264\213\345\244\247\350\245\277\346\264\213\346\265\201\346\260\264\351\227\256\351\242\230_417_\344\270\255\347\255\211/Solution_my.java" new file mode 100644 index 00000000..294b6430 --- /dev/null +++ "b/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\345\244\252\345\271\263\346\264\213\345\244\247\350\245\277\346\264\213\346\265\201\346\260\264\351\227\256\351\242\230_417_\344\270\255\347\255\211/Solution_my.java" @@ -0,0 +1,85 @@ +package cn.cunchang.太平洋大西洋流水问题_417_中等; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +class Solution_my { + public List> pacificAtlantic(int[][] heights) { + List> result = new ArrayList<>(); + // 对每个单元格搜索,判断是否可以向上或左同时向下或右,可以就说明满足 + for (int i = 0; i < heights.length; i++) { + for (int j = 0; j < heights.length; j++) { + boolean flag = pacificAtlantic(heights, i, j); + if (flag) { + result.add(Arrays.asList(i,j)); + } + } + } + return result; + } + + /** + * @param i 纵 + * @param j 横 + */ + private boolean pacificAtlantic(int[][] heights, int i, int j) { + + boolean pacificEnable1 = true; + // 上;i减减 + for (int k = i; k >= 0; k--) { + if (heights[i][j] < heights[k][j]) { + pacificEnable1 = false; + break; + } + if (i - k > 1 && heights[i][j] == heights[k][j]) { + pacificEnable1 = false; + break; + } + } + boolean pacificEnable2 = true; + // 左 j减 + for (int k = j; k >= 0; k--) { + if (heights[i][j] < heights[i][k]) { + pacificEnable2 = false; + break; + } + if (j - k > 1 && heights[i][j] == heights[k][j]) { + pacificEnable1 = false; + break; + } + } + + boolean atlanticEnable1 = true; + // 下 + for (int k = i; k < heights.length; k++) { + if (heights[i][j] < heights[k][j]) { + atlanticEnable1 = false; + break; + } + if (k - i > 1 && heights[i][j] == heights[k][j]) { + pacificEnable1 = false; + break; + } + } + boolean atlanticEnable2 = true; + // 右 + for (int k = j; k < heights.length; k++) { + if (heights[i][j] < heights[i][k]) { + atlanticEnable2 = false; + break; + } + if (k - j > 1 && heights[i][j] == heights[k][j]) { + pacificEnable1 = false; + break; + } + } + + return (pacificEnable1 || pacificEnable2) && (atlanticEnable1 || atlanticEnable2); + } + + public static void main(String[] args) { + int[][] heights = {{1, 2, 2, 3, 5}, {3, 2, 3, 4, 4}, {2, 4, 5, 3, 1}, {6, 7, 1, 4, 5}, {5, 1, 1, 2, 4}}; + System.out.println(new Solution_my().pacificAtlantic(heights)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\345\262\233\345\261\277\347\232\204\346\234\200\345\244\247\351\235\242\347\247\257_695_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\345\262\233\345\261\277\347\232\204\346\234\200\345\244\247\351\235\242\347\247\257_695_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..602f81f5 --- /dev/null +++ "b/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\345\262\233\345\261\277\347\232\204\346\234\200\345\244\247\351\235\242\347\247\257_695_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,35 @@ +package cn.cunchang.岛屿的最大面积_695_中等; + +class Solution { + public int maxAreaOfIsland(int[][] grid) { + int res = 0; + // 对搜索过的岛屿进行标记 + int[][] mark = new int[grid.length][grid[0].length]; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + int tmp = dfs(grid, i, j, mark); + res = Math.max(res, tmp); + } + } + return res; + } + + private int dfs(int[][] grid, int i, int j, int[][] mark) { + // i,j未超界 + if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length) { + return 0; + } + // 已经来过不处理 + if (mark[i][j] == 1 || grid[i][j] == 0) { + return 0; + } + mark[i][j] = 1;// 标记已经来过 + int res = 1; + res += dfs(grid, i - 1, j, mark);//上 + res += dfs(grid, i + 1, j, mark);//下 + res += dfs(grid, i, j - 1, mark);//左 + res += dfs(grid, i, j + 1, mark);//右 + return res; + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\345\262\233\345\261\277\347\232\204\346\234\200\345\244\247\351\235\242\347\247\257_695_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\345\262\233\345\261\277\347\232\204\346\234\200\345\244\247\351\235\242\347\247\257_695_\344\270\255\347\255\211/Solution2.java" new file mode 100644 index 00000000..06684056 --- /dev/null +++ "b/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\345\262\233\345\261\277\347\232\204\346\234\200\345\244\247\351\235\242\347\247\257_695_\344\270\255\347\255\211/Solution2.java" @@ -0,0 +1,71 @@ +package cn.cunchang.岛屿的最大面积_695_中等; + +import javafx.util.Pair; + +import java.util.Stack; + +class Solution2 { + /** + * 栈模拟递归 + */ + public int maxAreaOfIsland(int[][] grid) { + int res = 0; + int x, y; + int[] direction = new int[]{-1, 0, 1, 0, -1}; + Stack> stack = new Stack<>(); + // 对搜索过的岛屿进行标记 + int[][] visited = new int[grid.length][grid[0].length]; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + if (grid[i][j] == 1 && visited[i][j] == 0) { + int areaCount = 1; + visited[i][j] = 1;//当前节点已经访问 + stack.push(new Pair<>(i, j)); + + while (!stack.isEmpty()) { + Pair pair = stack.pop(); + for (int k = 0; k < 4; ++k) { + x = pair.getKey() + direction[k]; + y = pair.getValue() + direction[k + 1]; + if (checkArea(grid, visited, x, y)) { + areaCount++; + visited[x][y] = 1; + stack.push(new Pair<>(x, y)); + } + } + + } + + res = Math.max(res, areaCount); + } + } + } + return res; + } + + private boolean checkArea(int[][] grid, int[][] visited, int x, int y) { + // i,j未超界 + if (x < 0 || y < 0 || x >= grid.length || y >= grid[0].length) { + return false; + } + // 已经来过不处理 + if (visited[x][y] == 1 || grid[x][y] == 0) { + return false; + } + return true; + } + + public static void main(String[] args) { + int[][] x = { + {0,0,1,0,0,0,0,1,0,0,0,0,0}, + {0,0,0,0,0,0,0,1,1,1,0,0,0}, + {0,1,1,0,1,0,0,0,0,0,0,0,0}, + {0,1,0,0,1,1,0,0,1,0,1,0,0}, + {0,1,0,0,1,1,0,0,1,1,1,0,0}, + {0,0,0,0,0,0,0,0,0,0,1,0,0}, + {0,0,0,0,0,0,0,1,1,1,0,0,0}, + {0,0,0,0,0,0,0,1,1,0,0,0,0}}; + System.out.println(new Solution2().maxAreaOfIsland(x)); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\347\234\201\344\273\275\346\225\260\351\207\217_547_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\347\234\201\344\273\275\346\225\260\351\207\217_547_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..3138fb69 --- /dev/null +++ "b/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\347\234\201\344\273\275\346\225\260\351\207\217_547_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,40 @@ + +package cn.cunchang.省份数量_547_中等; + +class Solution { + /** + * 有几个需要注意的条件 + * isConnected[i][i] == 1 + * isConnected[i][j] == isConnected[j][i] + *

+ * isConnected[i][i] == 1 说明是个无向图 + */ + public int findCircleNum(int[][] isConnected) { + boolean[] visited = new boolean[isConnected.length]; + + int res = 0; + for (int i = 0; i < isConnected.length; i++) { + if (!visited[i]) { + findCircleNum(isConnected, i, visited); + res++; + } + } + return res; + } + // 深度遍历,相邻节点,并对访问过的节点进行标记 + private void findCircleNum(int[][] isConnected, int i, boolean[] visited) { + visited[i] = true; + for (int j = 0; j < isConnected.length; j++) { + if (isConnected[i][j] == 1 && !visited[j]) { + findCircleNum(isConnected, j, visited); + } + } + } + + public static void main(String[] args) { + int[][] isConnected = {{1, 1, 0}, + {1, 1, 0}, + {0, 0, 1}}; + System.out.println(new Solution().findCircleNum(isConnected)); + } +} \ No newline at end of file diff --git a/algorithms/leetcode2/dynamic2/pom.xml b/algorithms/leetcode2/dynamic2/pom.xml new file mode 100644 index 00000000..77cc2ec4 --- /dev/null +++ b/algorithms/leetcode2/dynamic2/pom.xml @@ -0,0 +1,19 @@ + + + + leetcode2 + cn.cucnhang + 1.0-SNAPSHOT + + 4.0.0 + + dynamic + + + 8 + 8 + + + \ No newline at end of file diff --git a/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/knapsack01/knapsack01.md b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/knapsack01/knapsack01.md new file mode 100644 index 00000000..7431ee35 --- /dev/null +++ b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/knapsack01/knapsack01.md @@ -0,0 +1,15 @@ +| id | 0 | 1 | 2 | +| ------ | ---- | ---- | ---- | +| weight | 1 | 2 | 3 | +| value | 6 | 10 | 12 | + +​ + + + +| 物品编号\背包容量 | 0 | 1 | 2 | 3 | 4 | 5 | +|-----------| ---- | ---- | ---- | ---- | ---- | ---- | +| 0 | 0 | 6 | 6 | 6 | 6 | 6 | +| 1 | 0 | 6 | 10 | 16 | 16 | 16 | +| 2 | 0 | 6 | 10 | 16 | 18 | 22 | + diff --git "a/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\346\211\223\345\256\266\345\212\253\350\210\215_198_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\346\211\223\345\256\266\345\212\253\350\210\215_198_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..09910cfd --- /dev/null +++ "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\346\211\223\345\256\266\345\212\253\350\210\215_198_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,30 @@ +package cn.cunchang.打家劫舍_198_中等; + +class Solution { + public int rob(int[] nums) { + return tryRob(0, nums); + } + + /** + * idx 偷窃的起始位置 + */ + public int tryRob(int idx, int[] nums) { + if (idx >= nums.length) { + return 0; + } + int max = 0, res = 0; + // 对[idx,nums.length-1]每个位置进行偷窃 + for (int i = idx; i < nums.length; i++) { + // 找当前位置可以偷窃的最佳金额 + int subMax = tryRob(i + 2, nums); + res = nums[i] + subMax; + max = Math.max(max, res); + } + return max; + } + + public static void main(String[] args) { + System.out.println(new Solution().rob(new int[]{1,2,3,1})); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\346\211\223\345\256\266\345\212\253\350\210\215_198_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\346\211\223\345\256\266\345\212\253\350\210\215_198_\344\270\255\347\255\211/Solution2.java" new file mode 100644 index 00000000..dcb878b2 --- /dev/null +++ "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\346\211\223\345\256\266\345\212\253\350\210\215_198_\344\270\255\347\255\211/Solution2.java" @@ -0,0 +1,38 @@ +package cn.cunchang.打家劫舍_198_中等; + +import java.util.Arrays; + +class Solution2 { + public int rob(int[] nums) { + int[] moment = new int[nums.length]; + Arrays.fill(moment, -1); + return tryRob(0, nums, moment); + } + + /** + * idx 偷窃的起始位置 + */ + public int tryRob(int idx, int[] nums, int[] moment) { + if (idx >= nums.length) { + return 0; + } + if (moment[idx] != -1) { + return moment[idx]; + } + int max = 0, res = 0; + // 对[idx,nums.length-1]每个位置进行偷窃 + for (int i = idx; i < nums.length; i++) { + // 找当前位置可以偷窃的最佳金额 + int subMax = tryRob(i + 2, nums, moment); + res = nums[i] + subMax; + max = Math.max(max, res); + } + moment[idx] = max; + return max; + } + + public static void main(String[] args) { + System.out.println(new Solution2().rob(new int[]{1, 2, 3, 1})); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\347\210\254\346\245\274\346\242\257_70_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\347\210\254\346\245\274\346\242\257_70_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..4c715f6d --- /dev/null +++ "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\347\210\254\346\245\274\346\242\257_70_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,21 @@ +package cn.cunchang.爬楼梯_70_简单; + +class Solution { + public int climbStairs(int n) { + if (n == 1) { + return 1; + } + if (n == 2) { + return 2; + } + int f1 = 1, f2 = 2; + int res = 0; + for (int i = 2; i < n; i++) { + res = f1 + f2; + f1 = f2; + f2 = res; + } + + return res; + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\351\233\266\351\222\261\345\205\221\346\215\242_322_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\351\233\266\351\222\261\345\205\221\346\215\242_322_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..f453307e --- /dev/null +++ "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\351\233\266\351\222\261\345\205\221\346\215\242_322_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,47 @@ +package cn.cunchang.零钱兑换_322_中等; + +import java.util.HashMap; + +/** + * @author cunchang + * @date 2022/6/23 5:07 PM + */ +class Solution { + + public int coinChange(int[] coins, int amount) { + HashMap meno = new HashMap<>(); + return coinChange0(coins, amount, meno); + } + + public int coinChange0(int[] coins, int amount, HashMap meno) { + if (amount < 0) { + return -1; + } + if (amount == 0) { + return 0; + } + if (meno.get(amount) != null) { + return meno.get(amount); + } + int res = Integer.MAX_VALUE; + for (int coin : coins) { + int subRes = coinChange0(coins, amount - coin, meno); + // 子问题无解 + if (subRes == -1) { + continue; + } + // 找子问题最小解 + res = Math.min(res, subRes + 1); + } + + res = (res == Integer.MAX_VALUE) ? -1 : res; + // 对amount的结果进行缓存 + meno.put(amount, res); + return res; + } + + public static void main(String[] args) { + System.out.println(new Solution().coinChange(new int[]{1, 2, 5}, 11)); +// System.out.println(new Solution().coinChange(new int[]{2}, 3)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\351\233\266\351\222\261\345\205\221\346\215\242_322_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\351\233\266\351\222\261\345\205\221\346\215\242_322_\344\270\255\347\255\211/Solution2.java" new file mode 100644 index 00000000..c804b59d --- /dev/null +++ "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\351\233\266\351\222\261\345\205\221\346\215\242_322_\344\270\255\347\255\211/Solution2.java" @@ -0,0 +1,30 @@ +package cn.cunchang.零钱兑换_322_中等; + +import java.util.Arrays; + +/** + * @author cunchang + * @date 2022/6/23 5:07 PM + */ +class Solution2 { + + public int coinChange(int[] coins, int amount) { + int max = amount + 1; + int[] dp = new int[amount + 1]; + Arrays.fill(dp, max); + dp[0] = 0; + for (int i = 1; i <= amount; i++) { + for (int j = 0; j < coins.length; j++) { + if (coins[j] <= i) { + dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1); + } + } + } + return dp[amount] > amount ? -1 : dp[amount]; + } + + public static void main(String[] args) { + System.out.println(new Solution2().coinChange(new int[]{1, 2, 5}, 11)); +// System.out.println(new Solution().coinChange(new int[]{2}, 3)); + } +} \ No newline at end of file diff --git a/algorithms/leetcode2/greedy/pom.xml b/algorithms/leetcode2/greedy/pom.xml new file mode 100644 index 00000000..31a3db05 --- /dev/null +++ b/algorithms/leetcode2/greedy/pom.xml @@ -0,0 +1,22 @@ + + + 4.0.0 + + greedy + cn.cucnhang + 1.0-SNAPSHOT + + + 8 + 8 + + + + junit + junit + 4.12 + + + \ No newline at end of file diff --git "a/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272II_122_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272II_122_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..46b7e94e --- /dev/null +++ "b/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272II_122_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,31 @@ +package cn.cunchang.买卖股票的最佳时机II_122_简单; + +import org.junit.Assert; + +class Solution { + /** + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 贪心策略:从后往前遍历 + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public int maxProfit(int[] prices) { + int profit = 0; + for (int i = prices.length - 1; i > 0; i--) { + if (prices[i] > prices[i - 1]) { + profit += prices[i] - prices[i - 1]; + } + } + return profit; + } + + public static void main(String[] args) { +// int[] prices = {7, 1, 5, 3, 6, 4}; +// Assert.assertEquals(7, new Solution().maxProfit(prices)); + int[] prices = {1,2,3,4,5}; + Assert.assertEquals(4, new Solution().maxProfit(prices)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\345\210\206\345\217\221\347\263\226\346\236\234_135_\345\233\260\351\232\276/Solution1.java" "b/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\345\210\206\345\217\221\347\263\226\346\236\234_135_\345\233\260\351\232\276/Solution1.java" new file mode 100644 index 00000000..830f84ab --- /dev/null +++ "b/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\345\210\206\345\217\221\347\263\226\346\236\234_135_\345\233\260\351\232\276/Solution1.java" @@ -0,0 +1,51 @@ +package cn.cunchang.分发糖果_135_困难; + +import org.junit.Assert; + +import java.util.Arrays; + +public class Solution1 { + /** + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 从前往后贪一次,从后往前再贪一次,不过第二次要判断大小,只贪最大的哪个 + *

+ * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ + public int candy(int[] ratings) { + if (ratings.length < 2) { + return ratings.length; + } + int[] resArr = new int[ratings.length]; + Arrays.fill(resArr, 1); + // 先从左往右遍历一遍,如果右边孩子的评分比左边的高,则右边孩子的糖果数更新为左边孩子的糖果数加 1; + for (int i = 1; i < ratings.length; i++) {// i = 1而不是i = 0 + if (ratings[i] > ratings[i - 1]) { + resArr[i] = resArr[i - 1] + 1; + } + } + // 再从右往左遍历一遍,如果左边孩子的评分比右边的高,且左边孩子当前的糖果数不大于右边孩子的糖果数, + // 则左边孩子的糖果数更新为右边孩子的糖果数加 1。 + for (int i = ratings.length - 1; i > 0; i--) {// i > 0而不是i >= 0 + if (ratings[i] < ratings[i - 1]) { + resArr[i - 1] = Math.max(resArr[i - 1], resArr[i] + 1); + } + } + + int count = 0; + for (int res : resArr) { + count += res; + } + return count; + } + + public static void main(String[] args) { +// int[] g = new int[]{1, 2, 87, 87, 87, 2, 1}; + int[] g = new int[]{1, 0, 2}; + Assert.assertEquals(5, new Solution1().candy(g)); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\345\210\206\345\217\221\351\245\274\345\271\262_455_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\345\210\206\345\217\221\351\245\274\345\271\262_455_\347\256\200\345\215\225/Solution1.java" new file mode 100644 index 00000000..d8ff0bf0 --- /dev/null +++ "b/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\345\210\206\345\217\221\351\245\274\345\271\262_455_\347\256\200\345\215\225/Solution1.java" @@ -0,0 +1,48 @@ +package cn.cunchang.分发饼干_455_简单; + +import org.junit.Assert; + +import java.util.Arrays; + +public class Solution1 { + /** + * 思考:因为饥饿度最小的孩子最容易吃饱,所以我们先考虑这个孩子。为了尽量使得剩下的饼干可 + * 以满足饥饿度更大的孩子,所以我们应该把大于等于这个孩子饥饿度的、且大小最小的饼干给这 + * 个孩子。满足了这个孩子之后,我们采取同样的策略,考虑剩下孩子里饥饿度最小的孩子,直到 + * 没有满足条件的饼干存在。 + * ------------------------------------------------------------------- + * 思路: + * 1、排序,对孩子的胃口和饼干大小降序排序 + * 2、将最小的饼干s[j]给胃口最小的孩子g[i],s[j] >= g[i],说明满足,满足孩子数+1、继续分发下一块饼干; + * 不满足的话,孩子数不加,继续分发下一块饼干; + * + *

+ * ------------------------------------------------------------------- + * 时间复杂度:n + * 空间复杂度: + */ + public int findContentChildren(int[] childs, int[] cookies) { + Arrays.sort(childs); + Arrays.sort(cookies); + int child = 0, cookie = 0; + while (child < childs.length && cookie < cookies.length) { + if (cookies[cookie] >= childs[child]) { + child++; + } + cookie++; + } + return child; + } + + public static void main(String[] args) { +// int[] g = new int[]{1, 2}; +// int[] s = new int[]{1, 2, 3}; +// Assert.assertEquals(2, new Solution1().findContentChildren(g, s)); + + int[] g = new int[]{1, 2, 3}; + int[] s = new int[]{1, 1}; + Assert.assertEquals(1, new Solution1().findContentChildren(g, s)); + + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\346\227\240\351\207\215\345\217\240\345\214\272\351\227\264_435_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\346\227\240\351\207\215\345\217\240\345\214\272\351\227\264_435_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..ac08712c --- /dev/null +++ "b/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\346\227\240\351\207\215\345\217\240\345\214\272\351\227\264_435_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,45 @@ +package cn.cunchang.无重叠区间_435_中等; + +import org.junit.Assert; + +import java.util.Arrays; +import java.util.Comparator; + +public class Solution { + /** + * 思考: + * 1. 什么是“区间不重叠”?intervals[i][1]<=intervals[i+1][0],说明区间i和区间i+1不重叠,否则就是重叠 + * 2. 什么是“移除区间的最小数量,使剩余区间互不重叠”?比如“[[1,100],[11,22],[1,11],[2,12]]”移除后三个区间也不重叠,但是最小数量是移除1、4区间。 + * ------------------------------------------------------------------- + * 思路: + * 1、按照区间结尾升序 + * 2、相邻单位区间,重合就移除;不重叠继续判断 + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public int eraseOverlapIntervals(int[][] intervals) { + Arrays.sort(intervals, new Comparator() { + @Override + public int compare(int[] interval1, int[] interval2) { + return interval1[1] - interval2[1]; + } + }); + + int total = 0, pre = intervals[0][1]; + for (int i = 1; i < intervals.length; i++) { + if (intervals[i][0] >= pre) { + pre = intervals[i][1]; + } else { + total++; + } + } + return total; + } + + public static void main(String[] args) { + int[][] g = new int[][]{{1, 100}, {11, 22}, {1, 11}, {2, 12}}; + Assert.assertEquals(2, new Solution().eraseOverlapIntervals(g)); + + } +} \ No newline at end of file diff --git a/algorithms/leetcode2/leetcode2-common/pom.xml b/algorithms/leetcode2/leetcode2-common/pom.xml new file mode 100644 index 00000000..9e8d3916 --- /dev/null +++ b/algorithms/leetcode2/leetcode2-common/pom.xml @@ -0,0 +1,21 @@ + + + + + + + + 4.0.0 + + leetcode2-common + cn.cucnhang + 1.0-SNAPSHOT + + + 8 + 8 + + + \ No newline at end of file diff --git a/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/array/ArrayUtil.java b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/array/ArrayUtil.java new file mode 100644 index 00000000..5e3e6325 --- /dev/null +++ b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/array/ArrayUtil.java @@ -0,0 +1,75 @@ +package cn.cunchang.array; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author lastwhisper + * @date 2020/2/4 + */ +public class ArrayUtil { + + public static int[] createArrays(int... arr) { + return arr; + } + + /** + * {"ab","cd"}=> + * 创建二维字符数组 + */ + public static char[][] createCharArrays(String[] arr) { + int m = arr.length, n = arr[0].length(); + char[][] chars = new char[m][n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + chars[i][j] = arr[i].charAt(j); + } + } + return chars; + } + + /** + * {{"a","b","c","d"}}=> + * 创建二维字符数组 + */ + public static char[][] createCharArrays(String[][] arr) { + int m = arr.length, n = arr[0].length; + char[][] chars = new char[m][n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + chars[i][j] = arr[i][j].charAt(0); + } + } + return chars; + } + + /** + * 创建二维数组 + */ + public static int[][] createIntArrays(String[] arr) { + int m = arr.length, n = arr[0].length(); + int[][] ints = new int[m][n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + ints[i][j] = arr[i].charAt(j) - '0'; + } + } + return ints; + } + + + /** + * 创建list + */ + public static List> createList(int[][] arrays) { + List> lists = new ArrayList<>(arrays.length); + for (int[] array : arrays) { + List list = new ArrayList<>(array.length); + for (int num : array) { + list.add(num); + } + lists.add(list); + } + return lists; + } +} diff --git a/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/linkedlist/LinkedListUtil.java b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/linkedlist/LinkedListUtil.java new file mode 100644 index 00000000..bdafc303 --- /dev/null +++ b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/linkedlist/LinkedListUtil.java @@ -0,0 +1,58 @@ +package cn.cunchang.linkedlist; + + +/** + * 操作链表工具类 + * + * @author lastwhisper + * @date 1/7/2020 + */ +public class LinkedListUtil { + + /** + * 创建单链表 + */ + public static ListNode createListNode(int... arr) { + if (arr == null || arr.length == 0) { + return null; + } + ListNode head = new ListNode(arr[0]); + ListNode current = head; + for (int i = 1; i < arr.length; i++) { + current.next = new ListNode(arr[i]); + current = current.next; + } + return head; + } + + /** + * 打印单链表 + */ + public static void printListNode(String msg, ListNode head) { + System.out.println(msg + appendVal(head)); + } + + /** + * 打印单链表 + */ + public static void printListNode(ListNode head) { + System.out.println(appendVal(head)); + } + + private static String appendVal(ListNode head) { + StringBuilder sb = new StringBuilder(); + ListNode current = head; + while (current != null) { + sb.append(current.val); + sb.append("->"); + current = current.next; + } + sb.append("NULL"); + return sb.toString(); + } + + + public static void main(String[] args) { + printListNode(createListNode(1, 2, 3, 4, 5, 6, 7)); + } +} diff --git a/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/linkedlist/ListNode.java b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/linkedlist/ListNode.java new file mode 100644 index 00000000..3db97b0e --- /dev/null +++ b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/linkedlist/ListNode.java @@ -0,0 +1,11 @@ +package cn.cunchang.linkedlist; + +public class ListNode { + public int val; + public ListNode next; + + public ListNode(int x) { + val = x; + } + +} \ No newline at end of file diff --git a/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/print/PrintUtil.java b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/print/PrintUtil.java new file mode 100644 index 00000000..d87301ac --- /dev/null +++ b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/print/PrintUtil.java @@ -0,0 +1,93 @@ +package cn.cunchang.print; + +import java.util.Collection; +import java.util.List; + + +/** + * 打印工具类 + * @author lastwhisper + * @date 2020/2/1 + */ +public class PrintUtil { + + /** + * 层次打印二维数组 + */ + public static void printLists(List> lists) { + System.out.println("["); + int counter1 = 1; + for (List list : lists) { + System.out.print("\t[\""); + int counter2 = 1; + for (Integer i : list) { + if (counter2 != list.size()) { + System.out.print(i + "\",\""); + } else { + System.out.print(i); + } + counter2++; + } + if (counter1 != lists.size()) { + System.out.print("\"],\n"); + } else { + System.out.print("\"]\n"); + } + counter1++; + } + System.out.println("]"); + } + + public static void printStringLists(List> lists) { + System.out.println("["); + int counter1 = 1; + for (List list : lists) { + System.out.print("\t[\""); + int counter2 = 1; + for (String i : list) { + if (counter2 != list.size()) { + System.out.print(i + "\",\""); + } else { + System.out.print(i ); + } + counter2++; + } + if (counter1 != lists.size()) { + System.out.print("\"],\n"); + } else { + System.out.print("\"]\n"); + } + counter1++; + } + System.out.println("]"); + } + + /** + * 打印数组 + */ + public static void printList(Collection collection) { + System.out.println(collection2String(collection)); + } + + /** + * 将Collection扁平化迭代成String + */ + public static String collection2String(Collection collection) { + StringBuilder sb = new StringBuilder(); + try { + sb.append("[\""); + int counter = 1; + for (Object object : collection) { + sb.append(object); + if (counter != collection.size()) { + sb.append("\",\""); + } + counter++; + } + sb.append("\"]"); + } catch (Exception e) { + e.printStackTrace(); + } + return sb.toString(); + } +} diff --git a/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TreeNode.java b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TreeNode.java new file mode 100644 index 00000000..d3b599af --- /dev/null +++ b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TreeNode.java @@ -0,0 +1,11 @@ +package cn.cunchang.tree; + +public class TreeNode { + public int val; + public TreeNode left; + public TreeNode right; + + public TreeNode(int x) { + val = x; + } +} \ No newline at end of file diff --git a/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TreeUtil.java b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TreeUtil.java new file mode 100644 index 00000000..958d39fd --- /dev/null +++ b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TreeUtil.java @@ -0,0 +1,121 @@ +package cn.cunchang.tree; + +import cn.cunchang.print.PrintUtil; +import javafx.util.Pair; + +import java.util.*; + + +/** + * 树相关工具类 + * @author lastwhisper + * @date 1/16/2020 + */ +public class TreeUtil { + + /** + * 根据数组创建二叉树 + * 一、[5,4,8,11,null,13,4,7,2,null,null,null,1] + * 5 + * / \ + * 4 8 + * / / \ + * 11 13 4 + * / \ \ + * 7 2 1 + * 二、[1,null,2,3] + * 1 + * \ + * 2 + * / + * 3 + * 参考 https://blog.csdn.net/lenfranky/article/details/84444816 + * @param array 数组 + */ + public static TreeNode createTree(Integer... array) { + if (array.length == 0) return new TreeNode(0); + Deque nodeQueue = new LinkedList<>(); + // 创建一个根节点 + TreeNode root = new TreeNode(array[0]); + nodeQueue.offer(root); + TreeNode current; + // 记录当前行节点的数量(注意不一定是2的幂,而是上一行中非空节点的数量乘2) + int lineNodeNum = 2; + // 记录当前行中数字在数组中的开始位置 + int startIndex = 1; + // 记录数组中剩余的元素的数量 + int restLength = array.length - 1; + + while (restLength > 0) { + // 只有最后一行可以不满,其余行必须是满的 +// // 若输入的数组的数量是错误的,直接跳出程序 +// if (restLength < lineNodeNum) { +// System.out.println("Wrong Input!"); +// return new TreeNode(0); +// } + for (int i = startIndex; i < startIndex + lineNodeNum; i = i + 2) { + // 说明已经将nums中的数字用完,此时应停止遍历,并可以直接返回root + if (i == array.length) return root; + current = nodeQueue.poll(); + if (array[i] != null) { + current.left = new TreeNode(array[i]); + nodeQueue.offer(current.left); + } + // 同上,说明已经将nums中的数字用完,此时应停止遍历,并可以直接返回root + if (i + 1 == array.length) return root; + if (array[i + 1] != null) { + current.right = new TreeNode(array[i + 1]); + nodeQueue.offer(current.right); + } + } + startIndex += lineNodeNum; + restLength -= lineNodeNum; + lineNodeNum = nodeQueue.size() * 2; + } + + return root; + } + + /** + * 二叉树层次遍历 + */ + public static List> levelOrder(TreeNode root) { + List> result = new ArrayList<>(); + if (root == null) + return result; + + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + // 遍历每层的数据 + int size = queue.size(); + List list = new ArrayList<>(); + while (size > 0) { + root = queue.poll(); + list.add(root.val); + if (root.left != null) { + queue.add(root.left); + } + if (root.right != null) { + queue.add(root.right); + } + size--; + } + result.add(list); + } + return result; + } + + /** + * 输出二叉树层次遍历的结果 + */ + public static void printLevelOrder(TreeNode root) { + PrintUtil.printLists(levelOrder(root)); + } + + public static void main(String[] args) { +// printLevelOrder(createTree(1, null, 2, 3)); + printLevelOrder(createTree(5, 4, 8, 11, null, 13, 4, 7, 2, null, null, null, 1)); + //printLevelOrder(createTree(1,2,3,null,4,5,null)); + } +} diff --git a/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TrieNode.java b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TrieNode.java new file mode 100644 index 00000000..21358912 --- /dev/null +++ b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TrieNode.java @@ -0,0 +1,34 @@ +package cn.cunchang.tree; + +public class TrieNode { + // 26个字母 + private final int R = 26; + // 不存储真实的值,TrieNode[]中不为null表示存在 + private TrieNode[] links; + private boolean isEnd; + + public TrieNode() { + links = new TrieNode[R]; + } + + + public boolean containsKey(char ch) { + return links[ch - 'a'] != null; + } + + public TrieNode get(char ch) { + return links[ch - 'a']; + } + + public void put(char ch, TrieNode node) { + links[ch - 'a'] = node; + } + + public void setEnd() { + isEnd = true; + } + + public boolean isEnd() { + return isEnd; + } +} \ No newline at end of file diff --git a/algorithms/leetcode2/linkedlist/pom.xml b/algorithms/leetcode2/linkedlist/pom.xml new file mode 100644 index 00000000..b3ee7d09 --- /dev/null +++ b/algorithms/leetcode2/linkedlist/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + linkedlist + cn.cucnhang + 1.0-SNAPSHOT + + + 8 + 8 + + + + + leetcode2-common + cn.cucnhang + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git "a/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/K\344\270\252\344\270\200\347\273\204\347\277\273\350\275\254\351\223\276\350\241\250_25_\345\233\260\351\232\276/Solution.java" "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/K\344\270\252\344\270\200\347\273\204\347\277\273\350\275\254\351\223\276\350\241\250_25_\345\233\260\351\232\276/Solution.java" new file mode 100644 index 00000000..52526c46 --- /dev/null +++ "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/K\344\270\252\344\270\200\347\273\204\347\277\273\350\275\254\351\223\276\350\241\250_25_\345\233\260\351\232\276/Solution.java" @@ -0,0 +1,69 @@ +package cn.cunchang.K个一组翻转链表_25_困难; + +import cn.cunchang.linkedlist.LinkedListUtil; +import cn.cunchang.linkedlist.ListNode; + +/** + * @author cunchang + * @date 2022/6/20 8:33 PM + */ +public class Solution { + + public ListNode reverseKGroup(ListNode head, int k) { + if (head == null) { + return null; + } + int step = 0; + ListNode result = null; // 返回结果 + ListNode current = head; // 当前起点 + ListNode next = current; // 下一个k起点 + ListNode preTail = null; // 上一次反转后的尾结点 + while (current != null) { + while (next != null && step < k) { + next = next.next; + step++; + } + // 剩余链表不够反转,就不反转了 + // next == null不能够代表"剩余链表不够反转",可能是刚好够反转 + if (step < k && preTail != null) { + preTail.next = current; + break; + } + + step = 0; + // 反转后返回头结点 + ListNode tail = reverse1(current, k); + if (preTail != null) { + preTail.next = tail; + } + if (preTail == null) { // 第一次反转的头结点 + result = tail; + } + preTail = current;//反转链表的尾结点 + + current = next; + } + return result; + } + + // 返回头 + public ListNode reverse1(ListNode head, int k) { + ListNode pre = null; + ListNode current = head; + ListNode next = null; + while (current != null && k > 0) { + next = current.next; + current.next = pre; + pre = current; + current = next; + k--; + } + return pre; + } + + public static void main(String[] args) { + ListNode listNode1 = new Solution().reverseKGroup( + LinkedListUtil.createListNode(1,2,3,4), 2); + LinkedListUtil.printListNode(listNode1); + } +} diff --git "a/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\344\270\244\344\270\244\344\272\244\346\216\245\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_24_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\344\270\244\344\270\244\344\272\244\346\216\245\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_24_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..8ddba5a7 --- /dev/null +++ "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\344\270\244\344\270\244\344\272\244\346\216\245\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_24_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,58 @@ +package cn.cunchang.两两交接链表中的节点_24_中等; + +import cn.cunchang.linkedlist.LinkedListUtil; +import cn.cunchang.linkedlist.ListNode; + +class Solution { + + public ListNode swapPairs(ListNode head) { + if (head == null || head.next == null) { + return head; + } + ListNode holder = head.next; + ListNode pre = null; + ListNode headTemp = head; + while (headTemp != null && headTemp.next != null) { + ListNode next = headTemp.next.next; + // 2的next执行1 + // 4的next执行3 + headTemp.next.next = headTemp; + if (pre != null) { + // 4的next执行3时,1指向4,而不是1指向3 + pre.next = headTemp.next; + } + // 当前节点next指向下下个节点;1指向3 + headTemp.next = next; + pre = headTemp; + headTemp = next; + } + return holder; + } + +// public ListNode swapPairs(ListNode head) { +// ListNode holder = new ListNode(-1); +// holder.next = head; +// ListNode virtual = holder; +// while (virtual.next != null && virtual.next.next != null) { +// ListNode start = virtual.next; +// ListNode end = virtual.next.next; +// // 虚拟节点的next指向2 +// virtual.next = end; +// // 1的next指向2的next,就是3,1.next=3 +// start.next = end.next; +// // 2的next指向1,2.next = 1 +// end.next = start; +// // 目前就是 -1,2,1,3,4,start=1 +// virtual = start; +// } +// return holder.next; +// } + + public static void main(String[] args) { + LinkedListUtil.printListNode(new Solution().swapPairs(LinkedListUtil.createListNode(1, 2, 3, 4))); + LinkedListUtil.printListNode(new Solution().swapPairs(LinkedListUtil.createListNode(1, 2, 3, 4, 5, 6))); + LinkedListUtil.printListNode(new Solution().swapPairs(LinkedListUtil.createListNode(1, 2, 3, 4, 5))); + LinkedListUtil.printListNode(new Solution().swapPairs(LinkedListUtil.createListNode(1))); + LinkedListUtil.printListNode(new Solution().swapPairs(LinkedListUtil.createListNode())); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..3406a2d6 --- /dev/null +++ "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,58 @@ +package cn.cunchang.反转链表_206_简单; + +import cn.cunchang.linkedlist.LinkedListUtil; +import cn.cunchang.linkedlist.ListNode; + +import java.util.Stack; + +class Solution { + + // 递归 +// public ListNode reverseList(ListNode head) { +// if (head == null || head.next == null) { +// return head; +// } +// // newHead其实就是最后一个节点,唯一的作用就是让函数调用方拿到这个反转后的单链表的头,原先的head节点现在是尾结点了 +// // 通过递归遍历链表,在遍历每一个节点的时候,让当前节点的下一个节点next指向当前节点,当前节点next指向null +// // 由于栈先进后出,所以其实是从后往前遍历的,所以不需要像正向遍历的时候那样,记录前指针、next指针 +// ListNode newHead = reverseList(head.next); +// head.next.next = head; +// head.next = null; +// return newHead; +// } + + // 栈 + public ListNode reverseList(ListNode head) { + if (head == null) { + return null; + } + ListNode newHead; + + Stack stack = new Stack<>(); + // head=>1->2->3->4->5 + // stack=4<-3<-2<-1 + while (head.next != null) { + stack.push(head); + head = head.next; + } + // 握住尾结点,将来它是首节点;等价递归里面的newHead,也可以不要直接返回head + newHead = head; + // stack=4<-3<-2<-1 + while (!stack.isEmpty()) { + // 把4弹出来,4->5;依次把321都弹出来 + ListNode current = stack.pop(); + // 5->4 + current.next.next = current; + // 4->null + current.next = null; + } + return newHead; + } + + public static void main(String[] args) { + ListNode listNode = LinkedListUtil.createListNode(1, 2, 3, 4, 5); + LinkedListUtil.printListNode(listNode); + LinkedListUtil.printListNode(new Solution().reverseList(listNode)); + } + +} diff --git "a/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..19d8a2f5 --- /dev/null +++ "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,22 @@ +package cn.cunchang.反转链表_206_简单; + + +import cn.cunchang.linkedlist.ListNode; + +class Solution2 { + + public ListNode reverseList(ListNode head) { + ListNode pre = null;//无法找到前一个节点,所以需要记录前一个节点 + ListNode current = head;// 当前节点 + + while (current != null) { + ListNode next = current.next;// next节点,防止current反转后找不到next了 + current.next = pre; + pre = current; + current = next; + } + + return pre; + } + +} diff --git "a/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..70bf5f86 --- /dev/null +++ "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,34 @@ +package cn.cunchang.合并两个有序链表_21_中等; + +import cn.cunchang.linkedlist.LinkedListUtil; +import cn.cunchang.linkedlist.ListNode; + +class Solution { + public ListNode mergeTwoLists(ListNode list1, ListNode list2) { + ListNode mergeList = new ListNode(-1); + ListNode mergeNode = mergeList; + while (list1 != null && list2 != null) { + if (list1.val >= list2.val) { + mergeNode.next = list2; + list2 = list2.next; + } else { + mergeNode.next = list1; + list1 = list1.next; + } + mergeNode = mergeNode.next; + } + if (list1 != null) { + mergeNode.next = list1; + } + if (list2 != null) { + mergeNode.next = list2; + } + return mergeList.next; + } + + public static void main(String[] args) { + ListNode list1 = LinkedListUtil.createListNode(1, 2, 4); + ListNode list2 = LinkedListUtil.createListNode(1, 3, 4); + LinkedListUtil.printListNode(new Solution().mergeTwoLists(list1, list2)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\233\236\346\226\207\351\223\276\350\241\250_234_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\233\236\346\226\207\351\223\276\350\241\250_234_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..ff87fe54 --- /dev/null +++ "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\233\236\346\226\207\351\223\276\350\241\250_234_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,48 @@ +package cn.cunchang.回文链表_234_简单; + +import cn.cunchang.linkedlist.LinkedListUtil; +import cn.cunchang.linkedlist.ListNode; + +class Solution {public boolean isPalindrome(ListNode head) { + if (head == null || head.next == null) { + return true; + } + ListNode fast = head, slow = head; + while (fast.next != null && fast.next.next != null) { + slow = slow.next; + fast = fast.next.next; + } + ListNode list1 = reverse(slow); + ListNode list2 = head; + while (list1 != null && list2 != null) { + if (list1.val != list2.val) { + return false; + } + list1 = list1.next; + list2 = list2.next; + } + + return true; +} + + public ListNode reverse(ListNode head) { + ListNode pre = null;//无法找到前一个节点,所以需要记录前一个节点 + ListNode current = head;// 当前节点 + while (current != null) { + ListNode next = current.next;// next节点,防止current反转后找不到next了 + current.next = pre; + pre = current; + current = next; + } + return pre; + } + + + public static void main(String[] args) { +// ListNode listNode = LinkedListUtil.createListNode(1, 2, 2, 1); +// ListNode listNode = LinkedListUtil.createListNode(1, 2, 3, 2, 1); + ListNode listNode = LinkedListUtil.createListNode(1, 1); + LinkedListUtil.printListNode(listNode); + System.out.println(new Solution().isPalindrome(listNode)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\346\216\222\345\272\217\351\223\276\350\241\250_148_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\346\216\222\345\272\217\351\223\276\350\241\250_148_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..157baf5e --- /dev/null +++ "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\346\216\222\345\272\217\351\223\276\350\241\250_148_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,61 @@ +package cn.cunchang.排序链表_148_中等; + +import cn.cunchang.linkedlist.LinkedListUtil; +import cn.cunchang.linkedlist.ListNode; + +class Solution { + public ListNode sortList(ListNode head) { + // 递归终止点 + if (head == null || head.next == null) { + return head; + } + // 1. 快慢指针法,遍历链表找到中间节点 + ListNode fast = middleBeforeNode(head); + // 2. 中间节点切断链表 + ListNode mid = fast.next;//直接用fast当中间节点也可以,但是为了切断链表,用next比较方便 + fast.next = null; + // 3. 分别用归并排序排左右子链表 + ListNode leftNode = sortList(head); + ListNode rightNode = sortList(mid); + // 4. 合并子链表 + return mergeTwoLists(leftNode, rightNode); + } + + public static ListNode middleBeforeNode(ListNode head) { + ListNode fast = head; + ListNode slow = head; + while (fast.next != null && fast.next.next != null) { + fast = fast.next.next; + slow = slow.next; + } + return slow; + } + + public ListNode mergeTwoLists(ListNode list1, ListNode list2) { + ListNode mergeList = new ListNode(-1); + ListNode mergeNode = mergeList; + while (list1 != null && list2 != null) { + if (list1.val >= list2.val) { + mergeNode.next = list2; + list2 = list2.next; + } else { + mergeNode.next = list1; + list1 = list1.next; + } + mergeNode = mergeNode.next; + } + if (list1 != null) { + mergeNode.next = list1; + } + if (list2 != null) { + mergeNode.next = list2; + } + return mergeList.next; + } + + public static void main(String[] args) { + LinkedListUtil.printListNode(new Solution(). + sortList(LinkedListUtil.createListNode(9, 8, 7, 6, 5, 4, 3, 2, 1))); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\347\233\270\344\272\244\351\223\276\350\241\250_160_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\347\233\270\344\272\244\351\223\276\350\241\250_160_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..d6f9e707 --- /dev/null +++ "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\347\233\270\344\272\244\351\223\276\350\241\250_160_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,44 @@ +package cn.cunchang.相交链表_160_简单; + +import cn.cunchang.linkedlist.ListNode; + +public class Solution { + public ListNode getIntersectionNode(ListNode headA, ListNode headB) { + // 计算ab的长度 + int lenA = 0, lenB = 0; + ListNode lenHeadA = headA; + ListNode lenHeadB = headB; + while (lenHeadA != null) { + lenA++; + lenHeadA = lenHeadA.next; + } + while (lenHeadB != null) { + lenB++; + lenHeadB = lenHeadB.next; + } + // 将ab头设置到相同位置 + int diff = Math.abs(lenA - lenB); + ListNode startHeadA = headA; + ListNode startHeadB = headB; + if (lenA > lenB) { + while (diff > 0) { + startHeadA = startHeadA.next; + diff--; + } + } else { + while (diff > 0) { + startHeadB = startHeadB.next; + diff--; + } + } + // 比较,有相同说明相交 + while (startHeadA != null && startHeadB != null) { + if (startHeadA == startHeadB) { + return startHeadA; + } + startHeadA = startHeadA.next; + startHeadB = startHeadB.next; + } + return null; + } +} \ No newline at end of file diff --git a/algorithms/leetcode2/other-algo/pom.xml b/algorithms/leetcode2/other-algo/pom.xml new file mode 100644 index 00000000..2f4ad098 --- /dev/null +++ b/algorithms/leetcode2/other-algo/pom.xml @@ -0,0 +1,19 @@ + + + + leetcode2 + cn.cucnhang + 1.0-SNAPSHOT + + 4.0.0 + + other-algo + + + 8 + 8 + + + \ No newline at end of file diff --git "a/algorithms/leetcode2/other-algo/src/main/java/cn/cunchang/LRU\347\274\223\345\255\230_146_\344\270\255\347\255\211/LRUCache.java" "b/algorithms/leetcode2/other-algo/src/main/java/cn/cunchang/LRU\347\274\223\345\255\230_146_\344\270\255\347\255\211/LRUCache.java" new file mode 100644 index 00000000..19e14ec9 --- /dev/null +++ "b/algorithms/leetcode2/other-algo/src/main/java/cn/cunchang/LRU\347\274\223\345\255\230_146_\344\270\255\347\255\211/LRUCache.java" @@ -0,0 +1,126 @@ +package cn.cunchang.LRU缓存_146_中等; + +import org.junit.Assert; + +import java.util.HashMap; + +/** + * @author cunchang + * @date 2022/7/4 10:28 AM + */ +class LRUCache { + + public static void main(String[] args) { + LRUCache lRUCache = new LRUCache(2); + lRUCache.put(2, 1); + lRUCache.put(3, 2); + Assert.assertEquals(2, lRUCache.get(3)); + Assert.assertEquals(1, lRUCache.get(2)); + lRUCache.put(4, 3); + Assert.assertEquals(1, lRUCache.get(2)); + Assert.assertEquals(-1, lRUCache.get(3)); + Assert.assertEquals(3, lRUCache.get(4)); + } + + // 要求"函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。" + // hashmap存储kv保证 get、put O(1)、linkedlist存储k保证淘汰队尾 + DoubleLinkedList list; + HashMap kv; + int capacity; + + /** + * 以 正整数 作为容量 capacity 初始化 LRU 缓存 + */ + public LRUCache(int capacity) { + this.capacity = capacity; + list = new DoubleLinkedList(); + kv = new HashMap<>(); + } + + /** + * 要求:如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 + * 实现: + * 1、直接从map里面get,不存在返回-1 + * 2、存在,将list里面的node节点删除,并加到队头 + */ + public int get(int key) { + Node node = kv.get(key); + if (node == null) { + return -1; + } + list.remove(node); + list.addFirst(node); + return node.v; + } + + /** + * 要求: + * 1、如果关键字 key 已经存在,则变更其数据值 value ; + * 2、如果不存在,则向缓存中插入该组 key-value 。 + * 3、如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。 + * 实现: + * 1、k在map中存在,直接覆盖 + * 2、k在map中不存在, + * - 如果插入关键字数量未超过 capacity,put到map,add到list + * - 超过了,走淘汰逻辑,移除list队尾的k,同时在map中删除k。然后继续put即可 + */ + public void put(int key, int value) { + Node node = kv.get(key); + if (node != null) { + list.remove(node); + list.addFirst(node); + node.v = value; + return; + } + if (kv.size() >= capacity) { + Node last = list.removeLast(); + kv.remove(last.k); + } + node = new Node(key, value); + kv.put(key, node); + list.addFirst(node); + } + + class DoubleLinkedList { + Node head; + Node tail; + + public DoubleLinkedList() { + head = new Node(0, 0); + tail = new Node(0, 0); + head.next = tail; + tail.prev = head; + } + + // 删除某个节点 + public void remove(Node node) { + node.prev.next = node.next; + node.next.prev = node.prev; + } + + // node节点插入 + public void addFirst(Node node) { + node.next = head.next;//构建node.next + node.prev = head; // 构建node.pre + head.next.prev = node;// 构建原head.pre + head.next = node;// 构建head.next + } + public Node removeLast() { + if (tail.prev == head) + return null; + Node last = tail.prev; + remove(last); + return last; + } + } + + static class Node { + int k, v; + Node prev, next; + + public Node(int k, int v) { + this.k = k; + this.v = v; + } + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/other-algo/src/main/java/cn/cunchang/LRU\347\274\223\345\255\230_146_\344\270\255\347\255\211/LRUCache2.java" "b/algorithms/leetcode2/other-algo/src/main/java/cn/cunchang/LRU\347\274\223\345\255\230_146_\344\270\255\347\255\211/LRUCache2.java" new file mode 100644 index 00000000..b799ea81 --- /dev/null +++ "b/algorithms/leetcode2/other-algo/src/main/java/cn/cunchang/LRU\347\274\223\345\255\230_146_\344\270\255\347\255\211/LRUCache2.java" @@ -0,0 +1,59 @@ +package cn.cunchang.LRU缓存_146_中等; + +import org.junit.Assert; + +import java.util.HashMap; +import java.util.LinkedList; + +class LRUCache2 { + + private int capacity; + + private LinkedList keyCache = new LinkedList<>(); + + private HashMap keyAndValueCache = new HashMap<>(); + + public LRUCache2(int capacity) { + this.capacity = capacity; + } + + public int get(int key) { + final Integer value = keyAndValueCache.get(key); + if (value == null) { + return -1; + } + keyCache.remove((Object)key); + keyCache.addLast(key); + return value; + } + + public void put(int key, int value) { + if (keyCache.contains(key)) { + keyCache.remove((Object)key); + keyCache.addLast(key); + keyAndValueCache.put(key, value); + return; + } + + if (keyCache.size() >= capacity) { + Integer k = keyCache.removeFirst(); + keyAndValueCache.remove(k); + } + keyCache.addLast(key); + keyAndValueCache.put(key, value); + } + + + public static void main(String[] args) { + LRUCache2 lRUCache = new LRUCache2(2); + lRUCache.put(2, 1); + lRUCache.put(3, 2); + Assert.assertEquals(2,lRUCache.get(3)); + Assert.assertEquals(1,lRUCache.get(2)); + lRUCache.put(4, 3); + Assert.assertEquals(1,lRUCache.get(2)); + Assert.assertEquals(-1,lRUCache.get(3)); + Assert.assertEquals(3,lRUCache.get(4)); + } + +} \ No newline at end of file diff --git a/algorithms/leetcode2/point/pom.xml b/algorithms/leetcode2/point/pom.xml new file mode 100644 index 00000000..deb07872 --- /dev/null +++ b/algorithms/leetcode2/point/pom.xml @@ -0,0 +1,15 @@ + + + 4.0.0 + + point + cn.cucnhang + 1.0-SNAPSHOT + + 8 + 8 + + + \ No newline at end of file diff --git "a/algorithms/leetcode2/point/src/main/java/cn/cunchang/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..c914c932 --- /dev/null +++ "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,42 @@ +package cn.cunchang.两数之和_II_输入有序数组_167_简单; + +import java.util.Arrays; + +class Solution { + /** + * 思考: + * ------------------------------------------------------------------- + * 思路: + * "非递减顺序排列"表示升序 + * p1指向头,p2指向尾;num[p1]+num[p2]和target比会有三种情况; + * num[p1]+num[p2]==target说明p1、p2就是两数之和 + * num[p1]+num[p2]>target说明p2大了,p2-1再试试 + * num[p1]+num[p2] target) { + p2--; + } else if (tmp < target) { + p1++; + } else { + break; + } + } + return new int[]{p1+1, p2+1}; + } + + public static void main(String[] args) { + int[] numbers = new int[]{2, 7, 11, 15}; + int target = 9; + System.out.println(Arrays.toString( + new Solution().twoSum(numbers, target))); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/point/src/main/java/cn/cunchang/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..a2ce97f2 --- /dev/null +++ "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,40 @@ +package cn.cunchang.合并两个有序数组_88_简单; + +class Solution { + /** + * 思考: + * ------------------------------------------------------------------- + * 思路: + * m为num1指针,n为num2指针,p=m+n+1为复制位置指针 + * num1、num2从后往前,最大复制到num1尾部 + * num1复制完了,把num2剩余复制到num1。num2复制完了,就结束了。 + * + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public void merge(int[] nums1, int m, int[] nums2, int n) { + // 记录复制的位置 + int p = m + n - 1; + m--; + n--; + while (m >= 0 && n >= 0) { + if (nums2[n] > nums1[m]) { + nums1[p] = nums2[n]; + n--; + } else { + nums1[p] = nums1[m]; + m--; + } + p--; + } + // 复制num2 + if (n >= 0) { + for (int i = n; i >= 0; i--) { + nums1[p] = nums2[i]; + p--; + } + } + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/point/src/main/java/cn/cunchang/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_\345\233\260\351\232\276/Solution1.java" "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_\345\233\260\351\232\276/Solution1.java" new file mode 100644 index 00000000..0f80d8a8 --- /dev/null +++ "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_\345\233\260\351\232\276/Solution1.java" @@ -0,0 +1,72 @@ +package cn.cunchang.最小覆盖子串_76_困难; + +class Solution1 { + /** + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 1、将s串中的所有子串与t串比较,取最短的子串 + * 2、s子串与t串比较的逻辑:数组sarr记录t字符串的频率,遍历s字符,删除sarr中记录t字符的频率 + * 最后遍历sarr查看t字符串的频率是否还存在,存在说明不是覆盖子串 + * + * 暴力解法,超时了 + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public String minWindow(String s, String t) { + if (s.length() < t.length()) { + return ""; //"a","aa" + } + if (s.equals(t)) { + return s; + } + int l = 0, r = 0; + String target = ""; + while (l <= s.length() && r <= s.length()) { + if (r - l >= t.length()) { + String sub = s.substring(l, r); + if (isSub(sub, t)) { + if ("".equals(target)) {// 第一次找到 + target = sub; + } + if (target.length() > sub.length()) { //第n次找到,要最优的 + target = sub; + } + l++; + r = l; + } + } + r++; + } + return target; + } + + private boolean isSub(String sub, String t) { + if (sub.length() < t.length()) { + return false; + } + int[] set = new int[128]; + for (char c : t.toCharArray()) { + set[c]++;//记录t字符 + } + for (char c : sub.toCharArray()) { + set[c]--;//删除t字符 + } + for (char c : t.toCharArray()) { + if (set[c] > 0) {// 说明有t字符没有被删除,即sub不完全包含t + return false; + } + } + + return true; + } + + public static void main(String[] args) { +// String s = "ADOBECODEBANC", t = "ABC"; +// System.out.println(new Solution().minWindow(s, t)); + String s = "obzcopzocynyrsgsarijyxnkpnukkrvzuwdjldxndmnvevpgmxrmvfwkutwekrffnloyqnntbdohyfqndhzyoykiripdzwiojyoznbtogjyfpouuxvumtewmmnqnkadvzrvouqfbbdiqremqzgevkbhyoznacqwbhtrcjwfkzpdstpjswnpiqxjhywjanhdwavajrhwtwzlrqwmombxcaijzevbtcfsdcuovckoalcseaesmhrrizcjgxkbartdtotpsefsrjmvksqyahpijsrppdqpvmuocofuunonybjivbjviyftsyiicbzxnwnrmvlgkzticetyfcvqcbjvbufdxgcmesdqnowzpshuwcseenwjqhgsdlxatamysrohfnixfprdsljyyfhrnnjsagtuihuczilgvtfcjwgdhpbixlzmakebszxbhrdibpoxiwztshwczamwnninzmqrmpsviydkptjzpktksrortapgpxwojofxeasoyvyprjoguhqobehugwdvtzlenrcttuitsiijswpogicjolfxhiscjggzzissfcnxnvgftxvbfzkukqrtalvktdjsodmtgzqtuyaqvvrbuexgwqzwduixzrpnvegddyyywaquxjxrnuzlmyipuqotkghfkpknqinoidifnfyczzonxydtqroazxhjnrxfbmtlqcsfhshjrxwqvblovaouxwempdrrplefnxmwrwfjtebrfnfanvvmtbzjesctdgbsfnpxlwihalyiafincfcwgdfkvhebphtxukwgjgplrntsuchyjjuqozakiglangxkttsczhnswjksnuqwflmumpexxrznzwxurrysaokwxxqkrggytvsgkyfjrewrcvntomnoazmzycjrjrqemimyhriyxgrzcfuqtjhvjtuhwfzhwpljzajitrhryaqchnuawbxhxrpvyqcvhpggrpplhychyulijhkglinibedauhvdydkqszdbzfkzbvhldstocgydnbfjkcnkfxcyyfbzmmyojgzmasccaahpdnzproaxnexnkamwmkmwslksfpwirexxtymkmojztgmfhydvlqtddewjvsrmyqjrpycbmndhupmdqqabiuelacuvxnhxgtpvrtwfgzpcrbhhtikbcqpctlxszgpfbgcsbaaiapmtsucocmpecgixshrrnhyrpalralbccnxvjzjllarqhznzghswqsnfuyywmzbopyjyauknxddgdthlabjqtwxpxwljvoxkpjjpfvccyikbbrpdsyvlxscuoofkecwtnfkvcnzbxkeabtdusyhrqklhaqreupakxkfzxgawqfwsaboszvlshwzhosojjotgyagygguzntrouhiweuomqptfjjqsxlbylhwtpssdlltgubczxslqjgxuqnmpynnlwjgmebrpokxjnbiltvbebyytnnjlcwyzignmhedwqbfdepqakrelrdfesqrumptwwgifmmbepiktxavhuavlfaqxqhreznbvvlakzeoomykkzftthoemqwliednfsqcnbexbimrvkdhllcesrlhhjsspvfupxwdybablotibypmjutclgjurbmhztboqatrdwsomnxnmocvixxvfiqwmednahdqhxjkvcyhpxxdmzzuyyqdjibvmfkmonfxmohhshpkhmntnoplphqyprveyfsmsxjfosmicdsjrieeytpnbhlsziwxnpmgoxneqbnufhfwrjbqcsdfarybzwaplmxckkgclvwqdbpumsmqkswmjwnkuqbicykoisqwoootrdpdvcuiuswfqmrkctsgrevcxnyncmivsxbpbxzxpwchiwtkroqisnmrbmefbmatmdknaklpgpyqlsccgunaibsloyqpnsibwuowebomrmcegejozypjzjunjmeygozcjqbnrpakdermjcckartbcppmbtkhkmmtcngteigjnxxyzaibtdcwutkvpwezisskfaeljmxyjwykwglqlnofhycwuivdbnpintuyhtyqpwaoelgpbuwiuyeqhbvkqlsfgmeoheexbhnhutxvnvfjwlzfmvpcghiowocdsjcvqrdmkcizxnivbianfpsnzabxqecinhgfyjrjlbikrrgsbgfgyxtzzwwpayapfgueroncpxogouyrdgzdfucfrywtywjeefkvtzxlwmrniselyeodysirqflpduvibfdvedgcrzpzrunpadvawfsmmddqzaaahfxlifobffbyzqqbtlcpquedzjvykvarayfldvmkapjcfzfbmhscdwhciecsbdledspgpdtsteuafzbrjuvmsfrajtulwirzagiqjdiehefmfifocadxfuxrpsemavncdxuoaetjkavqicgndjkkfhbvbhjdcygfwcwyhpirrfjziqonbyxhibelinpllxsjzoiifscwzlyjdmwhnuovvugfhvquuleuzmehggdfubpzolgbhwyeqekzccuypaspozwuhbzbdqdtejuniuuyagackubauvriwneeqfhtwkocuipcelcfrcjcymcuktegiikyosumeioatfcxrheklookaqekljtvtdwhxsteajevpjviqzudnjnqbucnfvkybggaybebljwcstmktgnipdyrxbgewqczzkaxmeazpzbjsntltjwlmuclxirwytvxgvxscztryubtjweehapvxrguzzsatozzjytnamfyiitreyxmanhzeqwgpoikcjlokebksgkaqetverjegqgkicsyqcktmwjwakivtsxjwrgakphqincqrxqhzbcnxljzwturmsaklhnvyungjrxaonjqomdnxpnvihmwzphkyuhwqwdboabepmwgyatyrgtboiypxfavbjtrgwswyvcqhzwibpisydtmltbkydhznbsvxktyfxopwkxzbftzknnwipghuoijrbgqnzovxckvojvsqqraffwowfvqvfcmiicwitrhxdeombgesxexedlakitfovtydxunqnwqqdeeekiwjnwoshqcsljiicgobbbuqakjdonjawgjlezdnqhfdqnmsuavxdpnfzwipmspiabveaarshzwxmirgkmfncvtdrdvfxkpxlkdokxgtwcskmjryyymcthfnkasinihaunohkxaibtsqelockaefjmsuolebtnepauwmrxutspjwaxbmahsjtkfkxlnszribmeofbkyvbjscjtqjakuwvcgunvnonvqbbggfshauqsyznokqbhowjusypfnecffenojfvlblgzntqzlrgzprvhqnpfrrkzxznieiuivajivzijsqijigtatifmbplzqahuidegfoobpymkputzamzvweiyvvzlwihgmmmrcburbgbsdxrfjsbiylitghgcpqjbevvgypxcybubyoijijrhuzcdijfybqbfowlookqmlnplbxvjjosfqviygqyhgamuwzjklbyzopkrnhbywtfoqomweldmlrhjqswctubiknzzvcztyehouvnyiqnvkufaobehxhrjvtisxjlxoumipzjarwvbsaegdkpbsjmpevjbewzuqnfhoohhmdjgfpmjzdmtmykqvtucptwfidpwtwffzolffzqfdearclkyeecuzabjeqhxpmfodsvisnpxrqowdawheydfyhoexvcmihdlzavtqlshdhdgjzpozvvackebhgqppvcrvymljfvooauxcjnbejdivikcoaugxwzsulgfqdtefpehbrlhaoqxwcancuvbqutnfbuygoemditeagmcveatgaikwflozgdhkyfqmjcruyyuemwbqwxyyfiwnvlmbovlmccaoguieu", + t = "cjgamyzjwxrgwedhsexosmswogckohesskteksqgrjonnrwhywxqkqmywqjlxnfrayykqotkzhxmbwvzstrcjfchvluvbaobymlrcgbbqaprwlsqglsrqvynitklvzmvlamqipryqjpmwhdcsxtkutyfoiqljfhxftnnjgmbpdplnuphuksoestuckgopnlwiyltezuwdmhsgzzajtrpnkkswsglhrjprxlvwftbtdtacvclotdcepuahcootzfkwqhtydwrgqrilwvbpadvpzwybmowluikmsfkvbebrxletigjjlealczoqnnejvowptikumnokysfjyoskvsxztnqhcwsamopfzablnrxokdxktrwqjvqfjimneenqvdxufahsshiemfofwlyiionrybfchuucxtyctixlpfrbngiltgtbwivujcyrwutwnuajcxwtfowuuefpnzqljnitpgkobfkqzkzdkwwpksjgzqvoplbzzjuqqgetlojnblslhpatjlzkbuathcuilqzdwfyhwkwxvpicgkxrxweaqevziriwhjzdqanmkljfatjifgaccefukavvsfrbqshhswtchfjkausgaukeapanswimbznstubmswqadckewemzbwdbogogcysfxhzreafwxxwczigwpuvqtathgkpkijqiqrzwugtr"; + System.out.println(new Solution1().minWindow(s, t)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/point/src/main/java/cn/cunchang/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_\345\233\260\351\232\276/Solution2.java" "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_\345\233\260\351\232\276/Solution2.java" new file mode 100644 index 00000000..3b80d759 --- /dev/null +++ "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_\345\233\260\351\232\276/Solution2.java" @@ -0,0 +1,49 @@ +package cn.cunchang.最小覆盖子串_76_困难; + +import java.util.HashMap; + +class Solution2 { + + public String minWindow(String s, String t) { + HashMap windows = new HashMap<>(); + // 记录字符串需要的字符以及数量 + HashMap need = new HashMap<>(); + for (int i = 0; i < t.length(); i++) { + char c = t.charAt(i); + need.put(c, need.getOrDefault(c, 0) + 1); + } + int l = 0, r = 0; + int valid = 0; + int start = 0, len = Integer.MAX_VALUE; + while (r < s.length()) { + char c = s.charAt(r); + // 扩大窗口 + r++; + + if (need.containsKey(c)) { + windows.put(c, windows.getOrDefault(c, 0) + 1); + if (windows.get(c).equals(need.get(c))) { + valid++; + } + } + + // s串窗口中寻找到的满足t串 + while (valid == need.size()) { + + } + + + } + + return null; + } + + + public static void main(String[] args) { + String s = "ADOBECODEBANC", t = "ABC"; + System.out.println(new Solution2().minWindow(s, t)); +// String s = "obzcopzocynyrsgsarijyxnkpnukkrvzuwdjldxndmnvevpgmxrmvfwkutwekrffnloyqnntbdohyfqndhzyoykiripdzwiojyoznbtogjyfpouuxvumtewmmnqnkadvzrvouqfbbdiqremqzgevkbhyoznacqwbhtrcjwfkzpdstpjswnpiqxjhywjanhdwavajrhwtwzlrqwmombxcaijzevbtcfsdcuovckoalcseaesmhrrizcjgxkbartdtotpsefsrjmvksqyahpijsrppdqpvmuocofuunonybjivbjviyftsyiicbzxnwnrmvlgkzticetyfcvqcbjvbufdxgcmesdqnowzpshuwcseenwjqhgsdlxatamysrohfnixfprdsljyyfhrnnjsagtuihuczilgvtfcjwgdhpbixlzmakebszxbhrdibpoxiwztshwczamwnninzmqrmpsviydkptjzpktksrortapgpxwojofxeasoyvyprjoguhqobehugwdvtzlenrcttuitsiijswpogicjolfxhiscjggzzissfcnxnvgftxvbfzkukqrtalvktdjsodmtgzqtuyaqvvrbuexgwqzwduixzrpnvegddyyywaquxjxrnuzlmyipuqotkghfkpknqinoidifnfyczzonxydtqroazxhjnrxfbmtlqcsfhshjrxwqvblovaouxwempdrrplefnxmwrwfjtebrfnfanvvmtbzjesctdgbsfnpxlwihalyiafincfcwgdfkvhebphtxukwgjgplrntsuchyjjuqozakiglangxkttsczhnswjksnuqwflmumpexxrznzwxurrysaokwxxqkrggytvsgkyfjrewrcvntomnoazmzycjrjrqemimyhriyxgrzcfuqtjhvjtuhwfzhwpljzajitrhryaqchnuawbxhxrpvyqcvhpggrpplhychyulijhkglinibedauhvdydkqszdbzfkzbvhldstocgydnbfjkcnkfxcyyfbzmmyojgzmasccaahpdnzproaxnexnkamwmkmwslksfpwirexxtymkmojztgmfhydvlqtddewjvsrmyqjrpycbmndhupmdqqabiuelacuvxnhxgtpvrtwfgzpcrbhhtikbcqpctlxszgpfbgcsbaaiapmtsucocmpecgixshrrnhyrpalralbccnxvjzjllarqhznzghswqsnfuyywmzbopyjyauknxddgdthlabjqtwxpxwljvoxkpjjpfvccyikbbrpdsyvlxscuoofkecwtnfkvcnzbxkeabtdusyhrqklhaqreupakxkfzxgawqfwsaboszvlshwzhosojjotgyagygguzntrouhiweuomqptfjjqsxlbylhwtpssdlltgubczxslqjgxuqnmpynnlwjgmebrpokxjnbiltvbebyytnnjlcwyzignmhedwqbfdepqakrelrdfesqrumptwwgifmmbepiktxavhuavlfaqxqhreznbvvlakzeoomykkzftthoemqwliednfsqcnbexbimrvkdhllcesrlhhjsspvfupxwdybablotibypmjutclgjurbmhztboqatrdwsomnxnmocvixxvfiqwmednahdqhxjkvcyhpxxdmzzuyyqdjibvmfkmonfxmohhshpkhmntnoplphqyprveyfsmsxjfosmicdsjrieeytpnbhlsziwxnpmgoxneqbnufhfwrjbqcsdfarybzwaplmxckkgclvwqdbpumsmqkswmjwnkuqbicykoisqwoootrdpdvcuiuswfqmrkctsgrevcxnyncmivsxbpbxzxpwchiwtkroqisnmrbmefbmatmdknaklpgpyqlsccgunaibsloyqpnsibwuowebomrmcegejozypjzjunjmeygozcjqbnrpakdermjcckartbcppmbtkhkmmtcngteigjnxxyzaibtdcwutkvpwezisskfaeljmxyjwykwglqlnofhycwuivdbnpintuyhtyqpwaoelgpbuwiuyeqhbvkqlsfgmeoheexbhnhutxvnvfjwlzfmvpcghiowocdsjcvqrdmkcizxnivbianfpsnzabxqecinhgfyjrjlbikrrgsbgfgyxtzzwwpayapfgueroncpxogouyrdgzdfucfrywtywjeefkvtzxlwmrniselyeodysirqflpduvibfdvedgcrzpzrunpadvawfsmmddqzaaahfxlifobffbyzqqbtlcpquedzjvykvarayfldvmkapjcfzfbmhscdwhciecsbdledspgpdtsteuafzbrjuvmsfrajtulwirzagiqjdiehefmfifocadxfuxrpsemavncdxuoaetjkavqicgndjkkfhbvbhjdcygfwcwyhpirrfjziqonbyxhibelinpllxsjzoiifscwzlyjdmwhnuovvugfhvquuleuzmehggdfubpzolgbhwyeqekzccuypaspozwuhbzbdqdtejuniuuyagackubauvriwneeqfhtwkocuipcelcfrcjcymcuktegiikyosumeioatfcxrheklookaqekljtvtdwhxsteajevpjviqzudnjnqbucnfvkybggaybebljwcstmktgnipdyrxbgewqczzkaxmeazpzbjsntltjwlmuclxirwytvxgvxscztryubtjweehapvxrguzzsatozzjytnamfyiitreyxmanhzeqwgpoikcjlokebksgkaqetverjegqgkicsyqcktmwjwakivtsxjwrgakphqincqrxqhzbcnxljzwturmsaklhnvyungjrxaonjqomdnxpnvihmwzphkyuhwqwdboabepmwgyatyrgtboiypxfavbjtrgwswyvcqhzwibpisydtmltbkydhznbsvxktyfxopwkxzbftzknnwipghuoijrbgqnzovxckvojvsqqraffwowfvqvfcmiicwitrhxdeombgesxexedlakitfovtydxunqnwqqdeeekiwjnwoshqcsljiicgobbbuqakjdonjawgjlezdnqhfdqnmsuavxdpnfzwipmspiabveaarshzwxmirgkmfncvtdrdvfxkpxlkdokxgtwcskmjryyymcthfnkasinihaunohkxaibtsqelockaefjmsuolebtnepauwmrxutspjwaxbmahsjtkfkxlnszribmeofbkyvbjscjtqjakuwvcgunvnonvqbbggfshauqsyznokqbhowjusypfnecffenojfvlblgzntqzlrgzprvhqnpfrrkzxznieiuivajivzijsqijigtatifmbplzqahuidegfoobpymkputzamzvweiyvvzlwihgmmmrcburbgbsdxrfjsbiylitghgcpqjbevvgypxcybubyoijijrhuzcdijfybqbfowlookqmlnplbxvjjosfqviygqyhgamuwzjklbyzopkrnhbywtfoqomweldmlrhjqswctubiknzzvcztyehouvnyiqnvkufaobehxhrjvtisxjlxoumipzjarwvbsaegdkpbsjmpevjbewzuqnfhoohhmdjgfpmjzdmtmykqvtucptwfidpwtwffzolffzqfdearclkyeecuzabjeqhxpmfodsvisnpxrqowdawheydfyhoexvcmihdlzavtqlshdhdgjzpozvvackebhgqppvcrvymljfvooauxcjnbejdivikcoaugxwzsulgfqdtefpehbrlhaoqxwcancuvbqutnfbuygoemditeagmcveatgaikwflozgdhkyfqmjcruyyuemwbqwxyyfiwnvlmbovlmccaoguieu", +// t = "cjgamyzjwxrgwedhsexosmswogckohesskteksqgrjonnrwhywxqkqmywqjlxnfrayykqotkzhxmbwvzstrcjfchvluvbaobymlrcgbbqaprwlsqglsrqvynitklvzmvlamqipryqjpmwhdcsxtkutyfoiqljfhxftnnjgmbpdplnuphuksoestuckgopnlwiyltezuwdmhsgzzajtrpnkkswsglhrjprxlvwftbtdtacvclotdcepuahcootzfkwqhtydwrgqrilwvbpadvpzwybmowluikmsfkvbebrxletigjjlealczoqnnejvowptikumnokysfjyoskvsxztnqhcwsamopfzablnrxokdxktrwqjvqfjimneenqvdxufahsshiemfofwlyiionrybfchuucxtyctixlpfrbngiltgtbwivujcyrwutwnuajcxwtfowuuefpnzqljnitpgkobfkqzkzdkwwpksjgzqvoplbzzjuqqgetlojnblslhpatjlzkbuathcuilqzdwfyhwkwxvpicgkxrxweaqevziriwhjzdqanmkljfatjifgaccefukavvsfrbqshhswtchfjkausgaukeapanswimbznstubmswqadckewemzbwdbogogcysfxhzreafwxxwczigwpuvqtathgkpkijqiqrzwugtr"; +// System.out.println(new Solution2().minWindow(s, t)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/point/src/main/java/cn/cunchang/\347\216\257\345\275\242\351\223\276\350\241\250_II_142_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\347\216\257\345\275\242\351\223\276\350\241\250_II_142_\344\270\255\347\255\211/Solution1.java" new file mode 100644 index 00000000..1a28128c --- /dev/null +++ "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\347\216\257\345\275\242\351\223\276\350\241\250_II_142_\344\270\255\347\255\211/Solution1.java" @@ -0,0 +1,42 @@ +package cn.cunchang.环形链表_II_142_中等; + +public class Solution1 { + /** + * 思考: + * ------------------------------------------------------------------- + * 思路: + *

+ * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public ListNode detectCycle(ListNode head) { + // 先找到相遇点 + ListNode fast = head, slow = head; + do { + // 说明不成环 + if (fast == null || fast.next == null) { + return null; + } + fast = fast.next.next; + slow = slow.next; + } while (fast != slow);// 说明成环 + // 再找成环点 + ListNode p1 = head, p2 = slow; + while (p1 != p2) { + p1 = p1.next; + p2 = p2.next; + } + return p1; + } + + class ListNode { + int val; + ListNode next; + + ListNode(int x) { + val = x; + next = null; + } + } +} \ No newline at end of file diff --git a/algorithms/leetcode2/pom.xml b/algorithms/leetcode2/pom.xml new file mode 100644 index 00000000..1f9885af --- /dev/null +++ b/algorithms/leetcode2/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + + cn.cucnhang + leetcode2 + pom + 1.0-SNAPSHOT + + leetcode2-common + sort + dynamic + backtracking + other-algo + + + + 8 + 8 + + + + + + junit + junit + 4.12 + + + \ No newline at end of file diff --git a/algorithms/leetcode2/sort/pom.xml b/algorithms/leetcode2/sort/pom.xml new file mode 100644 index 00000000..b2516fa4 --- /dev/null +++ b/algorithms/leetcode2/sort/pom.xml @@ -0,0 +1,25 @@ + + + + leetcode2 + cn.cucnhang + 1.0-SNAPSHOT + + 4.0.0 + + sort + + + 8 + 8 + + + + leetcode2-common + cn.cucnhang + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/BucketSort.java b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/BucketSort.java new file mode 100644 index 00000000..e08f47e1 --- /dev/null +++ b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/BucketSort.java @@ -0,0 +1,54 @@ +package cn.cunchang.sort; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; + +/** + * @author cunchang + * @date 2022/6/15 6:41 PM + */ +public class BucketSort { + + public static double[] bucketSort(double[] array) { + //第一步:找出待排序的数组中最大和最小的元素 + double max = array[0]; + double min = array[0]; + for (double i : array) { + if (i > max) { + max = i; + } + if (i < min) { + min = i; + } + } + double d = max - min; + //第二步:初始化桶 + int bucketNum = array.length; + ArrayList> bucketList = new ArrayList>(); + for (int i = 0; i < bucketNum; i++) { + bucketList.add(new LinkedList()); + } + //第三步:遍历原始数组,将每个元素放入桶中 + for (int i = 0; i < array.length; i++) { + // 定位元素属于第几个桶,是按照比例来定位:(array[i] - min) * (bucketNum-1) / d + int num = (int) ((array[i] - min) * (bucketNum - 1) / d); + bucketList.get(num).add(array[i]); + } + //第四步:对每个桶内的数据进行排序 + for (int i = 0; i < bucketList.size(); i++) { + Collections.sort(bucketList.get(i)); + } + //第五步:输入全部元素 + double[] sortArray = new double[array.length]; + int index = 0; + for (LinkedList list : bucketList) { + for (double element : list) { + sortArray[index] = element; + index++; + } + } + return sortArray; + } + +} diff --git a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/Heap1.java b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/Heap1.java new file mode 100644 index 00000000..c53463d0 --- /dev/null +++ b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/Heap1.java @@ -0,0 +1,100 @@ +package cn.cunchang.sort; + +import java.util.Arrays; + +public class Heap1 { + private int[] a; // 数组,从下标 1 开始存储数据 + private int n; // 堆可以存储的最大数据个数 + private int count; // 堆中已经存储的数据个数 + + public Heap1(int capacity) { + a = new int[capacity + 1]; + n = capacity; + count = 0; + } + + /** + * 插入 + */ + public void insert(int data) { + if (count >= n) return; // 堆满了 + ++count; + a[count] = data; + int i = count; + while (i / 2 > 0 && a[i] > a[i / 2]) { // 自下往上堆化 + swap(a, i, i / 2); // swap() 函数作用:交换下标为 i 和 i/2 的两个元素 + i = i / 2; + } + } + + /** + * 删除堆顶 + */ + public void removeMax() { + if (count == 0) return; // 堆中没有数据 + a[1] = a[count]; + --count; + heapify(a, count, 1); + } + + /** + * 堆化大顶堆 + * 自上往下堆化 + * + * @param arr 数组 + * @param n 堆中元素个数 + * @param i 待堆化的元素 + */ + private static void heapify(int[] arr, int n, int i) { + while (true) { + // 待堆化元素、左、右子树最大值的下标 + int maxPos = i; + // 待堆化元素小于左子树 + if (i * 2 <= n && arr[i] < arr[i * 2]) { + maxPos = i * 2; + } + // 待堆化元素左子树小于右子树, + if (i * 2 + 1 <= n && arr[maxPos] < arr[i * 2 + 1]) { + maxPos = i * 2 + 1; + } + // 最大元素是自己无需向下堆化 + if (maxPos == i) break; + // 最大元素不是自己,交互值 + swap(arr, i, maxPos); + // 将被交互的元素继续向下堆化 + i = maxPos; + } + } + + private static void buildHeap(int[] a, int n) { + // 对非叶子节点进行,自上往下堆化 + for (int i = n / 2; i >= 1; --i) { + heapify(a, n, i); + } + } + + // n 表示数据的个数,数组 a 中的数据从下标 1 到 n 的位置。 + public static void sort(int[] a, int n) { + buildHeap(a, n); + int k = n; + while (k > 1) { + swap(a, 1, k); + --k; + heapify(a, k, 1); + } + } + + private static void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + + public static void main(String[] args) { + int[] arr = new int[]{-99999, 9, 8, 7, 6, 5, 4, 3, 2, 1}; + System.out.println(Arrays.toString(arr)); + Heap1.sort(arr, arr.length - 1); + System.out.println(Arrays.toString(arr)); + } + +} \ No newline at end of file diff --git a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/Heap2.java b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/Heap2.java new file mode 100644 index 00000000..12fd37cb --- /dev/null +++ b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/Heap2.java @@ -0,0 +1,69 @@ +package cn.cunchang.sort; + +import java.util.Arrays; + +public class Heap2 { + + + /** + * 堆化大顶堆 + * 自上往下堆化 + * + * @param arr 数组 + * @param n 堆中元素个数 + * @param i 待堆化的元素 + */ + private static void heapify(int[] arr, int n, int i) { + while (true) { + // 待堆化元素、左、右子树最大值的下标 + int maxPos = i; + // 待堆化元素小于左子树 + if (i * 2 + 1 <= n && arr[i] < arr[i * 2 + 1]) { + maxPos = i * 2 + 1; + } + // 待堆化元素左子树小于右子树, + if (i * 2 + 2 <= n && arr[maxPos] < arr[i * 2 + 2]) { + maxPos = i * 2 + 2; + } + // 最大元素是自己无需向下堆化 + if (maxPos == i) break; + // 最大元素不是自己,交互值 + swap(arr, i, maxPos); + // 将被交互的元素继续向下堆化 + i = maxPos; + } + } + + private static void buildHeap(int[] a, int n) { + // 对非叶子节点进行,自上往下堆化 + for (int i = n / 2 - 1; i >= 0; --i) { + heapify(a, n, i); + } + } + + public static void sort(int[] arr, int n) { + // 1. 构建大顶堆 + buildHeap(arr, n); + int disorder = n; + // 2. 交换堆顶元素与末尾元素,调整堆结构 + while (disorder > 0) { + swap(arr, 0, disorder); + disorder--; + heapify(arr, disorder, 0); + } + } + + private static void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + + public static void main(String[] args) { + int[] arr = new int[]{9, 10, 7, 6, 5, 4, 3, 2, 1}; + System.out.println(Arrays.toString(arr)); + Heap2.sort(arr, arr.length - 1); + System.out.println(Arrays.toString(arr)); + } + +} \ No newline at end of file diff --git a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort1.java b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort1.java new file mode 100644 index 00000000..3cc792b0 --- /dev/null +++ b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort1.java @@ -0,0 +1,65 @@ +package cn.cunchang.sort; + +import java.util.Arrays; + +/** + * @author lastwhisper + */ +public class QuickSort1 { + public static void main(String[] args) { +// int[] arr = {2, 10, 8, 1000}; +// int[] arr = {-9, 78, 0, 23, -567, 70}; +// int[] arr = {-9, 78, 0, 23, 60, 70}; +// int[] arr = {9, 0, -567}; + int[] arr = {49, 38, 65, 97, 76, 13, 27}; + sort(arr, 0, arr.length - 1); + System.out.println(Arrays.toString(arr)); + } + + private static void sort(int[] arr, int left, int right) { + if (left >= right) return; + int pivotIdx = partition(arr, left, right); + // 此时分区pivotIdx左边值小于等于arr[pivotIdx],分区右边大于arr[pivotIdx] + // 对[left,pivotIdx - 1]再次分区 + sort(arr, left, pivotIdx - 1); + // 对[pivotIdx + 1,right]再次分区 + sort(arr, pivotIdx + 1, right); + } + + /** + * @param nums 待分区数组 + * @param left 待分区左边界 + * @param right 待分区右边界 + * @return pivotIdx 中轴索引 + */ + private static int partition(int[] nums, int left, int right) { + // 选最后一个值作为中轴 + int pivot = nums[left]; + // 所依right要减一 + int start = left + 1, end = right; + while (start <= end) { + // 寻找左边大于pivot + while (start <= end && nums[start] <= pivot) { + start++; + } + // 寻找右边小于等于pivot + while (start <= end && nums[end] > pivot) { + end--; + } + if (start < end) { + swap(nums, start, end); + } + } + // 此时[left+1,start-1]的值一定小于pivot=nums[left] + // left一定大于等于start,所以将start-1与left交互 + swap(nums, start - 1, left); + return start - 1; + } + + private static void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + +} diff --git a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort2.java b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort2.java new file mode 100644 index 00000000..6dc4c247 --- /dev/null +++ b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort2.java @@ -0,0 +1,62 @@ +package cn.cunchang.sort; + +import java.util.Arrays; + +/** + * @author lastwhisper + */ +public class QuickSort2 { + public static void main(String[] args) { +// int[] arr = {2, 10, 8, 1000}; + int[] arr = {49, 38, 65, 97, 76, 13, 27}; + sort(arr, 0, arr.length - 1); + System.out.println(Arrays.toString(arr)); + } + + private static void sort(int[] arr, int left, int right) { + if (left >= right) return; + int pivotIdx = partition(arr, left, right); + // 此时分区pivotIdx左边值小于等于arr[pivotIdx],分区右边大于arr[pivotIdx] + // 对[left,pivotIdx - 1]再次分区 + sort(arr, left, pivotIdx - 1); + // 对[pivotIdx + 1,right]再次分区 + sort(arr, pivotIdx + 1, right); + } + + /** + * @param nums 待分区数组 + * @param left 待分区左边界 + * @param right 待分区右边界 + * @return pivotIdx 中轴索引 + */ + private static int partition(int[] nums, int left, int right) { + // 选最后一个值作为中轴 + int pivot = nums[right]; + // 所依right要减一 + int start = left, end = right - 1; + while (start <= end) { + // 寻找左边大于pivot + while (start <= end && nums[start] <= pivot) { + start++; + } + // 寻找右边小于等于pivot + while (start <= end && nums[end] > pivot) { + end--; + } + if (start < end) { + swap(nums, start, end); + } + } + // 此时[left,start-1]的值一定小于pivot=nums[right] + // start一定大于right,所以将start与right交互 + swap(nums, start, right); + return start; + } + + private static void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + +} diff --git a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort3.java b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort3.java new file mode 100644 index 00000000..5e850ecb --- /dev/null +++ b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort3.java @@ -0,0 +1,73 @@ +package cn.cunchang.sort; + +import java.util.Arrays; +import java.util.Random; + +/** + * @author lastwhisper + */ +public class QuickSort3 { + private final static Random random = new Random(System.currentTimeMillis()); + + public static void main(String[] args) { +// int[] arr = {2, 10, 8, 1000}; +// int[] arr = {-9, 78, 0, 23, -567, 70}; +// int[] arr = {-9, 78, 0, 23, 60, 70}; +// int[] arr = {9, 0, -567}; + int[] arr = {49, 38, 65, 97, 76, 13, 27}; + sort(arr, 0, arr.length - 1); + System.out.println(Arrays.toString(arr)); + } + + private static void sort(int[] arr, int left, int right) { + if (left >= right) return; + int pivotIdx = partition(arr, left, right); + // 此时分区pivotIdx左边值小于等于arr[pivotIdx],分区右边大于arr[pivotIdx] + // 对[left,pivotIdx - 1]再次分区 + sort(arr, left, pivotIdx - 1); + // 对[pivotIdx + 1,right]再次分区 + sort(arr, pivotIdx + 1, right); + } + + /** + * @param nums 待分区数组 + * @param left 待分区左边界 + * @param right 待分区右边界 + * @return pivotIdx 中轴索引 + */ + private static int partition(int[] nums, int left, int right) { + int randomIndex = left + random.nextInt(right - left + 1); + swap(nums, left, randomIndex); + + // all in nums[left + 1..le) <= pivot; + // all in nums(ge..right] >= pivot; + int pivot = nums[left]; + int start = left + 1; + int end = right; + + while (true) { + while (start <= end && nums[start] < pivot) { + start++; + } + while (start <= end && nums[end] > pivot) { + end--; + } + if (start >= end) { + break; + } + swap(nums, start, end); + start++; + end--; + } + + swap(nums, left, end); + return end; + } + + private static void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + +} diff --git a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/README.md b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/README.md new file mode 100644 index 00000000..741b6e50 --- /dev/null +++ b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/README.md @@ -0,0 +1,7 @@ +快排 +QuickSort1 第一个元素做分区 +QuickSort2 最后一个元素做分区 +QuickSort3 随机一个元素做分区 +堆排序 +Heap1 数组第一个元素空出 +Heap2 数组第一个元素不空出 \ No newline at end of file diff --git "a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\345\211\215K\344\270\252\351\253\230\351\242\221\345\205\203\347\264\240_347_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\345\211\215K\344\270\252\351\253\230\351\242\221\345\205\203\347\264\240_347_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..4864a528 --- /dev/null +++ "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\345\211\215K\344\270\252\351\253\230\351\242\221\345\205\203\347\264\240_347_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,46 @@ +package cn.cunchang.前K个高频元素_347_中等; + +import cn.cunchang.array.ArrayUtil; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +class Solution { + + public int[] topKFrequent(int[] nums, int k) { + // 记录数字出现的频率 + Map freqMap = new HashMap<>(); + for (int num : nums) { + Integer freq = freqMap.get(num); + if (freq == null) { + freqMap.put(num, 1); + } else { + freqMap.put(num, ++freq); + } + } + // 记录最大频率 + int maxTime = 0; + for (Integer freq : freqMap.values()) { + if (freq > maxTime) { + maxTime = freq; + } + } + + int[] res = new int[k]; + while (k > 0) { + for (Map.Entry entry : freqMap.entrySet()) { + if (entry.getValue() == maxTime) { + res[--k] = entry.getKey(); + } + } + maxTime--; + } + return res; + } + + public static void main(String[] args) { + System.out.println(Arrays.toString(new Solution(). + topKFrequent(ArrayUtil.createArrays(1, 1, 1, 2, 2, 3), 2))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..691dc6f5 --- /dev/null +++ "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,65 @@ +package cn.cunchang.数组中的第K个最大元素_215_中等; + +import cn.cunchang.array.ArrayUtil; + +class Solution { + public int findKthLargest(int[] nums, int k) { + // topk的分区的位置 + int targetIdx = nums.length - k; + int left = 0, right = nums.length - 1; + + while (left <= right) { + // 中轴索引值 + int pivotIdx = partition(nums, left, right); + if (targetIdx > pivotIdx) { + // 说明要往右边分 + left = pivotIdx + 1; + } else if (targetIdx < pivotIdx) { + // 说明要往左边分 + right = pivotIdx - 1; + } else { + // 说明分区分到这个topk了 + return nums[pivotIdx]; + } + + } + return -1; + } + + private int partition(int[] nums, int left, int right) { + // 选最后一个值作为中轴 + int pivot = nums[right]; + // 所依right要减一 + int start = left, end = right - 1; + while (start <= end) { + // 寻找左边大于pivot + while (start <= end && nums[start] <= pivot) { + start++; + } + // 寻找右边小于等于pivot + while (start <= end && nums[end] > pivot) { + end--; + } + if (start <= end) { + swap(nums, start, end); + } + } + // 此时[left,start-1]的值一定小于pivot=nums[right] + // start一定大于right,所以将start与right交互 + swap(nums, start, right); + + return start; + } + + private void swap(int[] nums, int start, int end) { + int tmp = nums[start]; + nums[start] = nums[end]; + nums[end] = tmp; + } + + public static void main(String[] args) { + System.out.println(new Solution().findKthLargest(ArrayUtil.createArrays(2,1), 1)); +// System.out.println(new Solution().findKthLargest(ArrayUtil.createArrays(3, 2, 1, 5, 6, 4), 2)); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution2.java" new file mode 100644 index 00000000..a0c482e8 --- /dev/null +++ "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution2.java" @@ -0,0 +1,32 @@ +package cn.cunchang.数组中的第K个最大元素_215_中等; + +import cn.cunchang.array.ArrayUtil; + +import java.util.Comparator; +import java.util.PriorityQueue; + +class Solution2 { + public int findKthLargest(int[] nums, int k) { + PriorityQueue heap = new PriorityQueue<>(); + for (int num : nums) { + heap.add(num); + if (heap.size() > k) { + heap.poll(); + } + } + return heap.peek(); + } + + + private void swap(int[] nums, int start, int end) { + int tmp = nums[start]; + nums[start] = nums[end]; + nums[end] = tmp; + } + + public static void main(String[] args) { +// System.out.println(new Solution2().findKthLargest(ArrayUtil.createArrays(2, 1), 1)); + System.out.println(new Solution2().findKthLargest(ArrayUtil.createArrays(3, 2, 1, 5, 6, 4), 2)); + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\240\271\346\215\256\345\255\227\347\254\246\345\207\272\347\216\260\351\242\221\347\216\207\346\216\222\345\272\217_451_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\240\271\346\215\256\345\255\227\347\254\246\345\207\272\347\216\260\351\242\221\347\216\207\346\216\222\345\272\217_451_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..d63dbf1a --- /dev/null +++ "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\240\271\346\215\256\345\255\227\347\254\246\345\207\272\347\216\260\351\242\221\347\216\207\346\216\222\345\272\217_451_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,51 @@ +package cn.cunchang.根据字符出现频率排序_451_中等; + +import java.util.HashMap; +import java.util.Map; + +class Solution { + public String frequencySort(String s) { + // 记录字母出现的频率 + Map freqMap = new HashMap<>(); + for (int i = 0; i < s.length(); i++) { + Integer freq = freqMap.get(s.charAt(i)); + if (freq == null) { + freqMap.put(s.charAt(i), 1); + } else { + freqMap.put(s.charAt(i), ++freq); + } + } + // 记录最大频率 + int maxTime = 0; + for (Integer freq : freqMap.values()) { + if (freq > maxTime) { + maxTime = freq; + } + } + // 倒序记录出现频率最大的字母 + int size = freqMap.size(); + char[] charFreqOrder = new char[freqMap.size()]; + while (size > 0) { + for (Map.Entry entry : freqMap.entrySet()) { + if (entry.getValue() == maxTime) { + charFreqOrder[--size] = entry.getKey(); + } + } + maxTime--; + } + + StringBuilder sb = new StringBuilder(); + for (int i = charFreqOrder.length - 1; i >= 0; i--) { + Integer freq = freqMap.get(charFreqOrder[i]); + for (int j = 0; j < freq; j++) { + sb.append(charFreqOrder[i]); + } + } + return sb.toString(); + } + + public static void main(String[] args) { + System.out.println(new Solution().frequencySort("tree")); + System.out.println(new Solution().frequencySort("cccaaa")); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..901ce539 --- /dev/null +++ "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,28 @@ +package cn.cunchang.颜色分类_75_中等; + +import cn.cunchang.array.ArrayUtil; + +import java.util.Arrays; + +class Solution { + public void sortColors(int[] nums) { + // 下标表示对应数字,值表示频率 + int[] freq = new int[3]; + for (int num : nums) { + freq[num]++; + } + int idx = 0; + for (int i = 0; i < freq.length; i++) { + while (freq[i]-- > 0) { + // freq[i]表i这个数字出现了freq[i]次;freq[0]=2,说明0出现了两次 + nums[idx++] = i; + } + } + } + + public static void main(String[] args) { + int[] arrays = ArrayUtil.createArrays(2, 0, 2, 1, 1, 0); + new Solution().sortColors(arrays); + System.out.println(Arrays.toString(arrays)); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/README.md" "b/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/README.md" new file mode 100644 index 00000000..8a8ac1ea --- /dev/null +++ "b/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/README.md" @@ -0,0 +1,5 @@ + +Solution1;按照自己的思路写了一遍 +Solution2;精简代码;因为Solution1超时了,,,, +Solution3;备忘录优化 + diff --git "a/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution1.java" "b/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution1.java" new file mode 100644 index 00000000..90f9b691 --- /dev/null +++ "b/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution1.java" @@ -0,0 +1,78 @@ +package cn.cunchang.接雨水_42_困难; + +import org.junit.Assert; + +class Solution1 { + /** + * 题目地址:https://leetcode.cn/problems/container-with-most-water/ + * ------------------------------------------------------------------- + * 思考:只看局部柱子最多盛放水量 + * ------------------------------------------------------------------- + * 思路(磨刀不误砍柴工,先写思路,再写代码): + * 数组n个柱子,当前柱子i,每个柱子可 + * 1、遍历每个柱子,找每个柱子左右最高层数 + * 2、找i左右最高层数 + * (1)i=0 or i=n,左最高和右最高=0;第一个柱子和最后一个柱子不管多高,自身都无法盛水 + * (2)遍历[0,i),记录左最高层数 + * (3)遍历(i,n-1],记录右最高层数 + * 3、i可盛放水量计算 + * (1)如果左最高或右最高=0,说明当前柱子无法盛水,当前柱子盛水量=0 + * (2)i自身高度大于或等于左右高度,当前柱子盛水量=0 + * (3)i最多盛放水量=左右最高里面最低的哪个层数-当前柱子层数 + * 4、[0,n-1]对应盛水量汇总 + * ------------------------------------------------------------------- + * 时间复杂度:O(n^2) + * 空间复杂度:O(1) + */ + public int trap(int[] height) { + if (height == null || height.length == 0) { + return 0; + } + int count = 0; + for (int i = 0; i < height.length; i++) { + KV kv = getMax(i, height); + if (kv.leftMax == 0 || kv.rightMax == 0) { + continue; + } + if (height[i] >= kv.leftMax || height[i] >= kv.rightMax) { + continue; + } + int low = kv.leftMax > kv.rightMax ? kv.rightMax : kv.leftMax; + // i最多盛放水量 + count += low - height[i]; + } + return count; + } + + private KV getMax(int i, int[] height) { + int leftMax = 0; + for (int j = 0; j < i; j++) { + if (leftMax < height[j]) { + leftMax = height[j]; + } + } + int rightMax = 0; + for (int j = height.length - 1; j > i; j--) { + if (rightMax < height[j]) { + rightMax = height[j]; + } + } + return new KV(leftMax, rightMax); + } + + class KV { + int leftMax; + int rightMax; + + public KV(int leftMax, int rightMax) { + this.leftMax = leftMax; + this.rightMax = rightMax; + } + } + + public static void main(String[] args) { +// Assert.assertEquals(2, new Solution1().maxDistance(new int[][]{{1, 0, 1}, {0, 0, 0}, {1, 0, 1}})); + Solution1 solution1 = new Solution1(); + Assert.assertEquals(6, solution1.trap(new int[]{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1})); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution2.java" "b/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution2.java" new file mode 100644 index 00000000..d2f834c4 --- /dev/null +++ "b/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution2.java" @@ -0,0 +1,39 @@ +package cn.cunchang.接雨水_42_困难; + +import org.junit.Assert; + +class Solution2 { + /** + * 题目地址:https://leetcode.cn/problems/container-with-most-water/ + * ------------------------------------------------------------------- + * 思考:只看局部柱子最多盛放水量 + * ------------------------------------------------------------------- + * 思路:基于solution1,精简代码 + * ------------------------------------------------------------------- + * 时间复杂度:O(n^2) + * 空间复杂度:O(1) + */ + public int trap(int[] height) { + int count = 0; + for (int i = 1; i < height.length - 1; i++) { + int leftMax = 0, rightMax = 0; + // 左边最高,j <= i包含自己,后面不用判断小于的情况 + for (int j = 0; j <= i; j++) { + leftMax = Math.max(leftMax, height[j]); + } + // 右边最高,j >= i 包含自己 + for (int j = height.length - 1; j >= i; j--) { + rightMax = Math.max(rightMax, height[j]); + } + count += Math.min(leftMax, rightMax) - height[i]; + } + return count; + } + + public static void main(String[] args) { +// Assert.assertEquals(2, new Solution1().maxDistance(new int[][]{{1, 0, 1}, {0, 0, 0}, {1, 0, 1}})); + Solution2 solution2 = new Solution2(); + Assert.assertEquals(6, solution2.trap(new int[]{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1})); + + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution3.java" "b/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution3.java" new file mode 100644 index 00000000..28b4370c --- /dev/null +++ "b/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution3.java" @@ -0,0 +1,31 @@ +package cn.cunchang.接雨水_42_困难; + +import org.junit.Assert; + +class Solution3 { + /** + * 题目地址:https://leetcode.cn/problems/container-with-most-water/ + * ------------------------------------------------------------------- + * 思考:只看局部柱子最多盛放水量 + * ------------------------------------------------------------------- + * 思路:备忘录 + * + * 之前的暴力解法,不是在每个位置 i 都要计算 r_max 和 l_max 吗?我们直接把结果都提前计算出来,别傻不拉几的每次都遍历,这时间复杂度不就降下来了嘛。 + * + * 我们开两个数组 r_max 和 l_max 充当备忘录,l_max[i] 表示位置 i 左边最高的柱子高度,r_max[i] 表示位置 i 右边最高的柱子高度。预先把这两个数组计算好,避免重复计算: + * + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ + public int trap(int[] height) { + + + return 0; + } + + public static void main(String[] args) { + Solution3 solution = new Solution3(); + Assert.assertEquals(6, solution.trap(new int[]{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1})); + } +} \ No newline at end of file diff --git a/algorithms/leetcode2/tree/pom.xml b/algorithms/leetcode2/tree/pom.xml new file mode 100644 index 00000000..601f6b08 --- /dev/null +++ b/algorithms/leetcode2/tree/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + cn.cunchang + tree + 1.0-SNAPSHOT + + + 8 + 8 + + + + + leetcode2-common + cn.cucnhang + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\345\261\225\345\274\200\344\270\272\351\223\276\350\241\250_114_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\345\261\225\345\274\200\344\270\272\351\223\276\350\241\250_114_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..8ad66b91 --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\345\261\225\345\274\200\344\270\272\351\223\276\350\241\250_114_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,40 @@ +package cn.cunchang.二叉树展开为链表_114_中等; + +import cn.cunchang.tree.TreeNode; +import cn.cunchang.tree.TreeUtil; + +/** + * @author cunchang + * @date 2022/6/20 6:41 PM + */ +public class Solution { + + public void flatten(TreeNode root) { + if (root == null) { + return; + } + + flatten(root.left); + flatten(root.right); + // 原先左子树 + TreeNode left = root.left; + // 原先右子树 + TreeNode right = root.right; + // 将左子树作为当前节点的右子树 + root.left = null; + root.right = left; + // 将当前右子树(原先的左子树)的末端指向原先的右子树 + TreeNode p = root;//这里为什么是root?left行不行;left也可以,但是left可能为空需要判空 + while (p.right!=null){ + p = p.right; + } + // + p.right = right; + } + + public static void main(String[] args) { + TreeNode node = TreeUtil.createTree(1, 2, 5, 3, 4, null, 6); + new Solution().flatten(node); + TreeUtil.printLevelOrder(node); + } +} diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..e29285d9 --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,41 @@ +package cn.cunchang.二叉树的前序遍历_144_简单; + +import cn.cunchang.tree.TreeNode; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +class Solution { + + public List preorderTraversal(TreeNode root) { + List preOrder = new ArrayList<>(); + Stack stack = new Stack<>(); + stack.push(root); + while (!stack.isEmpty()) { + TreeNode treeNode = stack.pop(); + if (treeNode != null) { + preOrder.add(treeNode.val); + // 先进后出,保证left先执行 + stack.push(treeNode.right); + stack.push(treeNode.left); + } + } + return preOrder; + } + +// public List preorderTraversal(TreeNode root) { +// List preOrder = new ArrayList<>(); +// preorderTraversal(root, preOrder); +// return preOrder; +// } +// +// public void preorderTraversal(TreeNode root, List preOrder) { +// if (root == null) { +// return; +// } +// preOrder.add(root.val); +// preorderTraversal(root.left, preOrder); +// preorderTraversal(root.right, preOrder); +// } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\271\263\345\235\207\345\200\274_637_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\271\263\345\235\207\345\200\274_637_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..558eacd0 --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\271\263\345\235\207\345\200\274_637_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,38 @@ +package cn.cunchang.二叉树的层平均值_637_简单; + +import cn.cunchang.tree.TreeNode; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +class Solution { + public List averageOfLevels(TreeNode root) { + if (root == null) { + return new ArrayList<>(); + } + List resultList = new ArrayList<>(); + + Queue queue = new LinkedList<>(); + queue.offer(root); + + while (!queue.isEmpty()) { + double result = 0.0; + int levelCount = queue.size(); + for (int i = 0; i < levelCount; i++) { + TreeNode treeNode = queue.poll(); + result += treeNode.val; + if (treeNode.left != null) { + queue.offer(treeNode.left); + } + if (treeNode.right != null) { + queue.offer(treeNode.right); + } + } + resultList.add(result/levelCount); + } + return resultList; + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..b6292a02 --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,17 @@ +package cn.cunchang.二叉树的最大深度_104_简单; + + +import cn.cunchang.tree.TreeNode; + +class Solution { + public int maxDepth(TreeNode root) { + if (root == null) { + return 0; + } + + int leftDep = maxDepth(root.left); + int rightDep = maxDepth(root.right); + + return Math.max(leftDep, rightDep) + 1; + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..f23e92a9 --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,31 @@ +package cn.cunchang.二叉树的最大深度_104_简单; + + +import cn.cunchang.tree.TreeNode; + +class Solution2 { + int res = 0; + int depth = 0; + + public int maxDepth(TreeNode root) { + maxDepth2(root); + return res; + } + + public void maxDepth2(TreeNode root) { + if (root == null) { + return; + } + + // 进入节点深度增加 + depth++; + // 当前是最后一个节点了,记录一下最大位置 + if (root.left == null && root.right == null) { + res = Math.max(res, depth); + } + maxDepth(root.left); + maxDepth(root.right); + // 离开当前节点,深度减少 + depth--; + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\347\233\264\345\276\204_543_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\347\233\264\345\276\204_543_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..22fd643c --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\347\233\264\345\276\204_543_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,22 @@ +package cn.cunchang.二叉树的直径_543_简单; + +import cn.cunchang.tree.TreeNode; + +class Solution { + int res = 1; + + public int diameterOfBinaryTree(TreeNode root) { + diameterOfBinaryTree0(root); + return res - 1; + } + + public int diameterOfBinaryTree0(TreeNode root) { + if (root == null) { + return 0; + } + int leftDep = diameterOfBinaryTree0(root.left); + int rightDep = diameterOfBinaryTree0(root.right); + res = Math.max(leftDep + rightDep + 1, res); + return Math.max(leftDep, rightDep) + 1; + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\344\270\255\345\272\217\344\270\216\345\220\216\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_106_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\344\270\255\345\272\217\344\270\216\345\220\216\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_106_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..f82d684a --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\344\270\255\345\272\217\344\270\216\345\220\216\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_106_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,49 @@ +package cn.cunchang.从中序与后序遍历序列构造二叉树_106_中等; + +import cn.cunchang.array.ArrayUtil; +import cn.cunchang.tree.TreeNode; +import cn.cunchang.tree.TreeUtil; + +/** + * @author cunchang + * @date 2022/6/21 8:42 PM + */ +class Solution { + public TreeNode buildTree(int[] inorder, int[] postorder) { + return buildTree0(inorder, 0, inorder.length - 1, + postorder, 0, postorder.length - 1); + } + + public TreeNode buildTree0(int[] inorder, int inLeft, int inRight, + int[] postorder, int postLeft, int postRight) { + if (postLeft > postRight) { + return null; + } + // 找到根节点postRight,并构造根节点 + TreeNode treeNode = new TreeNode(postorder[postRight]); + // 找到根节点在inorder的下标index + int postOrderIndex = 0; + for (int i = inLeft; i <= inRight; i++) { + if (postorder[postRight] == inorder[i]) { + postOrderIndex = i; + break; + } + } + // 计算根节点右子树的节点数 + int leftCount = inRight - postOrderIndex; + // 递归构造根节点的右子树 + // 右子树在inorder[postOrderIndex+1,inRight],postorder[postRight-leftCount,postRight-1] + treeNode.right = buildTree0(inorder, postOrderIndex + 1, inRight, + postorder, postRight - leftCount , postRight-1); + // 递归构造根节点的左子树 + // 左子树在inorder[inLeft,postOrderIndex-1],postorder[postLeft,leftCount-1] + treeNode.left = buildTree0(inorder, inLeft, postOrderIndex - 1, + postorder, postLeft, postRight - leftCount - 1); + return treeNode; + } + + public static void main(String[] args) { + TreeUtil.printLevelOrder(new Solution().buildTree( + ArrayUtil.createArrays(9, 3, 15, 20, 7), ArrayUtil.createArrays(9, 15, 7, 20, 3))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\344\270\255\345\272\217\344\270\216\345\220\216\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_106_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\344\270\255\345\272\217\344\270\216\345\220\216\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_106_\344\270\255\347\255\211/Solution2.java" new file mode 100644 index 00000000..29350ce2 --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\344\270\255\345\272\217\344\270\216\345\220\216\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_106_\344\270\255\347\255\211/Solution2.java" @@ -0,0 +1,56 @@ +package cn.cunchang.从中序与后序遍历序列构造二叉树_106_中等; + +import cn.cunchang.array.ArrayUtil; +import cn.cunchang.tree.TreeNode; +import cn.cunchang.tree.TreeUtil; + +import java.util.HashMap; + +/** + * @author cunchang + * @date 2022/6/21 8:42 PM + */ +class Solution2 { + + public TreeNode buildTree(int[] inorder, int[] postorder) { + HashMap inorderIndexMap = new HashMap<>(); + for (int i = 0; i < inorder.length; i++) { + inorderIndexMap.put(inorder[i], i); + } + return buildTree0(inorder, 0, inorder.length - 1, + postorder, 0, postorder.length - 1, inorderIndexMap); + } + + public TreeNode buildTree0(int[] inorder, int inLeft, int inRight, + int[] postorder, int postLeft, int postRight, HashMap inorderIndexMap) { + if (postLeft > postRight) { + return null; + } + // 找到根节点postRight,并构造根节点 + TreeNode treeNode = new TreeNode(postorder[postRight]); + // 找到根节点在inorder的下标index + int postOrderIndex = inorderIndexMap.get(postorder[postRight]); +// for (int i = inLeft; i <= inRight; i++) { +// if (postorder[postRight] == inorder[i]) { +// postOrderIndex = i; +// break; +// } +// } + // 计算根节点右子树的节点数 + int leftCount = inRight - postOrderIndex; + // 递归构造根节点的右子树 + // 的右子树在在inorder[postOrderIndex+1,inRight],postorder[postRight-leftCount,postRight-1] + treeNode.right = buildTree0(inorder, postOrderIndex + 1, inRight, + postorder, postRight - leftCount, postRight - 1, inorderIndexMap); + // 递归构造根节点的左子树 + // 左子树在在inorder[inLeft,postOrderIndex-1],postorder[postLeft,leftCount-1] + treeNode.left = buildTree0(inorder, inLeft, postOrderIndex - 1, + postorder, postLeft, postRight - leftCount - 1, inorderIndexMap); + return treeNode; + } + + public static void main(String[] args) { + TreeUtil.printLevelOrder(new Solution2().buildTree( + ArrayUtil.createArrays(9, 3, 15, 20, 7), ArrayUtil.createArrays(9, 15, 7, 20, 3))); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\345\211\215\345\272\217\344\270\216\344\270\255\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_105_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\345\211\215\345\272\217\344\270\216\344\270\255\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_105_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..03f0a712 --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\345\211\215\345\272\217\344\270\216\344\270\255\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_105_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,51 @@ +package cn.cunchang.从前序与中序遍历序列构造二叉树_105_中等; + +import cn.cunchang.array.ArrayUtil; +import cn.cunchang.tree.TreeNode; +import cn.cunchang.tree.TreeUtil; + +/** + * @author cunchang + * @date 2022/6/20 6:41 PM + */ +class Solution { + + public TreeNode buildTree(int[] preorder, int[] inorder) { + return buildTree0(preorder, 0, preorder.length - 1, + inorder, 0, inorder.length - 1); + } + + public TreeNode buildTree0(int[] preorder, int preLeft, int preRight, + int[] inorder, int inLeft, int inRight) { + // 递归终止 + if (preLeft > preRight) { + return null; + } + + // 1、preLeft是preorder的根节点,对根节点进行构造 + TreeNode root = new TreeNode(preorder[preLeft]); + // 2、根节点在inorder的下标为index + int inOrderIndex = 0; + for (int i = inLeft; i <= inRight; i++) { + if (inorder[i] == preorder[preLeft]) { + inOrderIndex = i; + break; + } + } + // 3、根节点的左子树节点个数leftCount = index-inLeft,根节点左子树在preorder的范围[preLeft+1,preLeft+leftCount], + // 根节点已经构造过了,所以从preLeft+1开始,至左子树个数preLeft+leftCount结束; + // 在inorder的范围[inLeft,index-1] + int leftCount = inOrderIndex - inLeft; + root.left = buildTree0(preorder, preLeft + 1, preLeft + leftCount, + inorder, inLeft, inOrderIndex - 1); + // 4、根节点右子树在preorder的范围[preLeft+leftCount+1,preRight],在inorder的范围[index+1,inRight] + root.right = buildTree0(preorder, preLeft + leftCount + 1, preRight, + inorder, inOrderIndex + 1, inRight); + return root; + } + + public static void main(String[] args) { + TreeUtil.printLevelOrder(new Solution().buildTree( + ArrayUtil.createArrays(3, 9, 20, 15, 7), ArrayUtil.createArrays(9, 3, 15, 20, 7))); + } +} diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\210\240\347\202\271\346\210\220\346\236\227_1110_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\210\240\347\202\271\346\210\220\346\236\227_1110_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..7e88ddb3 --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\210\240\347\202\271\346\210\220\346\236\227_1110_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,66 @@ +package cn.cunchang.删点成林_1110_简单; + +import cn.cunchang.array.ArrayUtil; +import cn.cunchang.tree.TreeNode; +import cn.cunchang.tree.TreeUtil; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +class Solution { + List result = new ArrayList<>(); + + public List delNodes(TreeNode root, int[] to_delete) { + Set deleteSet = new HashSet<>(); + for (int deleteNum : to_delete) { + deleteSet.add(deleteNum); + } + // 根节点不需要删除,就加入到返回值,需要删除就不管了 + if (!deleteSet.contains(root.val)) { + result.add(root); + } + delNodes0(root, deleteSet); + return result; + } + + public boolean delNodes0(TreeNode root, Set deleteSet) { + if (root == null) { + return false; + } + + boolean leftDelete = delNodes0(root.left, deleteSet); + if (leftDelete) { + root.left = null; + } + boolean rightDelete = delNodes0(root.right, deleteSet); + if (rightDelete) { + root.right = null; + } + if (deleteSet.contains(root.val)) { + // 当前节点是需要删除的节点 + // 那么当前节点的左节点,不为空的话,就是一个单独的森林 + if (root.left != null) { + result.add(root.left); + } + // 当前节点的右节点,不为空的话,就是一个单独的森林 + if (root.right != null) { + result.add(root.right); + } + root.left = null; + root.right = null; + // 通知上层节点把自己删了 + return true; + } + return false; + } + + public static void main(String[] args) { + List treeNodeList = new Solution().delNodes(TreeUtil.createTree(1, 2, 3, 4, 5, 6, 7), + ArrayUtil.createArrays(3)); + for (TreeNode treeNode : treeNodeList) { + TreeUtil.printLevelOrder(treeNode); + } + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\241\253\345\205\205\346\257\217\344\270\252\350\212\202\347\202\271\347\232\204\344\270\213\344\270\200\344\270\252\345\217\263\344\276\247\350\212\202\347\202\271\346\214\207\351\222\210_116_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\241\253\345\205\205\346\257\217\344\270\252\350\212\202\347\202\271\347\232\204\344\270\213\344\270\200\344\270\252\345\217\263\344\276\247\350\212\202\347\202\271\346\214\207\351\222\210_116_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..1fa42bfa --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\241\253\345\205\205\346\257\217\344\270\252\350\212\202\347\202\271\347\232\204\344\270\213\344\270\200\344\270\252\345\217\263\344\276\247\350\212\202\347\202\271\346\214\207\351\222\210_116_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,48 @@ +package cn.cunchang.填充每个节点的下一个右侧节点指针_116_中等; + +/** + * @author cunchang + * @date 2022/6/20 6:33 PM + */ +public class Solution { + public Node connect(Node root) { + if (root == null) { + return null; + } + connect2(root.left, root.right); + return root; + } + + public void connect2(Node node1, Node node2) { + if (node1 == null || node2 == null) { + return; + } + node1.next = node2; + + connect2(node1.left,node1.right); + connect2(node2.left,node2.right); + // 跨节点相连 + connect2(node1.right,node2.left); + } + + class Node { + public int val; + public Node left; + public Node right; + public Node next; + + public Node() { + } + + public Node(int _val) { + val = _val; + } + + public Node(int _val, Node _left, Node _right, Node _next) { + val = _val; + left = _left; + right = _right; + next = _next; + } + } +} diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..4372bf7b --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,25 @@ +package cn.cunchang.对称二叉树_101_简单; + +import cn.cunchang.tree.TreeNode; + +class Solution { + public boolean isSymmetric(TreeNode root) { + if (root == null) { + return true; + } + return isSymmetric0(root.left, root.right); + } + + public boolean isSymmetric0(TreeNode p1, TreeNode p2) { + if (p1 == null && p2 == null) { + return true; + } + if (p1 == null || p2 == null) { + return false; + } + if (p1.val != p2.val) { + return false; + } + return isSymmetric0(p1.left, p2.right) && isSymmetric0(p1.right, p2.left); + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221_110_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221_110_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..09ce8f7e --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221_110_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,21 @@ +package cn.cunchang.平衡二叉树_110_简单; + +import cn.cunchang.tree.TreeNode; + +class Solution { + public boolean isBalanced(TreeNode root) { + return isBalanced0(root) != -1; + } + + public int isBalanced0(TreeNode root) { + if (root == null) { + return 0; + } + int leftDep = isBalanced0(root.left); + int rightDep = isBalanced0(root.right); + if (leftDep == -1 || rightDep == -1 || Math.abs(leftDep - rightDep) > 1) { + return -1; + } + return Math.max(leftDep, rightDep) + 1; + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\346\234\200\345\244\247\344\272\214\345\217\211\346\240\221_654_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\346\234\200\345\244\247\344\272\214\345\217\211\346\240\221_654_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..52cc6d44 --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\346\234\200\345\244\247\344\272\214\345\217\211\346\240\221_654_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,35 @@ +package cn.cunchang.最大二叉树_654_中等; + +import cn.cunchang.tree.TreeNode; + +/** + * @author cunchang + * @date 2022/6/20 7:50 PM + */ +class Solution { + public TreeNode constructMaximumBinaryTree(int[] nums) { + return constructMaximumBinaryTree0(nums, 0, nums.length - 1); + } + + public TreeNode constructMaximumBinaryTree0(int[] nums, int left, int right) { + if (left > right) { + return null; + } + // 找到最大值构造根节点 + int max = Integer.MIN_VALUE; + int index = -1; + for (int i = left; i <= right; i++) { + if (max < nums[i]) { + index = i; + max = nums[i]; + } + + } + TreeNode treeNode = new TreeNode(max); + // 再以最大值下标为界限,构造左右子树 + treeNode.left = constructMaximumBinaryTree0(nums, left, index - 1); + treeNode.right = constructMaximumBinaryTree0(nums, index + 1, right); + return treeNode; + } + +} \ No newline at end of file diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\346\240\271\346\215\256\345\211\215\345\272\217\345\222\214\345\220\216\345\272\217\351\201\215\345\216\206\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_889_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\346\240\271\346\215\256\345\211\215\345\272\217\345\222\214\345\220\216\345\272\217\351\201\215\345\216\206\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_889_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..bdb765a0 --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\346\240\271\346\215\256\345\211\215\345\272\217\345\222\214\345\220\216\345\272\217\351\201\215\345\216\206\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_889_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,25 @@ +package cn.cunchang.根据前序和后序遍历构造二叉树_889_中等; + +import cn.cunchang.tree.TreeNode; + +/** + * @author cunchang + * @date 2022/6/21 11:59 PM + */ +class Solution { + public TreeNode constructFromPrePost(int[] preorder, int[] postorder) { + return constructFromPrePost0(preorder, 0, preorder.length - 1, postorder, 0, postorder.length - 1); + } + + private TreeNode constructFromPrePost0(int[] preorder, int preLeft, int preRight, int[] postorder, int postLeft, int postRight) { + if (preLeft > preRight) { + return null; + } + // 构造根节点 + TreeNode root = new TreeNode(preorder[preLeft]); + // 把先序遍历的第二个值当做左子树 + + + return null; + } +} diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution.java" new file mode 100644 index 00000000..212b213c --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution.java" @@ -0,0 +1,42 @@ +package cn.cunchang.翻转二叉树_226_简单; + +import cn.cunchang.tree.TreeNode; + +/** + * @author cunchang + * @date 2022/6/20 6:28 PM + */ +class Solution { + public TreeNode invertTree(TreeNode root) { + invertTree2(root); + return root; + } + + /** + * 通过遍历解决 + */ + public void invertTree2(TreeNode root) { + if (root == null) { + return; + } + // 前序交换 + TreeNode tmp = root.left; + root.left = root.right; + root.right = tmp; + + invertTree2(root.left); + invertTree2(root.right); + } + +// public void invertTree2(TreeNode root) { +// if (root == null) { +// return; +// } +// invertTree2(root.left); +// invertTree2(root.right); +// // 后序交换 +// TreeNode tmp = root.left; +// root.left = root.right; +// root.right = tmp; +// } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution2.java" new file mode 100644 index 00000000..45ebe11a --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution2.java" @@ -0,0 +1,23 @@ +package cn.cunchang.翻转二叉树_226_简单; + +import cn.cunchang.tree.TreeNode; + +/** + * @author cunchang + * @date 2022/6/20 6:28 PM + */ +class Solution2 { + /** + * 通过分解解决 + */ + public TreeNode invertTree(TreeNode root) { + if (root == null) { + return null; + } + TreeNode left = invertTree(root.left); + TreeNode right = invertTree(root.right); + root.left = right; + root.right = left; + return root; + } +} \ No newline at end of file diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\350\267\257\345\276\204\346\200\273\345\222\214_III_437_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\350\267\257\345\276\204\346\200\273\345\222\214_III_437_\344\270\255\347\255\211/Solution.java" new file mode 100644 index 00000000..38ffe573 --- /dev/null +++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\350\267\257\345\276\204\346\200\273\345\222\214_III_437_\344\270\255\347\255\211/Solution.java" @@ -0,0 +1,38 @@ +package cn.cunchang.路径总和_III_437_中等; + +import cn.cunchang.tree.TreeNode; +import cn.cunchang.tree.TreeUtil; + +class Solution { + + public int pathSum(TreeNode root, int sum) { + if (root == null) { + return 0; + } + int res = findPathSum(root, sum); + res += pathSum(root.left, sum); + res += pathSum(root.right, sum); + return res; + } + + // 从node找到路径和等于sum的数量 + public int findPathSum(TreeNode node, int sum) { + if (node == null) { + return 0; + } + int res = 0; + sum -= node.val; + if (sum == 0) { + res++; + } + res += findPathSum(node.left, sum); + res += findPathSum(node.right, sum); + + return res; + } + + public static void main(String[] args) { + System.out.println(new Solution().pathSum( + TreeUtil.createTree(10, 5, -3, 3, 2, null, 11, 3, -2, null, 1), 8)); + } +} \ No newline at end of file diff --git a/algorithms/niuke/pom.xml b/algorithms/niuke/pom.xml new file mode 100644 index 00000000..4884603b --- /dev/null +++ b/algorithms/niuke/pom.xml @@ -0,0 +1,20 @@ + + + + algorithms + cn.lastwhisper + 1.0-SNAPSHOT + + 4.0.0 + + cn.cunchang + niuke + + + 8 + 8 + + + \ No newline at end of file diff --git a/algorithms/niuke/src/main/java/cn/cunchang/od/DemoMain1.java b/algorithms/niuke/src/main/java/cn/cunchang/od/DemoMain1.java new file mode 100644 index 00000000..492077e0 --- /dev/null +++ b/algorithms/niuke/src/main/java/cn/cunchang/od/DemoMain1.java @@ -0,0 +1,17 @@ +package cn.cunchang.od; + +// 本题为考试单行多行输入输出规范示例,无需提交,不计分。 + +import java.math.BigDecimal; +import java.util.Scanner; + +public class DemoMain1 { + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + while (in.hasNextInt()) {// 注意,如果输入是多个测试用例,请通过while循环处理多个测试用例 + BigDecimal a = in.nextBigDecimal(); + BigDecimal b = in.nextBigDecimal(); + System.out.println(a.add(b)); + } + } +} \ No newline at end of file diff --git a/algorithms/niuke/src/main/java/cn/cunchang/od/DemoMain2.java b/algorithms/niuke/src/main/java/cn/cunchang/od/DemoMain2.java new file mode 100644 index 00000000..ea59823c --- /dev/null +++ b/algorithms/niuke/src/main/java/cn/cunchang/od/DemoMain2.java @@ -0,0 +1,17 @@ +package cn.cunchang.od;// 本题为考试多行输入输出规范示例,无需提交,不计分。 +import java.util.Scanner; + +public class DemoMain2 { + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + int n = sc.nextInt(); + int ans = 0, x; + for(int i = 0; i < n; i++){ + for(int j = 0; j < n; j++){ + x = sc.nextInt(); + ans += x; + } + } + System.out.println(ans); + } +} \ No newline at end of file diff --git a/algorithms/niuke/src/main/java/cn/cunchang/od/Main1.java b/algorithms/niuke/src/main/java/cn/cunchang/od/Main1.java new file mode 100644 index 00000000..9ec563ab --- /dev/null +++ b/algorithms/niuke/src/main/java/cn/cunchang/od/Main1.java @@ -0,0 +1,47 @@ +package cn.cunchang.od; + + +import java.util.*; + +public class Main1 { + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + int xmH = sc.nextInt();//小明身高 + int N = sc.nextInt();// 同学数量 + + // 同学身高 + List hList = new ArrayList<>(N); + for (int i = 0; i < N; i++) { + hList.add(sc.nextInt()); + } + // 计算各个同学的身高差,按差升序,放到TreeMapList<差,同学身高list> + Map> diffSortMapList = new TreeMap<>(); + for (Integer height : hList) { + int subDiff = Math.abs(xmH - height); + List someList = diffSortMapList.get(subDiff); + if (someList == null || someList.isEmpty()) { + someList = new ArrayList<>(); + diffSortMapList.put(subDiff, someList); + } + someList.add(height); + } + + // 返回结果 + List result = new ArrayList<>(N); + + // 对同学身高list局部排序 + for (Map.Entry> entry : diffSortMapList.entrySet()) { + List someList = entry.getValue(); + Collections.sort(someList); + result.addAll(someList); + } + for (int i = 0; i < result.size(); i++) { + if (i == result.size() - 1) { + System.out.print(result.get(i)); + } else { + System.out.print(result.get(i) + " "); + } + } + } + +} \ No newline at end of file diff --git a/algorithms/niuke/src/main/java/cn/cunchang/od/Main2.java b/algorithms/niuke/src/main/java/cn/cunchang/od/Main2.java new file mode 100644 index 00000000..a514a449 --- /dev/null +++ b/algorithms/niuke/src/main/java/cn/cunchang/od/Main2.java @@ -0,0 +1,123 @@ +package cn.cunchang.od; + + +import java.util.*; + +public class Main2 { + // 映射与反映射 j=11,q=12,k=13,a=14 + static Map pokMap = new HashMap<>(); + static Map codeMap = new HashMap<>(); + + static { + pokMap.put("3", 0); + pokMap.put("4", 1); + pokMap.put("5", 2); + pokMap.put("6", 3); + pokMap.put("7", 4); + pokMap.put("8", 5); + pokMap.put("9", 6); + pokMap.put("10", 7); + pokMap.put("J", 8); + pokMap.put("Q", 9); + pokMap.put("K", 10); + pokMap.put("A", 11); + + codeMap.put(0, "3"); + codeMap.put(1, "4"); + codeMap.put(2, "5"); + codeMap.put(3, "6"); + codeMap.put(4, "7"); + codeMap.put(5, "8"); + codeMap.put(6, "9"); + codeMap.put(7, "10"); + codeMap.put(8, "J"); + codeMap.put(9, "Q"); + codeMap.put(10, "K"); + codeMap.put(11, "A"); + } + + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + String my = sc.nextLine();//我的手牌 + String show = sc.nextLine();//别人打了的 + + // 顺子【3,14】不能有 2、大小王 + + // 统计my和show里面的牌频率 + String[] mySplit = my.split("-"); + String[] showSplit = show.split("-"); + + int[] freqs = new int[12];//12种可以构成顺子的牌 + for (String myPok : mySplit) { + Integer pokCode = pokMap.get(myPok); + freqs[pokCode]++; + } + for (String showPok : showSplit) { + Integer pokCode = pokMap.get(showPok); + freqs[pokCode]++; + } + // 找到四张牌 + List fourIdxList = new ArrayList<>(); + for (int i = 0; i < freqs.length; i++) { + if (freqs[i] == 4) { + fourIdxList.add(i); + } + } + + fourIdxList.add(12);//保证结尾扑克也会被扫到,偷懒写法 + + List orderList = new ArrayList<>(); + + // 顺子12张:0,1,2,3,4,5,6,7,8,9,10,11 + int preIdx = 0; + int orderMax = 0;//顺子最大个数 + + // 构成顺子的 + for (Integer fourIdx : fourIdxList) { + // 0~fourIdx-1;fourIdx+1~fourIdx-1; + int subOrderCount = fourIdx - preIdx; + if (subOrderCount >= 5) {//构成顺子 + orderList.add(new KV(preIdx, fourIdx - 1)); + orderMax = Math.max(subOrderCount, orderMax); + } + + preIdx = fourIdx + 1; + } + + // 找到四张牌,在【3,14】的位置,没有直接返回【3,A】 + +// if (fourIdxList.isEmpty()) { +// orderList.add(new KV(0, 11)); +// orderMax = 11; +// } + + int start = -1, end = -1; + for (KV kv : orderList) { + if (kv.v - kv.k == orderMax-1) {//减1是因为这里的kv是两个闭区间 + start = kv.k; + end = kv.v; + } + } + if (start == -1) { + System.out.println("NO-CHAIN"); + } else { + for (int i = start; i <= end; i++) { + if (i == end) { + System.out.print(codeMap.get(i)); + } else { + System.out.print(codeMap.get(i) + "-"); + } + } + } + } + + static class KV { + public int k; + public int v; + + public KV(int k, int v) { + this.k = k; + this.v = v; + } + } +} \ No newline at end of file diff --git a/algorithms/niuke/src/main/java/cn/cunchang/od/Main3.java b/algorithms/niuke/src/main/java/cn/cunchang/od/Main3.java new file mode 100644 index 00000000..4eb9be04 --- /dev/null +++ b/algorithms/niuke/src/main/java/cn/cunchang/od/Main3.java @@ -0,0 +1,87 @@ +package cn.cunchang.od; + + +import java.util.Scanner; + +public class Main3 { + + static int n; + static int m; + + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + n = sc.nextInt(); + m = sc.nextInt(); + // 邻接矩阵 + int[][] arrs = new int[n][m]; + boolean[][] visited = new boolean[n][m]; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + arrs[i][j] = sc.nextInt(); + } + } + + int res = 0; + + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (!visited[i][j]) { + int subResult = helper(arrs, visited, i, j); + res = Math.max(subResult, res); + } + } + } + System.out.println(res); + } + + private static int helper(int[][] arrs, boolean[][] visited, int i, int j) { + if (i < 0 || i >= n || j < 0 || j >= m) { + return 0; + } + if (visited[i][j] || arrs[i][j] != 1) { + return 0; + } + visited[i][j] = true; + int subRes = helper(arrs, visited, i + 1, j) //下 + + helper(arrs, visited, i - 1, j) // 上 + + helper(arrs, visited, i, j - 1) // 左 + + helper(arrs, visited, i, j + 1); //右 + return subRes + 1; + } + + +// public static void main(String[] args) { +// Scanner sc = new Scanner(System.in); +// int n = sc.nextInt(); +// int m = sc.nextInt(); +// // 邻接矩阵 +// int[][] arrs = new int[n][m]; +// boolean[] visited = new boolean[n]; +// for (int i = 0; i < n; i++) { +// for (int j = 0; j < m; j++) { +// arrs[i][j] = sc.nextInt(); +// } +// } +// for (int i = 0; i < n; i++) { +// if (!visited[i]) { +// helper(arrs, visited, i); +// res++; +// } +// } +// System.out.println(res); +// } +// +// public static void helper(int[][] arrs, boolean[] visited, int idx) { +// if (idx >= arrs.length) { +// return; +// } +// if (visited[idx]) { +// return; +// } +// visited[idx] = true; +// for (int i = 0; i < idx; i++) { +// helper(arrs, visited, i); +// } +// } + +} \ No newline at end of file diff --git a/algorithms/niuke/src/main/java/cn/cunchang/scanner/Main.java b/algorithms/niuke/src/main/java/cn/cunchang/scanner/Main.java new file mode 100644 index 00000000..3cab137d --- /dev/null +++ b/algorithms/niuke/src/main/java/cn/cunchang/scanner/Main.java @@ -0,0 +1,18 @@ +package cn.cunchang.scanner; + +import java.util.Scanner; + +public class Main { + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + int n = sc.nextInt(); + int ans = 0, x; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + x = sc.nextInt(); + ans += x; + } + } + System.out.println(ans); + } +} \ No newline at end of file diff --git "a/algorithms/niuke/src/main/java/cn/cunchang/\346\262\241\346\234\211\351\207\215\345\244\215\351\241\271\346\225\260\345\255\227\347\232\204\345\205\250\346\216\222\345\210\227_BM55/Solution.java" "b/algorithms/niuke/src/main/java/cn/cunchang/\346\262\241\346\234\211\351\207\215\345\244\215\351\241\271\346\225\260\345\255\227\347\232\204\345\205\250\346\216\222\345\210\227_BM55/Solution.java" new file mode 100644 index 00000000..86cbd2b8 --- /dev/null +++ "b/algorithms/niuke/src/main/java/cn/cunchang/\346\262\241\346\234\211\351\207\215\345\244\215\351\241\271\346\225\260\345\255\227\347\232\204\345\205\250\346\216\222\345\210\227_BM55/Solution.java" @@ -0,0 +1,46 @@ +package cn.cunchang.没有重复项数字的全排列_BM55; + +import java.util.ArrayList; +import java.util.LinkedList; + +/** + * @author cunchang + * @date 2022/6/29 6:47 PM + */ +public class Solution { + ArrayList> result = new ArrayList<>(); + + public ArrayList> permute(int[] num) { + // 记录「路径」 + LinkedList subResult = new LinkedList<>(); + // 「路径」中的元素会被标记为 true,避免重复使用 + boolean[] visited = new boolean[num.length]; + permute0(num, subResult, visited); + return result; + } + + private void permute0(int[] num, LinkedList subResult, boolean[] visited) { + // 回溯结束,记录结果 + if (num.length == subResult.size()) { + result.add(new ArrayList<>(subResult)); + } + // 遍历选择列表 + for (int i = 0; i < num.length; i++) { + if (visited[i]) { + continue; + } + // 选择值 + subResult.add(num[i]); + visited[i] = true; + permute0(num, subResult, visited); + // 撤销选择 + subResult.removeLast(); + visited[i] = false; + } + } + + public static void main(String[] args) { + System.out.println(new Solution().permute(new int[]{1, 2, 3})); + } + +} \ No newline at end of file diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23007_\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221_\344\270\255\347\255\211/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23007_\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221_\344\270\255\347\255\211/Solution1.java" index 41c01344..8bdbec40 100644 --- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23007_\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23007_\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221_\344\270\255\347\255\211/Solution1.java" @@ -1,7 +1,7 @@ package cn.lastwhisper.offer.面试题07_重建二叉树_中等; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; class Solution1 { /** @@ -50,6 +50,6 @@ private TreeNode construct(int[] pre, int[] in, int pStart, int pEnd, int iStart public static void main(String[] args) { int[] preorder = {3, 9, 20, 15, 7}, inorder = {9, 3, 15, 20, 7}; - TreeUtils.printLevelOrder(new Solution1().buildTree(preorder, inorder)); + TreeUtil.printLevelOrder(new Solution1().buildTree(preorder, inorder)); } } \ No newline at end of file diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23012_\347\237\251\351\230\265\344\270\255\347\232\204\350\267\257\345\276\204_\344\270\255\347\255\211/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23012_\347\237\251\351\230\265\344\270\255\347\232\204\350\267\257\345\276\204_\344\270\255\347\255\211/Solution1.java" index ebe32a67..5ba13063 100644 --- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23012_\347\237\251\351\230\265\344\270\255\347\232\204\350\267\257\345\276\204_\344\270\255\347\255\211/Solution1.java" +++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23012_\347\237\251\351\230\265\344\270\255\347\232\204\350\267\257\345\276\204_\344\270\255\347\255\211/Solution1.java" @@ -1,6 +1,6 @@ package cn.lastwhisper.offer.面试题12_矩阵中的路径_中等; -import cn.lastwhisper.leetcode.common.matrix.ArrayUtils; +import cn.lastwhisper.leetcode.common.array.ArrayUtil; class Solution1 { @@ -90,6 +90,6 @@ public static void main(String[] args) { //String word = "ABCCED"; String[][] board = new String[][]{{"a", "b"}, {"c", "d"}}; String word = "abcd"; - System.err.println(new Solution1().exist(ArrayUtils.createCharArrays(board), word)); + System.err.println(new Solution1().exist(ArrayUtil.createCharArrays(board), word)); } } \ No newline at end of file diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23026_\346\240\221\347\232\204\345\255\220\347\273\223\346\236\204/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23026_\346\240\221\347\232\204\345\255\220\347\273\223\346\236\204/Solution1.java" index 75aa1f36..863b39a9 100644 --- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23026_\346\240\221\347\232\204\345\255\220\347\273\223\346\236\204/Solution1.java" +++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23026_\346\240\221\347\232\204\345\255\220\347\273\223\346\236\204/Solution1.java" @@ -1,7 +1,7 @@ package cn.lastwhisper.offer.面试题26_树的子结构; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; class Solution1 { /** @@ -49,8 +49,8 @@ private boolean compare(TreeNode root1, TreeNode root2) { public static void main(String[] args) { //TreeNode A = TreeUtils.createTree(1, 2, 3); //TreeNode B = TreeUtils.createTree(3, 1); - TreeNode A = TreeUtils.createTree(3, 4, 5, 1, 2); - TreeNode B = TreeUtils.createTree(4, 1); + TreeNode A = TreeUtil.createTree(3, 4, 5, 1, 2); + TreeNode B = TreeUtil.createTree(4, 1); System.out.println(new Solution1().isSubStructure(A, B)); } } \ No newline at end of file diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23027_\344\272\214\345\217\211\346\240\221\347\232\204\351\225\234\345\203\217/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23027_\344\272\214\345\217\211\346\240\221\347\232\204\351\225\234\345\203\217/Solution1.java" index 12a910e3..cf03f38d 100644 --- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23027_\344\272\214\345\217\211\346\240\221\347\232\204\351\225\234\345\203\217/Solution1.java" +++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23027_\344\272\214\345\217\211\346\240\221\347\232\204\351\225\234\345\203\217/Solution1.java" @@ -1,7 +1,7 @@ package cn.lastwhisper.offer.面试题27_二叉树的镜像; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; class Solution1 { /** @@ -27,7 +27,7 @@ public TreeNode mirrorTree(TreeNode root) { } public static void main(String[] args) { - TreeNode tree = TreeUtils.createTree(4, 2, 7, 1, 3, 6, 9); - TreeUtils.printLevelOrder(new Solution1().mirrorTree(tree)); + TreeNode tree = TreeUtil.createTree(4, 2, 7, 1, 3, 6, 9); + TreeUtil.printLevelOrder(new Solution1().mirrorTree(tree)); } } \ No newline at end of file diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23028_\345\257\271\347\247\260\347\232\204\344\272\214\345\217\211\346\240\221/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23028_\345\257\271\347\247\260\347\232\204\344\272\214\345\217\211\346\240\221/Solution1.java" index d17e7cc7..e2d01313 100644 --- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23028_\345\257\271\347\247\260\347\232\204\344\272\214\345\217\211\346\240\221/Solution1.java" +++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23028_\345\257\271\347\247\260\347\232\204\344\272\214\345\217\211\346\240\221/Solution1.java" @@ -1,7 +1,7 @@ package cn.lastwhisper.offer.面试题28_对称的二叉树; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; class Solution1 { /** @@ -36,6 +36,6 @@ private boolean isSymmetric(TreeNode root1, TreeNode root2) { } public static void main(String[] args) { - System.out.println(new Solution1().isSymmetric(TreeUtils.createTree(1, 2, 2, 3, 4, 4, 3))); + System.out.println(new Solution1().isSymmetric(TreeUtil.createTree(1, 2, 2, 3, 4, 4, 3))); } } \ No newline at end of file diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_III_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221III/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_III_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221III/Solution1.java" index 66709343..d9cab9f4 100644 --- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_III_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221III/Solution1.java" +++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_III_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221III/Solution1.java" @@ -1,8 +1,8 @@ package cn.lastwhisper.offer.面试题32_III_从上到下打印二叉树III; -import cn.lastwhisper.leetcode.common.print.PrintUtils; +import cn.lastwhisper.leetcode.common.print.PrintUtil; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; import java.util.ArrayList; import java.util.LinkedList; @@ -47,6 +47,6 @@ public List> levelOrder(TreeNode root) { } public static void main(String[] args) { - PrintUtils.printLists(new Solution1().levelOrder(TreeUtils.createTree(3, 9, 20, null, null, 15, 7))); + PrintUtil.printLists(new Solution1().levelOrder(TreeUtil.createTree(3, 9, 20, null, null, 15, 7))); } } \ No newline at end of file diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_II_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221II/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_II_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221II/Solution1.java" index 3dd0f11f..bb031ef7 100644 --- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_II_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221II/Solution1.java" +++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_II_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221II/Solution1.java" @@ -1,9 +1,8 @@ package cn.lastwhisper.offer.面试题32_II_从上到下打印二叉树II; -import cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil; -import cn.lastwhisper.leetcode.common.print.PrintUtils; +import cn.lastwhisper.leetcode.common.print.PrintUtil; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; import java.util.ArrayList; import java.util.LinkedList; @@ -43,6 +42,6 @@ public List> levelOrder(TreeNode root) { } public static void main(String[] args) { - PrintUtils.printLists(new Solution1().levelOrder(TreeUtils.createTree(3,9,20,null,null,15,7))); + PrintUtil.printLists(new Solution1().levelOrder(TreeUtil.createTree(3,9,20,null,null,15,7))); } } \ No newline at end of file diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_I_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_I_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221/Solution1.java" index 9deecdbf..af425ebb 100644 --- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_I_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221/Solution1.java" +++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_I_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221/Solution1.java" @@ -1,7 +1,7 @@ package cn.lastwhisper.offer.面试题32_I_从上到下打印二叉树; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; import java.util.*; @@ -37,6 +37,6 @@ public int[] levelOrder(TreeNode root) { } public static void main(String[] args) { - System.out.println(Arrays.toString(new Solution1().levelOrder(TreeUtils.createTree(3, 9, 20, 15, 7)))); + System.out.println(Arrays.toString(new Solution1().levelOrder(TreeUtil.createTree(3, 9, 20, 15, 7)))); } } \ No newline at end of file diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23034_\344\272\214\345\217\211\346\240\221\344\270\255\345\222\214\344\270\272\346\237\220\344\270\200\345\200\274\347\232\204\350\267\257\345\276\204/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23034_\344\272\214\345\217\211\346\240\221\344\270\255\345\222\214\344\270\272\346\237\220\344\270\200\345\200\274\347\232\204\350\267\257\345\276\204/Solution1.java" index b574fb09..901418e2 100644 --- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23034_\344\272\214\345\217\211\346\240\221\344\270\255\345\222\214\344\270\272\346\237\220\344\270\200\345\200\274\347\232\204\350\267\257\345\276\204/Solution1.java" +++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23034_\344\272\214\345\217\211\346\240\221\344\270\255\345\222\214\344\270\272\346\237\220\344\270\200\345\200\274\347\232\204\350\267\257\345\276\204/Solution1.java" @@ -1,8 +1,8 @@ package cn.lastwhisper.offer.面试题34_二叉树中和为某一值的路径; -import cn.lastwhisper.leetcode.common.print.PrintUtils; +import cn.lastwhisper.leetcode.common.print.PrintUtil; import cn.lastwhisper.leetcode.common.tree.TreeNode; -import cn.lastwhisper.leetcode.common.tree.TreeUtils; +import cn.lastwhisper.leetcode.common.tree.TreeUtil; import java.util.ArrayList; import java.util.List; @@ -45,8 +45,8 @@ public void pathSumHelper(TreeNode root, int sum, List list, List 0 && idx < k) { + res[idx++] = num; + } + if (idx == k) { + break; + } + } + return res; } public static void main(String[] args) { - + Assert.assertArrayEquals(new int[]{1, 2}, new Solution1().getLeastNumbers(new int[]{3, 2, 1}, 2)); + Assert.assertArrayEquals(new int[]{0}, new Solution1().getLeastNumbers(new int[]{0, 1, 2, 1}, 1)); } } \ No newline at end of file diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23059_I_\346\273\221\345\212\250\347\252\227\345\217\243\347\232\204\346\234\200\345\244\247\345\200\274/Solution.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23059_I_\346\273\221\345\212\250\347\252\227\345\217\243\347\232\204\346\234\200\345\244\247\345\200\274/Solution.java" new file mode 100644 index 00000000..c96621eb --- /dev/null +++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23059_I_\346\273\221\345\212\250\347\252\227\345\217\243\347\232\204\346\234\200\345\244\247\345\200\274/Solution.java" @@ -0,0 +1,34 @@ +package cn.lastwhisper.offer.面试题59_I_滑动窗口的最大值; + +import java.util.Arrays; + +class Solution { + /** + * 题目地址:https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/ + * 编号:面试题59 - I + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路:双指针(滑动窗口) + * (1) + * ------------------------------------------------------------------- + * 时间复杂度: + * 空间复杂度: + */ + public int[] maxSlidingWindow(int[] nums, int k) { + if (nums == null || nums.length < k) + return nums; + + + + + return null; + } + + + public static void main(String[] args) { + int[] nums = new int[]{1, 3, -1, -3, 5, 3, 6, 7}; + int k = 3; + System.out.println(Arrays.toString(new Solution().maxSlidingWindow(nums, k))); + } +} \ No newline at end of file diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23062_\345\234\206\345\234\210\344\270\255\346\234\200\345\220\216\345\211\251\344\270\213\347\232\204\346\225\260\345\255\227/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23062_\345\234\206\345\234\210\344\270\255\346\234\200\345\220\216\345\211\251\344\270\213\347\232\204\346\225\260\345\255\227/Solution1.java" new file mode 100644 index 00000000..a196364e --- /dev/null +++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23062_\345\234\206\345\234\210\344\270\255\346\234\200\345\220\216\345\211\251\344\270\213\347\232\204\346\225\260\345\255\227/Solution1.java" @@ -0,0 +1,39 @@ +package cn.lastwhisper.offer.面试题62_圆圈中最后剩下的数字; + +import org.junit.Assert; + +import java.util.ArrayList; +import java.util.List; + +class Solution1 { + /** + * 题目地址:https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * 通过取模模拟环状 + * ------------------------------------------------------------------- + * 时间复杂度:O(mn) + * 空间复杂度:O(n) + */ + public int lastRemaining(int n, int m) { + List list = new ArrayList<>(); + for (int i = 0; i < n; i++) { + list.add(i); + } + int idx = 0; + while (n > 1) { + // 模拟环状,-1是因为移除一个数 + idx = (idx + m - 1) % n; + list.remove(idx); + n--; + } + + return list.get(0); + } + + public static void main(String[] args) { + Assert.assertEquals(3, new Solution1().lastRemaining(5, 3)); + } +} \ No newline at end of file diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23062_\345\234\206\345\234\210\344\270\255\346\234\200\345\220\216\345\211\251\344\270\213\347\232\204\346\225\260\345\255\227/Solution2.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23062_\345\234\206\345\234\210\344\270\255\346\234\200\345\220\216\345\211\251\344\270\213\347\232\204\346\225\260\345\255\227/Solution2.java" new file mode 100644 index 00000000..6e87c9a2 --- /dev/null +++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23062_\345\234\206\345\234\210\344\270\255\346\234\200\345\220\216\345\211\251\344\270\213\347\232\204\346\225\260\345\255\227/Solution2.java" @@ -0,0 +1,42 @@ +package cn.lastwhisper.offer.面试题62_圆圈中最后剩下的数字; + +import org.junit.Assert; + +class Solution2 { + /** + * 题目地址:https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/ + * ------------------------------------------------------------------- + * 思考: + * ------------------------------------------------------------------- + * 思路: + * https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/solution/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-by-lee/ + * 将上述问题建模为函数 f(n, m),该函数的返回值为最终留下的元素的序号 + * 长度为n的序列会先删除第m%n个元素,然后剩下一个长度为n-1的序列,递归地求解f(n-1,m),设x=f(n-1,m) + * f(n - 1, m) = (m % n + x) % n = (m + x) % n + * ------------------------------------------------------------------- + * 时间复杂度:O(n) + * 空间复杂度:O(n) + */ + public int lastRemaining(int n, int m) { + //int ans = 0; + //// 最后一轮剩下2个人,所以从2开始反推 + //for (int i = 2; i <= n; i++) { + // ans = (ans + m) % i; + //} + //return ans; + return f(n, m); + } + + private int f(int n, int m) { + // 当序列长度为 1 时,一定会留下唯一的那个元素,它的编号为 0 + if (n == 1){ + return 0; + } + int x = f(n - 1, m); + return (m + x) % n; + } + + public static void main(String[] args) { + Assert.assertEquals(3, new Solution2().lastRemaining(5, 3)); + } +} \ No newline at end of file diff --git a/algorithms/pom.xml b/algorithms/pom.xml index bc8c6ec3..c67bc1b0 100644 --- a/algorithms/pom.xml +++ b/algorithms/pom.xml @@ -14,7 +14,8 @@ interview algorithm leetcode - thread + algorithm-common + niuke diff --git a/algorithms/test/pom.xml b/algorithms/test/pom.xml new file mode 100644 index 00000000..2b1eb3d3 --- /dev/null +++ b/algorithms/test/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + + org.example + test + 1.0-SNAPSHOT + + + 8 + 8 + + + \ No newline at end of file diff --git a/algorithms/test/src/main/java/cn/cunchang/Main.java b/algorithms/test/src/main/java/cn/cunchang/Main.java new file mode 100644 index 00000000..51de18e3 --- /dev/null +++ b/algorithms/test/src/main/java/cn/cunchang/Main.java @@ -0,0 +1,39 @@ +package cn.cunchang; + +import java.util.ArrayList; +import java.util.Scanner; + +/** + * @author cunchang + * @date 2022/7/6 8:12 PM + */ +public class Main { + + /** + * 有n个人围成一圈,顺序排号。 + * 从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位,起始索引位置为0。 + */ + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + int n = scanner.nextInt(); + ArrayList list = new ArrayList<>(n); + for (int i = 0; i < n; i++) { + list.add(i + 1); + } + int idx = 0; + int count = 0; + while (list.size() >1) { + if (count == 2) { + list.remove(idx); + idx=-1; + count=0; + } + idx++; + count++; + } + + // 还剩两个人 + System.out.println(list); + } + +} diff --git a/algorithms/test/src/main/java/cn/cunchang/Main2.java b/algorithms/test/src/main/java/cn/cunchang/Main2.java new file mode 100644 index 00000000..8eda3417 --- /dev/null +++ b/algorithms/test/src/main/java/cn/cunchang/Main2.java @@ -0,0 +1,45 @@ +package cn.cunchang; + +import java.util.Scanner; + +/** + * @author cunchang + * @date 2022/7/6 8:12 PM + */ +public class Main2 { + + /** + * 有n个人围成一圈,顺序排号。 + * 从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位,起始索引位置为0。 + */ + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + int n = scanner.nextInt(); + + boolean[] visited = new boolean[n];//true表示访问了 + + int outCount = n; + int idx = 0;// 访问下标 + int outIdx = 1;// 剔除计数 + while (outCount > 1) { + if (visited[idx % n]) { + idx++; + continue; + } + if (outIdx == 3) { + visited[idx % n] = true; + outCount--; + outIdx = 0; + } + idx++; + outIdx++; + } + + for (int i = 0; i < visited.length; i++) { + if (!visited[i]) { + System.out.println(i + 1); + } + } + } + +} diff --git a/algorithms/thread/pom.xml b/algorithms/thread/pom.xml deleted file mode 100644 index 765558b2..00000000 --- a/algorithms/thread/pom.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - algorithms - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - cn.lastwhisper - thread - - - \ No newline at end of file diff --git "a/algorithms/thread/src/main/java/cn/lastwhisper/thread/\346\214\211\345\272\217\346\211\223\345\215\2601114/Foo.java" "b/algorithms/thread/src/main/java/cn/lastwhisper/thread/\346\214\211\345\272\217\346\211\223\345\215\2601114/Foo.java" deleted file mode 100644 index a075b4a2..00000000 --- "a/algorithms/thread/src/main/java/cn/lastwhisper/thread/\346\214\211\345\272\217\346\211\223\345\215\2601114/Foo.java" +++ /dev/null @@ -1,32 +0,0 @@ -package cn.lastwhisper.thread.按序打印1114; - -import java.util.concurrent.CountDownLatch; - -public class Foo { - private CountDownLatch second = new CountDownLatch(1); - private CountDownLatch third = new CountDownLatch(1); - - public Foo() { - - } - - public void first(Runnable printFirst) throws InterruptedException { - - // printFirst.run() outputs "first". Do not change or remove this line. - printFirst.run(); - second.countDown(); - } - - public void second(Runnable printSecond) throws InterruptedException { - - // printSecond.run() outputs "second". Do not change or remove this line. - printSecond.run(); - third.countDown(); - } - - public void third(Runnable printThird) throws InterruptedException { - third.await(); - // printThird.run() outputs "third". Do not change or remove this line. - printThird.run(); - } -} \ No newline at end of file diff --git a/bigdata/flink-cdc/pom.xml b/bigdata/flink-cdc/pom.xml new file mode 100644 index 00000000..041ae367 --- /dev/null +++ b/bigdata/flink-cdc/pom.xml @@ -0,0 +1,92 @@ + + + 4.0.0 + + cn.cunchang + flink-cdc + 1.0-SNAPSHOT + + + 8 + 8 + 1.13.2 + + + + + + org.apache.flink + flink-java + ${flink-version} + + + + org.apache.flink + flink-streaming-java_2.12 + ${flink-version} + + + + org.apache.flink + flink-clients_2.12 + ${flink-version} + + + + org.apache.hadoop + hadoop-client + 3.1.3 + + + + mysql + mysql-connector-java + 5.1.49 + + + + org.apache.flink + flink-table-planner-blink_2.12 + ${flink-version} + + + + com.ververica + flink-connector-mysql-cdc + 2.0.0 + + + + com.alibaba + fastjson + 1.2.75 + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.0.0 + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + + + \ No newline at end of file diff --git a/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkCDC.java b/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkCDC.java new file mode 100644 index 00000000..81ecaeb2 --- /dev/null +++ b/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkCDC.java @@ -0,0 +1,51 @@ +package cn.cunchang; + +import com.ververica.cdc.connectors.mysql.MySqlSource; +import com.ververica.cdc.connectors.mysql.table.StartupOptions; +import com.ververica.cdc.debezium.DebeziumSourceFunction; +import com.ververica.cdc.debezium.StringDebeziumDeserializationSchema; +import org.apache.flink.runtime.state.hashmap.HashMapStateBackend; +import org.apache.flink.streaming.api.CheckpointingMode; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; + +public class FlinkCDC { + + public static void main(String[] args) throws Exception { + + //1.获取Flink 执行环境 + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + env.setParallelism(1); + + //1.1 开启Checkpoint,保存任务中断点,重启从中断点继续执行 +// env.enableCheckpointing(5000); +// env.getCheckpointConfig().setCheckpointTimeout(10000); +// env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE); +// env.getCheckpointConfig().setMaxConcurrentCheckpoints(1); + // 默认ck在内存里,也可以存到hdfs + env.setStateBackend(new HashMapStateBackend()); + // env.setStateBackend(new FsStateBackend("hdfs://localhost:9000/cdc-test/ck")); //过时写法 + // env.getCheckpointConfig().setCheckpointStorage("hdfs://localhost:9000/cdc-test/ck"); + + //2.通过FlinkCDC构建SourceFunction + DebeziumSourceFunction sourceFunction = MySqlSource.builder() + .hostname("localhost") + .port(3306) + .username("root") + .password("123456") + .databaseList("cdc_test") + .tableList("cdc_test.user_info") + .deserializer(new StringDebeziumDeserializationSchema()) + .startupOptions(StartupOptions.initial()) + .build(); + DataStreamSource dataStreamSource = env.addSource(sourceFunction); + + //3.数据打印 + dataStreamSource.print(); + + //4.启动任务 + env.execute("FlinkCDC"); + + } + +} diff --git a/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkCDC2.java b/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkCDC2.java new file mode 100644 index 00000000..5bbc1bef --- /dev/null +++ b/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkCDC2.java @@ -0,0 +1,43 @@ +package cn.cunchang; + +import cn.cunchang.func.CustomerDeserializationSchema; +import com.ververica.cdc.connectors.mysql.MySqlSource; +import com.ververica.cdc.connectors.mysql.table.StartupOptions; +import com.ververica.cdc.debezium.DebeziumSourceFunction; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; + +public class FlinkCDC2 { + + /** + * @param args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + + //1.获取Flink 执行环境 + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + env.setParallelism(1); + + //2.通过FlinkCDC构建SourceFunction + DebeziumSourceFunction sourceFunction = MySqlSource.builder() + .hostname("localhost") + .port(3306) + .username("root") + .password("123456") + .databaseList("cdc_test") + .tableList("cdc_test.user_info") + .deserializer(new CustomerDeserializationSchema()) + .startupOptions(StartupOptions.initial()) + .build(); + DataStreamSource dataStreamSource = env.addSource(sourceFunction); + + //3.数据打印 + dataStreamSource.print(); + + //4.启动任务 + env.execute("FlinkCDC2"); + + } + +} diff --git a/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkSQLCDC.java b/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkSQLCDC.java new file mode 100644 index 00000000..70ae914e --- /dev/null +++ b/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkSQLCDC.java @@ -0,0 +1,45 @@ +package cn.cunchang; + +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.table.api.Table; +import org.apache.flink.table.api.bridge.java.StreamTableEnvironment; +import org.apache.flink.types.Row; + +public class FlinkSQLCDC { + + public static void main(String[] args) throws Exception { + + //1.获取执行环境 + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + env.setParallelism(1); + StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env); + + //2.使用FLINKSQL DDL模式构建CDC 表 + tableEnv.executeSql("CREATE TABLE user_info ( " + + " id STRING primary key, " + + " name STRING, " + + " sex STRING " + + ") WITH ( " + + " 'connector' = 'mysql-cdc', " + + " 'scan.startup.mode' = 'latest-offset', " + + " 'hostname' = 'localhost', " + + " 'port' = '3306', " + + " 'username' = 'root', " + + " 'password' = '123456', " + + " 'database-name' = 'cdc_test', " + + " 'table-name' = 'user_info' " + + ")"); + + //3.查询数据并转换为流输出 + Table table = tableEnv.sqlQuery("select * from user_info"); + DataStream> retractStream = tableEnv.toRetractStream(table, Row.class); + retractStream.print(); + + //4.启动 + env.execute("FlinkSQLCDC"); + + } + +} diff --git a/bigdata/flink-cdc/src/main/java/cn/cunchang/func/CustomerDeserializationSchema.java b/bigdata/flink-cdc/src/main/java/cn/cunchang/func/CustomerDeserializationSchema.java new file mode 100644 index 00000000..99448140 --- /dev/null +++ b/bigdata/flink-cdc/src/main/java/cn/cunchang/func/CustomerDeserializationSchema.java @@ -0,0 +1,82 @@ +package cn.cunchang.func; + +import com.alibaba.fastjson.JSONObject; +import com.ververica.cdc.debezium.DebeziumDeserializationSchema; +import io.debezium.data.Envelope; +import org.apache.flink.api.common.typeinfo.BasicTypeInfo; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.util.Collector; +import org.apache.kafka.connect.data.Field; +import org.apache.kafka.connect.data.Schema; +import org.apache.kafka.connect.data.Struct; +import org.apache.kafka.connect.source.SourceRecord; + +import java.util.List; + +public class CustomerDeserializationSchema implements DebeziumDeserializationSchema { + + + /** + * { + * "db":"", + * "tableName":"", + * "before":{"id":"1001","name":""...}, + * "after":{"id":"1001","name":""...}, + * "op":"" + * } + */ + @Override + public void deserialize(SourceRecord sourceRecord, Collector collector) throws Exception { + + //创建JSON对象用于封装结果数据 + JSONObject result = new JSONObject(); + + //获取库名&表名 + String topic = sourceRecord.topic(); + String[] fields = topic.split("\\."); + result.put("db", fields[1]); + result.put("tableName", fields[2]); + + //获取before数据 + Struct value = (Struct) sourceRecord.value(); + Struct before = value.getStruct("before"); + JSONObject beforeJson = new JSONObject(); + if (before != null) { + //获取列信息 + Schema schema = before.schema(); + List fieldList = schema.fields(); + + for (Field field : fieldList) { + beforeJson.put(field.name(), before.get(field)); + } + } + result.put("before", beforeJson); + + //获取after数据 + Struct after = value.getStruct("after"); + JSONObject afterJson = new JSONObject(); + if (after != null) { + //获取列信息 + Schema schema = after.schema(); + List fieldList = schema.fields(); + + for (Field field : fieldList) { + afterJson.put(field.name(), after.get(field)); + } + } + result.put("after", afterJson); + + //获取操作类型 + Envelope.Operation operation = Envelope.operationFor(sourceRecord); + result.put("op", operation); + + //输出数据 + collector.collect(result.toJSONString()); + + } + + @Override + public TypeInformation getProducedType() { + return BasicTypeInfo.STRING_TYPE_INFO; + } +} diff --git a/bigdata/flink/pom.xml b/bigdata/flink/pom.xml new file mode 100644 index 00000000..30a11181 --- /dev/null +++ b/bigdata/flink/pom.xml @@ -0,0 +1,149 @@ + + + 4.0.0 + + cn.cunchang + flink + 1.0-SNAPSHOT + + + 8 + 8 + + + + + org.apache.flink + flink-java + 1.11.1 + + + + org.apache.flink + flink-streaming-java_2.12 + 1.11.1 + + + + + org.apache.flink + flink-streaming-scala_2.12 + 1.11.0 + + + + + org.apache.flink + flink-clients_2.12 + 1.11.1 + + + + + org.slf4j + slf4j-api + 1.7.10 + + + + org.slf4j + slf4j-log4j12 + 1.7.10 + + + + org.apache.hadoop + hadoop-client + 3.2.0 + + + + org.apache.bahir + flink-connector-redis_2.11 + 1.0 + + + + org.apache.flink + flink-table-api-java-bridge_2.12 + 1.11.0 + + + + org.apache.flink + flink-table-api-scala-bridge_2.12 + 1.11.0 + + + + + org.apache.flink + flink-table-planner-blink_2.12 + 1.11.0 + + + + + org.apache.flink + flink-table-planner_2.12 + 1.11.1 + + + + + org.apache.flink + flink-connector-kafka_2.12 + 1.11.1 + + + org.apache.flink + flink-statebackend-rocksdb_2.12 + 1.11.1 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + UTF-8 + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.4.1 + + + jar-with-dependencies + + + + + + + + + + + make-assembly + package + + single + + + + + + + + + \ No newline at end of file diff --git a/bigdata/flink/src/main/java/cn/cunchang/README.txt b/bigdata/flink/src/main/java/cn/cunchang/README.txt new file mode 100644 index 00000000..3449dfb0 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/README.txt @@ -0,0 +1,57 @@ + +# 入门 +# 一、流处理和批处理程序开发 +stream.SocketWindowWordCountJava 实时处理 +batch.BatchWordCountJava 批处理 + +# 二、Flink核心API之DataStream API +## DataStreamAPI之DataSource +- stream.source.StreamCollectionSourceJava + +## DataStreamAPI之Transformation +- stream.transformation +- 算子 + - union 合并多个流,多个流的数据类型必须一致 + - connect 只能连接两个流,两个流的数据类型可以不同 + - split 根据规则把一个数据流切分为多个流;代码:StreamSplitJava、StreamSideOutputJava +- 算子分区 + - shuffle 随机分区 + - rebalance 对数据集进行再平衡(顺序),重分区,消除数据倾斜 + - rescale 重分区(局部顺序) + - partitionCustom 自定义分区;代码:StreamPartitionOpJava + +## DataStreamAPI之DataSink +- stream.sink.StreamRedisSinkJava + +# 三、Flink核心API之DataSetAPI +## DataSetAPI之Transformation +- batch.transformation +- 算子 + - mapPartition 类似map,一次处理一个分区的数据;代码:BatchMapPartitionJava + - distinct 返回数据集中去重之后的元素 + - join 内连接;代码:BatchJoinJava + - outerJoin 外连接;代码:BatchOuterJoinJava + - cross 获取两个数据集的笛卡尔积;BatchCrossJava + - union 返回多个数据集的总和,数据类型需要一致 + - first-n 获取集合中的前N个元素;BatchFirstNJava + +# 四、Flink核心API之TableAPI和SQL +tablesql + +## Table API 和SQL的使用 +- CreateTableEnvironmentJava 创建一个TableEnvironment对象 +- TableAPIAndSQLOpJava +- DataStreamToTableJava DataStream、DataSet和Table之间的互相转换 + +# 进阶 +# 一、Window +- TimeWindowOpJava +- CountWindowOpJava +- MyTimeWindowJava + + + + + + + diff --git a/bigdata/flink/src/main/java/cn/cunchang/batch/BatchWordCountJava.java b/bigdata/flink/src/main/java/cn/cunchang/batch/BatchWordCountJava.java new file mode 100644 index 00000000..53a727b9 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/batch/BatchWordCountJava.java @@ -0,0 +1,44 @@ +package cn.cunchang.batch; + +import org.apache.flink.api.common.functions.FlatMapFunction; +import org.apache.flink.api.java.ExecutionEnvironment; +import org.apache.flink.api.java.operators.AggregateOperator; +import org.apache.flink.api.java.operators.DataSource; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.util.Collector; + +/** + * 需求:统计指定文件中单词出现的总次数 + * Created by xuwei + */ +public class BatchWordCountJava { + public static void main(String[] args) throws Exception{ + //获取执行环境 + ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment(); + + String inputPath = "hdfs://localhost:9000/hello.txt"; + String outPath = "hdfs://localhost:9000/out2"; + + //读取文件中的数据 + DataSource text = env.readTextFile(inputPath); + + //处理数据 + AggregateOperator> wordCount = text.flatMap(new FlatMapFunction>() { + public void flatMap(String line, Collector> out) + throws Exception { + String[] words = line.split(" "); + for (String word : words) { + out.collect(new Tuple2(word, 1)); + } + } + }).groupBy(0) + .sum(1) + .setParallelism(1); + + //将结果数据保存到文件中 + wordCount.writeAsCsv(outPath,"\n"," "); + + //执行程序 + env.execute("BatchWordCountJava"); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchCrossJava.java b/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchCrossJava.java new file mode 100644 index 00000000..1994477c --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchCrossJava.java @@ -0,0 +1,24 @@ +package cn.cunchang.batch.transformation; + +import org.apache.flink.api.java.ExecutionEnvironment; +import org.apache.flink.api.java.operators.DataSource; + +import java.util.Arrays; + +/** + * cross:获取两个数据集的笛卡尔积 + * Created by xuwei + */ +public class BatchCrossJava { + public static void main(String[] args) throws Exception{ + ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment(); + + //初始化第一份数据 + DataSource text1 = env.fromCollection(Arrays.asList(1, 2)); + //初始化第二份数据 + DataSource text2 = env.fromCollection(Arrays.asList("a", "b")); + + //执行cross操作 + text1.cross(text2).print(); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchFirstNJava.java b/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchFirstNJava.java new file mode 100644 index 00000000..47b1959e --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchFirstNJava.java @@ -0,0 +1,43 @@ +package cn.cunchang.batch.transformation; + +import org.apache.flink.api.common.operators.Order; +import org.apache.flink.api.java.ExecutionEnvironment; +import org.apache.flink.api.java.operators.DataSource; +import org.apache.flink.api.java.tuple.Tuple2; + +import java.util.ArrayList; + +/** + * first-n:获取集合中的前N个元素 + * Created by xuwei + */ +public class BatchFirstNJava { + public static void main(String[] args) throws Exception{ + ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment(); + + ArrayList> data = new ArrayList<>(); + data.add(new Tuple2(2,"zs")); + data.add(new Tuple2(4,"ls")); + data.add(new Tuple2(3,"ww")); + data.add(new Tuple2(1,"aw")); + data.add(new Tuple2(1,"xw")); + data.add(new Tuple2(1,"mw")); + + //初始化数据 + DataSource> text = env.fromCollection(data); + + //获取前3条数据,按照数据插入的顺序 + text.first(3).print(); + System.out.println("============================================"); + + + //根据数据中的第一列进行分组,获取每组的前2个元素 + text.groupBy(0).first(2).print(); + System.out.println("============================================"); + + //根据数据中的第一列分组,再根据第二列进行组内排序[倒序],获取每组的前2个元素 + //分组排序取TopN + text.groupBy(0).sortGroup(1, Order.DESCENDING).first(2).print(); + System.out.println("============================================"); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchJoinJava.java b/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchJoinJava.java new file mode 100644 index 00000000..34a2b1c6 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchJoinJava.java @@ -0,0 +1,52 @@ +package cn.cunchang.batch.transformation; + +import org.apache.flink.api.common.functions.JoinFunction; +import org.apache.flink.api.java.ExecutionEnvironment; +import org.apache.flink.api.java.operators.DataSource; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.api.java.tuple.Tuple3; + +import java.util.ArrayList; + +/** + * join:内连接 + * Created by xuwei + */ +public class BatchJoinJava { + public static void main(String[] args) throws Exception{ + ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment(); + + //初始化第一份数据 Tuple2<用户id,用户姓名> + ArrayList> data1 = new ArrayList<>(); + data1.add(new Tuple2(1,"jack")); + data1.add(new Tuple2(2,"tom")); + data1.add(new Tuple2(3,"mick")); + DataSource> text1 = env.fromCollection(data1); + + //初始化第二份数据 Tuple2<用户id,用户所在城市> + ArrayList> data2 = new ArrayList<>(); + data2.add(new Tuple2(1,"bj")); + data2.add(new Tuple2(2,"sh")); + data2.add(new Tuple2(4,"gz")); + DataSource> text2 = env.fromCollection(data2); + + //对两份数据集执行join操作 + text1.join(text2) + //注意:这里的where和equalTo实现了类似于on fieldA=fieldB的效果 + //where:指定左边数据集中参与比较的元素角标 + .where(0) + .equalTo(0) + //三个输入参数: + //第一个tuple2是左边数据集的类型, + //第二个tuple2是右边数据集的类型, + //第三个tuple3是此函数返回的数据集类型 + .with(new JoinFunction, Tuple2, Tuple3>() { + @Override + public Tuple3 join(Tuple2 first, Tuple2 second) + throws Exception { + return new Tuple3(first.f0,first.f1,second.f1); + } + }).print(); + + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchMapPartitionJava.java b/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchMapPartitionJava.java new file mode 100644 index 00000000..b532864d --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchMapPartitionJava.java @@ -0,0 +1,40 @@ +package cn.cunchang.batch.transformation; + +import org.apache.flink.api.common.functions.MapPartitionFunction; +import org.apache.flink.api.java.ExecutionEnvironment; +import org.apache.flink.api.java.operators.DataSource; +import org.apache.flink.util.Collector; + +import java.util.Arrays; +import java.util.UUID; + +/** + * MapPartition的使用:一次处理一个分区的数据 + * Created by xuwei + */ +public class BatchMapPartitionJava { + public static void main(String[] args) throws Exception { + ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment(); + //生成数据源数据 + DataSource text = env.fromCollection(Arrays.asList("hello you", "hello me")); + + //每次处理一个分区的数据 + text.mapPartition(new MapPartitionFunction() { + @Override + public void mapPartition(Iterable iterable, Collector out) + throws Exception { + String id = UUID.randomUUID().toString(); + // 可以在此处创建数据库连接,建议把这块代码放到try-catch代码块中 + // 注意:此时是每个分区获取一个数据库连接,不需要每处理一条数据就获取一次连接 + for (String line : iterable) { + System.out.println("id:" + id + ",line:" + line); + String[] words = line.split(" "); + for (String word : words) { + out.collect(word); + } + } + //关闭数据库连接 + } + }).print(); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchOuterJoinJava.java b/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchOuterJoinJava.java new file mode 100644 index 00000000..29e5abb1 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchOuterJoinJava.java @@ -0,0 +1,94 @@ +package cn.cunchang.batch.transformation; + +import org.apache.flink.api.common.functions.JoinFunction; +import org.apache.flink.api.java.ExecutionEnvironment; +import org.apache.flink.api.java.operators.DataSource; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.api.java.tuple.Tuple3; + +import java.util.ArrayList; + +/** + * outerJoin:外连接 + * 一共有三种情况 + * 1:leftOuterJoin + * 2:rightOuterJoin + * 3:fullOuterJoin + * Created by xuwei + */ +public class BatchOuterJoinJava { + public static void main(String[] args) throws Exception{ + ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment(); + + //初始化第一份数据 Tuple2<用户id,用户姓名> + ArrayList> data1 = new ArrayList<>(); + data1.add(new Tuple2(1,"jack")); + data1.add(new Tuple2(2,"tom")); + data1.add(new Tuple2(3,"mick")); + DataSource> text1 = env.fromCollection(data1); + + //初始化第二份数据 Tuple2<用户id,用户所在城市> + ArrayList> data2 = new ArrayList<>(); + data2.add(new Tuple2(1,"bj")); + data2.add(new Tuple2(2,"sh")); + data2.add(new Tuple2(4,"gz")); + DataSource> text2 = env.fromCollection(data2); + + System.out.println("==================左外连接===================="); + //对两份数据集执行leftOuterJoin操作 + text1.leftOuterJoin(text2) + .where(0) + .equalTo(0) + .with(new JoinFunction, Tuple2, Tuple3>() { + @Override + public Tuple3 join(Tuple2 first, Tuple2 second) + throws Exception { + if(second==null){ + return new Tuple3(first.f0,first.f1,"null"); + }else{ + return new Tuple3(first.f0,first.f1,second.f1); + } + } + }).print(); + + System.out.println("========================================"); + + System.out.println("==================右外连接===================="); + //对两份数据集执行rightOuterJoin操作 + text1.rightOuterJoin(text2) + .where(0) + .equalTo(0) + .with(new JoinFunction, Tuple2, Tuple3>() { + @Override + public Tuple3 join(Tuple2 first, Tuple2 second) + throws Exception { + if(first==null){ + return new Tuple3(second.f0,"null",second.f1); + }else{ + return new Tuple3(first.f0,first.f1,second.f1); + } + } + }).print(); + + System.out.println("========================================"); + + System.out.println("==================全外连接===================="); + //对两份数据集执行fullOuterJoin操作 + text1.fullOuterJoin(text2) + .where(0) + .equalTo(0) + .with(new JoinFunction, Tuple2, Tuple3>() { + @Override + public Tuple3 join(Tuple2 first, Tuple2 second) + throws Exception { + if(first==null){ + return new Tuple3(second.f0,"null",second.f1); + }else if(second==null){ + return new Tuple3(first.f0,first.f1,"null"); + }else{ + return new Tuple3(first.f0,first.f1,second.f1); + } + } + }).print(); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/kafkaconnector/StreamKafkaSinkJava.java b/bigdata/flink/src/main/java/cn/cunchang/kafkaconnector/StreamKafkaSinkJava.java new file mode 100644 index 00000000..2b7da149 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/kafkaconnector/StreamKafkaSinkJava.java @@ -0,0 +1,33 @@ +package cn.cunchang.kafkaconnector; + +import org.apache.flink.api.common.serialization.SimpleStringSchema; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer; +import org.apache.flink.streaming.connectors.kafka.internals.KafkaSerializationSchemaWrapper; + +import java.util.Properties; + +/** + * Flink向Kafka中生产数据 + * Created by xuwei + */ +public class StreamKafkaSinkJava { + public static void main(String[] args) throws Exception{ + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + DataStreamSource text = env.socketTextStream("bigdata04", 9001); + + //指定FlinkKafkaProducer相关配置 + String topic = "t3"; + Properties prop = new Properties(); + prop.setProperty("bootstrap.servers","bigdata01:9092,bigdata02:9092,bigdata03:9092"); + + //指定kafak作为sink + FlinkKafkaProducer kafkaProducer = new FlinkKafkaProducer<>(topic, new KafkaSerializationSchemaWrapper(topic, null, false, new SimpleStringSchema()), prop, FlinkKafkaProducer.Semantic.EXACTLY_ONCE); + text.addSink(kafkaProducer); + + env.execute("StreamKafkaSinkJava"); + + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/kafkaconnector/StreamKafkaSourceJava.java b/bigdata/flink/src/main/java/cn/cunchang/kafkaconnector/StreamKafkaSourceJava.java new file mode 100644 index 00000000..6af40e3b --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/kafkaconnector/StreamKafkaSourceJava.java @@ -0,0 +1,33 @@ +package cn.cunchang.kafkaconnector; + +import org.apache.flink.api.common.serialization.SimpleStringSchema; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer; + +import java.util.Properties; + +/** + * Flink从kafka中消费数据 + * Created by xuwei + */ +public class StreamKafkaSourceJava { + public static void main(String[] args) throws Exception{ + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + //指定FlinkKafkaConsumer相关配置 + String topic = "t1"; + Properties prop = new Properties(); + prop.setProperty("bootstrap.servers","bigdata01:9092,bigdata02:9092,bigdata03:9092"); + prop.setProperty("group.id","con1"); + FlinkKafkaConsumer kafkaConsumer = new FlinkKafkaConsumer<>(topic, new SimpleStringSchema(), prop); + + //指定kafka作为source + DataStreamSource text = env.addSource(kafkaConsumer); + + //将读取到的数据打印到控制台 + text.print(); + + env.execute("StreamKafkaSourceJava"); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/stream/SocketWindowWordCountJava.java b/bigdata/flink/src/main/java/cn/cunchang/stream/SocketWindowWordCountJava.java new file mode 100644 index 00000000..246c4a52 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/stream/SocketWindowWordCountJava.java @@ -0,0 +1,58 @@ +package cn.cunchang.stream; + +import org.apache.flink.api.common.functions.FlatMapFunction; +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.java.functions.KeySelector; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.api.windowing.time.Time; +import org.apache.flink.util.Collector; + +/** + * 需求:通过socket实时产生一些单词 + * 使用Flink实时接收数据 + * 对指定时间窗口内(例如:2秒)的数据进行聚合统计 + * 并且把时间窗口内计算的结果打印出来 + * Created by xuwei + */ +public class SocketWindowWordCountJava { + public static void main(String[] args) throws Exception{ + //获取运行环境 + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + //连接socket获取输入数据 + DataStreamSource text = env.socketTextStream("localhost", 9001); + + //处理数据 + SingleOutputStreamOperator> wordCount = text.flatMap(new FlatMapFunction() { + @Override + public void flatMap(String line, Collector out) throws Exception { + String[] words = line.split(" "); + for (String word : words) { + out.collect(word); + } + } + }).map(new MapFunction>() { + @Override + public Tuple2 map(String word) throws Exception { + return new Tuple2(word, 1); + } + }).keyBy(new KeySelector, String>() { + @Override + public String getKey(Tuple2 tup) throws Exception { + return tup.f0; + } + })//.keyBy(0) + .timeWindow(Time.seconds(2)) + .sum(1); + + //使用一个线程执行打印操作 + wordCount.print().setParallelism(1); + + //执行程序 + env.execute("SocketWindowWordCountJava"); + + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/stream/sink/StreamRedisSinkJava.java b/bigdata/flink/src/main/java/cn/cunchang/stream/sink/StreamRedisSinkJava.java new file mode 100644 index 00000000..8a035852 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/stream/sink/StreamRedisSinkJava.java @@ -0,0 +1,61 @@ +package cn.cunchang.stream.sink; + +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.connectors.redis.RedisSink; +import org.apache.flink.streaming.connectors.redis.common.config.FlinkJedisPoolConfig; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisCommand; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisCommandDescription; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisMapper; + +/** + * 需求:接收socket传输过来的数据,把数据保存到redis的list队列中 + * Created by xuwei + */ +public class StreamRedisSinkJava { + public static void main(String[] args) throws Exception{ + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + //连接socket获取输入数据 + DataStreamSource text = env.socketTextStream("localhost", 9008); + + // 组装数据,这里组装的是tuple2类型 + // 第一个元素是指list队列的key名称 + // 第二个元素是指需要向list队列中添加的元素 + SingleOutputStreamOperator> listData = text.map(new MapFunction>() { + @Override + public Tuple2 map(String word) throws Exception { + return new Tuple2("l_words_java", word); + } + }); + + //指定redissink + FlinkJedisPoolConfig conf = new FlinkJedisPoolConfig.Builder().setHost("localhost").setPort(6379).build(); + RedisSink> redisSink = new RedisSink<>(conf, new MyRedisMapper()); + listData.addSink(redisSink); + + env.execute("StreamRedisSinkJava"); + } + + public static class MyRedisMapper implements RedisMapper>{ + + //指定具体的操作命令 + @Override + public RedisCommandDescription getCommandDescription() { + return new RedisCommandDescription(RedisCommand.LPUSH); + } + + //获取key + @Override + public String getKeyFromData(Tuple2 data) { + return data.f0; + } + //获取value + @Override + public String getValueFromData(Tuple2 data) { + return data.f1; + } + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/stream/source/StreamCollectionSourceJava.java b/bigdata/flink/src/main/java/cn/cunchang/stream/source/StreamCollectionSourceJava.java new file mode 100644 index 00000000..d1cdde10 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/stream/source/StreamCollectionSourceJava.java @@ -0,0 +1,23 @@ +package cn.cunchang.stream.source; + +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; + +import java.util.Arrays; + +/** + * 基于collection的source的应用 + * Created by xuwei + */ +public class StreamCollectionSourceJava { + public static void main(String[] args) throws Exception{ + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + //使用collection集合生成DataStream + DataStreamSource text = env.fromCollection(Arrays.asList(1, 2, 3, 4, 5)); + + text.print().setParallelism(1); + + env.execute("StreamCollectionSourceJava"); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/MyPartitionerJava.java b/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/MyPartitionerJava.java new file mode 100644 index 00000000..4bfcc73f --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/MyPartitionerJava.java @@ -0,0 +1,20 @@ +package cn.cunchang.stream.transformation; + +import org.apache.flink.api.common.functions.Partitioner; + +/** + * 自定义分区规则:按照数字的奇偶性进行分区 + * Created by xuwei + */ +public class MyPartitionerJava implements Partitioner { + + @Override + public int partition(Integer key, int numPartitions) { + System.out.println("key:" + key + ",分区总数:" + numPartitions); + if (key % 2 == 0) { + return 0; + } else { + return 1; + } + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/StreamConnectJava.java b/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/StreamConnectJava.java new file mode 100644 index 00000000..bc71e94f --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/StreamConnectJava.java @@ -0,0 +1,41 @@ +package cn.cunchang.stream.transformation; + +import org.apache.flink.streaming.api.datastream.ConnectedStreams; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.api.functions.co.CoMapFunction; + +/** + * 只能连接两个流,两个流的数据类型可以不同 + * 应用:可以将两种不同格式的数据统一成一种格式 + * Created by xuwei + */ +public class StreamConnectJava { + public static void main(String[] args) throws Exception{ + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + //第1份数据流 + DataStreamSource text1 = env.fromElements("user:tom,age:18"); + //第2份数据流 + DataStreamSource text2 = env.fromElements("user:jack;age:18"); + + //连接两个流 + ConnectedStreams connectStream = text1.connect(text2); + + connectStream.map(new CoMapFunction() { + + //处理第1份数据流中的数据 + @Override + public String map1(String value) throws Exception { + return value.replace(",","-"); + } + //处理第2份数据流中的数据 + @Override + public String map2(String value) throws Exception { + return value.replace(";","-"); + } + }).print().setParallelism(1); + + env.execute("StreamConnectJava"); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/StreamPartitionOpJava.java b/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/StreamPartitionOpJava.java new file mode 100644 index 00000000..6afff71b --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/StreamPartitionOpJava.java @@ -0,0 +1,106 @@ +package cn.cunchang.stream.transformation; + +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.java.functions.KeySelector; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; + +import java.util.Arrays; + +/** + * 分区规则的使用 + * Created by xuwei + */ +public class StreamPartitionOpJava { + public static void main(String[] args) throws Exception{ + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + // 注意:默认情况下Flink任务中算子的并行度会读取当前机器的CPU个数 + // fromCollection的并行度为1, + DataStreamSource text = env.fromCollection(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); + + //使用shuffle分区规则 +// shuffleOp(text); + + //使用rebalance分区规则 +// rebalanceOp(text); + + //使用rescale分区规则 + //rescaleOp(text); + + //使用broadcast分区规则 + //broadcastOp(text); + + //自定义分区规则 + custormPartitionOp(text); + + env.execute("StreamPartitionOpJava"); + } + + private static void custormPartitionOp(DataStreamSource text) { + // 自定义分区规则:根据数据的奇偶性进行分区 + // 注意:此时虽然print算子的并行度为4,但是自定义的分区规则只会把数据分发给2个并行度,所以有2个是不干活 + text.map(new MapFunction() { + @Override + public Integer map(Integer value) throws Exception { + return value; + } + }).setParallelism(2) + .partitionCustom(new MyPartitionerJava(), new KeySelector() { + @Override + public Integer getKey(Integer value) throws Exception { + return value; + } + }) + .print() + .setParallelism(4); + } + + private static void broadcastOp(DataStreamSource text) { + text.map(new MapFunction() { + @Override + public Integer map(Integer value) throws Exception { + return value; + } + }).setParallelism(2) + .broadcast() + .print() + .setParallelism(4); + } + + private static void rescaleOp(DataStreamSource text) { + text.map(new MapFunction() { + @Override + public Integer map(Integer value) throws Exception { + return value; + } + }).setParallelism(2) + .rescale() + .print() + .setParallelism(4); + } + + private static void rebalanceOp(DataStreamSource text) { + text.map(new MapFunction() { + @Override + public Integer map(Integer value) throws Exception { + return value; + } + }).setParallelism(2) + .rebalance() + .print() + .setParallelism(4); + } + + private static void shuffleOp(DataStreamSource text) { + // 由于fromCollection已经设置了并行度为1,所以需要再接一个算子才能修改并行度,在这使用map算子 + text.map(new MapFunction() { + @Override + public Integer map(Integer value) throws Exception { + return value; + } + }).setParallelism(2)// 设置map算子的并行度为2 + .shuffle() + .print() + .setParallelism(4);// 设置print算子的并行度为4 + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/StreamSideOutputJava.java b/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/StreamSideOutputJava.java new file mode 100644 index 00000000..8a617f5a --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/StreamSideOutputJava.java @@ -0,0 +1,89 @@ +package cn.cunchang.stream.transformation; + +import org.apache.flink.api.common.functions.FilterFunction; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.api.functions.ProcessFunction; +import org.apache.flink.util.Collector; +import org.apache.flink.util.OutputTag; + +import java.util.Arrays; + +/** + * 使用sideoutput切分流 + * Created by xuwei + */ +public class StreamSideOutputJava { + public static void main(String[] args) throws Exception { + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + DataStreamSource text = env.fromCollection(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); + + //按照数据的奇偶性对数据进行分流 + //首先定义两个sideoutput来保存切分出来的数据 + OutputTag outputTag1 = new OutputTag("even") { + };//保存偶数 + OutputTag outputTag2 = new OutputTag("odd") { + };//保存奇数 + + SingleOutputStreamOperator outputStream = text.process(new ProcessFunction() { + + @Override + public void processElement(Integer value, Context ctx, Collector out) + throws Exception { + if (value % 2 == 0) { + ctx.output(outputTag1, value); + } else { + ctx.output(outputTag2, value); + } + } + }); + + //获取偶数数据流 + DataStream evenStream = outputStream.getSideOutput(outputTag1); + + //对evenStream流进行二次切分 + OutputTag outputTag11 = new OutputTag("low") { + }; + OutputTag outputTag12 = new OutputTag("high") { + }; + SingleOutputStreamOperator subOutputStream = evenStream.process(new ProcessFunction() { + + @Override + public void processElement(Integer value, Context ctx, Collector out) + throws Exception { + if (value <= 5) { + ctx.output(outputTag11, value); + } else { + ctx.output(outputTag12, value); + } + } + }); + + //获取小于等于5的数据流 + DataStream lowStream = subOutputStream.getSideOutput(outputTag11); + //获取大于5的数据流 + DataStream highStream = subOutputStream.getSideOutput(outputTag12); +// lowStream.print().setParallelism(1); + + + //获取奇数数据流 + DataStream oddStream = outputStream.getSideOutput(outputTag2); + SingleOutputStreamOperator filterStream = oddStream.filter(new FilterFunction() { + @Override + public boolean filter(Integer value) throws Exception { + if (value <= 5) { + return true; + } else { + return false; + } + } + }); + filterStream.print().setParallelism(1); + + + env.execute("StreamSideOutputJava"); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/StreamSplitJava.java b/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/StreamSplitJava.java new file mode 100644 index 00000000..54eec61c --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/StreamSplitJava.java @@ -0,0 +1,46 @@ +package cn.cunchang.stream.transformation; + +import org.apache.flink.streaming.api.collector.selector.OutputSelector; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.datastream.SplitStream; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; + +import java.util.ArrayList; +import java.util.Arrays; + +/** + * 根据规则把一个数据流切分为多个数据流 + * 注意:split只能分一次流,切分出来的流不能继续切分 + * split需要和select配合使用,选择切分后的流 + * 应用场景:将一份数据流切分为多份,便于针对每一份数据使用不同的处理逻辑 + * Created by xuwei + */ +public class StreamSplitJava { + public static void main(String[] args) throws Exception{ + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + DataStreamSource text = env.fromCollection(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); + + //按照数据的奇偶性对数据进行分流 + SplitStream splitStream = text.split(new OutputSelector() { + @Override + public Iterable select(Integer value) { + ArrayList list = new ArrayList<>(); + if (value % 2 == 0) { + list.add("even");//偶数 + } else { + list.add("odd");//奇数 + } + return list; + } + }); + + //选择流 + DataStream enevStream = splitStream.select("even"); + + enevStream.print().setParallelism(1); + + env.execute("StreamSplitJava"); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/StreamUnionJava.java b/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/StreamUnionJava.java new file mode 100644 index 00000000..66b3ef13 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/stream/transformation/StreamUnionJava.java @@ -0,0 +1,32 @@ +package cn.cunchang.stream.transformation; + +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; + +import java.util.Arrays; + +/** + * 合并多个流,多个流的数据类型必须一致 + * 应用场景:多种数据源的数据类型一致,数据处理规则也一致 + * + * Created by xuwei + */ +public class StreamUnionJava { + public static void main(String[] args) throws Exception{ + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + //第1份数据流 + DataStreamSource text1 = env.fromCollection(Arrays.asList(1, 2, 3, 4, 5)); + //第2份数据流 + DataStreamSource text2 = env.fromCollection(Arrays.asList(6, 7, 8, 9, 10)); + + //合并流 + DataStream unionStream = text1.union(text2); + + //打印流中的数据 + unionStream.print().setParallelism(1); + + env.execute("StreamUnionJava"); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/tablesql/CreateTableEnvironmentJava.java b/bigdata/flink/src/main/java/cn/cunchang/tablesql/CreateTableEnvironmentJava.java new file mode 100644 index 00000000..f5bb5d27 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/tablesql/CreateTableEnvironmentJava.java @@ -0,0 +1,45 @@ +package cn.cunchang.tablesql; + +import org.apache.flink.api.java.ExecutionEnvironment; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.table.api.EnvironmentSettings; +import org.apache.flink.table.api.TableEnvironment; +import org.apache.flink.table.api.bridge.java.BatchTableEnvironment; +import org.apache.flink.table.api.bridge.java.StreamTableEnvironment; + +/** + * 创建TableEnvironment对象 + * Created by xuwei + */ +public class CreateTableEnvironmentJava { + public static void main(String[] args) { + /** + * 注意:如果Table API 和 SQL不需要和DataStream或者DataSet互相转换 + * 则针对stream和batch都可以使用TableEnvironment + */ + //指定底层引擎为Blink,以及数据处理模式-stream + // 从1.11版本开始,Blink引擎成为Table API和SQL的默认执行引擎,在生产环境下 + EnvironmentSettings sSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build(); + //创建TableEnvironment对象 + TableEnvironment sTableEnv = TableEnvironment.create(sSettings); + + //指定底层引擎为Blink,以及数据处理模式-batch + EnvironmentSettings bSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inBatchMode().build(); + //创建TableEnvironment对象 + TableEnvironment bTableEnv = TableEnvironment.create(bSettings); + + /** + * 注意:如果Table API和SQL需要和DataStream或者DataSet互相转换 + * 针对stream需要使用StreamTableEnvironment + * 针对batch需要使用BatchTableEnvironment + */ + //创建StreamTableEnvironment + StreamExecutionEnvironment ssEnv = StreamExecutionEnvironment.getExecutionEnvironment(); + EnvironmentSettings ssSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build(); + StreamTableEnvironment ssTableEnv = StreamTableEnvironment.create(ssEnv, ssSettings); + + //创建BatchTableEnvironment + ExecutionEnvironment bbEnv = ExecutionEnvironment.getExecutionEnvironment(); + BatchTableEnvironment bbTableEnv = BatchTableEnvironment.create(bbEnv); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/tablesql/DataSetToTableJava.java b/bigdata/flink/src/main/java/cn/cunchang/tablesql/DataSetToTableJava.java new file mode 100644 index 00000000..737f35b3 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/tablesql/DataSetToTableJava.java @@ -0,0 +1,41 @@ +package cn.cunchang.tablesql; + +import org.apache.flink.api.java.ExecutionEnvironment; +import org.apache.flink.api.java.operators.DataSource; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.table.api.bridge.java.BatchTableEnvironment; + +import java.util.ArrayList; + +import static org.apache.flink.table.api.Expressions.$; + +/** + * 将DataSet转换为表 + * Created by xuwei + */ +public class DataSetToTableJava { + public static void main(String[] args) { + //获取BatchTableEnvironment + ExecutionEnvironment bbEnv = ExecutionEnvironment.getExecutionEnvironment(); + BatchTableEnvironment bbTableEnv = BatchTableEnvironment.create(bbEnv); + + //获取DataSet + //获取DataStream + ArrayList> data = new ArrayList<>(); + data.add(new Tuple2(1,"jack")); + data.add(new Tuple2(2,"tom")); + data.add(new Tuple2(3,"mick")); + DataSource> set = bbEnv.fromCollection(data); + + //第一种:将DataSet转换为view视图 + bbTableEnv.createTemporaryView("myTable",set,$("id"),$("name")); + bbTableEnv.sqlQuery("select * from myTable where id > 1 ").execute().print(); + + //第二种:将DataSet转换为table对象 + bbTableEnv.fromDataSet(set,$("id"),$("name")) + .filter($("id").isGreater(1)) + .execute() + .print(); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/tablesql/DataStreamToTableJava.java b/bigdata/flink/src/main/java/cn/cunchang/tablesql/DataStreamToTableJava.java new file mode 100644 index 00000000..0a030872 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/tablesql/DataStreamToTableJava.java @@ -0,0 +1,43 @@ +package cn.cunchang.tablesql; + +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.table.api.EnvironmentSettings; +import org.apache.flink.table.api.Table; +import org.apache.flink.table.api.bridge.java.StreamTableEnvironment; + +import java.util.ArrayList; + +import static org.apache.flink.table.api.Expressions.$; + +/** + * 将DataStream转换为表 + * Created by xuwei + */ +public class DataStreamToTableJava { + public static void main(String[] args) { + //获取StreamTableEnvironment + StreamExecutionEnvironment ssEnv = StreamExecutionEnvironment.getExecutionEnvironment(); + EnvironmentSettings ssSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build(); + StreamTableEnvironment ssTableEnv = StreamTableEnvironment.create(ssEnv, ssSettings); + + //获取DataStream + ArrayList> data = new ArrayList<>(); + data.add(new Tuple2(1,"jack")); + data.add(new Tuple2(2,"tom")); + data.add(new Tuple2(3,"mick")); + DataStreamSource> stream = ssEnv.fromCollection(data); + + //第一种:将DataStream转换为view视图 + ssTableEnv.createTemporaryView("myTable",stream,$("id"),$("name")); + ssTableEnv.sqlQuery("select * from myTable where id > 1 ").execute().print(); + + //第二种:将DataStream转换为table对象 + Table table = ssTableEnv.fromDataStream(stream, $("id"), $("name")); + table.select($("id"),$("name")) + .filter($("id").isGreater(1)) + .execute() + .print(); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/tablesql/TableAPIAndSQLOpJava.java b/bigdata/flink/src/main/java/cn/cunchang/tablesql/TableAPIAndSQLOpJava.java new file mode 100644 index 00000000..f756fbd5 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/tablesql/TableAPIAndSQLOpJava.java @@ -0,0 +1,64 @@ +package cn.cunchang.tablesql; + +import org.apache.flink.table.api.EnvironmentSettings; +import org.apache.flink.table.api.Table; +import org.apache.flink.table.api.TableEnvironment; + +import static org.apache.flink.table.api.Expressions.$; + +/** + * TableAPI 和 SQL的使用 + * Created by xuwei + */ +public class TableAPIAndSQLOpJava { + public static void main(String[] args) { + //获取TableEnvironment对象 + EnvironmentSettings sSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build(); + TableEnvironment sTableEnv = TableEnvironment.create(sSettings); + + //创建输入表 + /** + * connector.type:指定connector的类型 + * connector.path:指定文件或者目录地址 + * format.type:文件数据格式化类型,现在只支持csv格式 + * 注意:SQL语句如果出现了换行,行的末尾可以添加空格或者\n都可以,最后一行不用添 + * + * 注意:/Users/cunchang/tmp/data/source下面必须要有csv文件,内容:1,jack + */ + sTableEnv.executeSql("" + + "create table myTable(\n" + + "id int,\n" + + "name string\n" + + ") with (\n" + + "'connector.type' = 'filesystem',\n" + + "'connector.path' = '/Users/cunchang/tmp/data/source',\n" + + "'format.type' = 'csv'\n" + + ")"); + + //使用TableAPI实现数据查询和过滤等操作 + /*Table result = sTableEnv.from("myTable") + .select($("id"), $("name")) + .filter($("id").isGreater(1));*/ + + //使用SQL实现数据查询和过滤等操作 + Table result = sTableEnv.sqlQuery("select id,name from myTable where id > 1"); + + //输出结果到控制台 + result.execute().print(); + + //创建输出表 + sTableEnv.executeSql("" + + "create table newTable(\n" + + "id int,\n" + + "name string\n" + + ") with (\n" + + "'connector.type' = 'filesystem',\n" + + "'connector.path' = '/Users/cunchang/tmp/data/res',\n" + + "'format.type' = 'csv'\n" + + ")"); + + //输出结果到表newTable中 + result.executeInsert("newTable"); + + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/tablesql/TableToDataSetJava.java b/bigdata/flink/src/main/java/cn/cunchang/tablesql/TableToDataSetJava.java new file mode 100644 index 00000000..12213745 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/tablesql/TableToDataSetJava.java @@ -0,0 +1,46 @@ +package cn.cunchang.tablesql; + +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.java.DataSet; +import org.apache.flink.api.java.ExecutionEnvironment; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.table.api.Table; +import org.apache.flink.table.api.bridge.java.BatchTableEnvironment; +import org.apache.flink.types.Row; + +/** + * 将table转换成DataSet + * Created by xuwei + */ +public class TableToDataSetJava { + public static void main(String[] args) throws Exception{ + //创建BatchTableEnvironment + ExecutionEnvironment bbEnv = ExecutionEnvironment.getExecutionEnvironment(); + BatchTableEnvironment bbTableEnv = BatchTableEnvironment.create(bbEnv); + + //创建输入表 + bbTableEnv.executeSql("" + + "create table myTable(\n" + + "id int,\n" + + "name string\n" + + ") with (\n" + + "'connector.type' = 'filesystem',\n" + + "'connector.path' = 'D:\\data\\source',\n" + + "'format.type' = 'csv'\n" + + ")"); + + //获取table + Table table = bbTableEnv.from("myTable"); + + //将table转换成DataSet + DataSet set = bbTableEnv.toDataSet(table, Row.class); + set.map(new MapFunction>() { + @Override + public Tuple2 map(Row row) throws Exception { + int id = Integer.parseInt(row.getField(0).toString()); + String name = row.getField(1).toString(); + return new Tuple2(id,name); + } + }).print(); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/tablesql/TableToDataStreamJava.java b/bigdata/flink/src/main/java/cn/cunchang/tablesql/TableToDataStreamJava.java new file mode 100644 index 00000000..c877a456 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/tablesql/TableToDataStreamJava.java @@ -0,0 +1,65 @@ +package cn.cunchang.tablesql; + +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.api.java.tuple.Tuple3; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.table.api.EnvironmentSettings; +import org.apache.flink.table.api.Table; +import org.apache.flink.table.api.bridge.java.StreamTableEnvironment; +import org.apache.flink.types.Row; + +/** + * 将table转换成DataStream + * Created by xuwei + */ +public class TableToDataStreamJava { + public static void main(String[] args) throws Exception{ + //获取StreamTableEnvironment + StreamExecutionEnvironment ssEnv = StreamExecutionEnvironment.getExecutionEnvironment(); + EnvironmentSettings ssSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build(); + StreamTableEnvironment ssTableEnv = StreamTableEnvironment.create(ssEnv, ssSettings); + + //创建输入表 + ssTableEnv.executeSql("" + + "create table myTable(\n" + + "id int,\n" + + "name string\n" + + ") with (\n" + + "'connector.type' = 'filesystem',\n" + + "'connector.path' = 'D:\\data\\source',\n" + + "'format.type' = 'csv'\n" + + ")"); + + //获取table + Table table = ssTableEnv.from("myTable"); + + //将table转换为DataStream + //如果只有新增(追加)操作,可以使用toAppendStream + DataStream appStream = ssTableEnv.toAppendStream(table, Row.class); + appStream.map(new MapFunction>() { + @Override + public Tuple2 map(Row row) throws Exception { + int id = Integer.parseInt(row.getField(0).toString()); + String name = row.getField(1).toString(); + return new Tuple2(id,name); + } + }).print(); + + //如果有增加操作,还有删除操作,则使用toRetractStream + DataStream> retStream = ssTableEnv.toRetractStream(table, Row.class); + retStream.map(new MapFunction, Tuple3>() { + @Override + public Tuple3 map(Tuple2 tup) throws Exception { + Boolean flag = tup.f0; + int id = Integer.parseInt(tup.f1.getField(0).toString()); + String name = tup.f1.getField(1).toString(); + return new Tuple3(flag,id,name); + } + }).print(); + + //注意:将table转换为DataStream之后,就需要调用StreamExecutionEnvironment中的execute方法了 + ssEnv.execute("TableToDataStreamJava"); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/window/CountWindowOpJava.java b/bigdata/flink/src/main/java/cn/cunchang/window/CountWindowOpJava.java new file mode 100644 index 00000000..941d4d5c --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/window/CountWindowOpJava.java @@ -0,0 +1,56 @@ +package cn.cunchang.window; + +import org.apache.flink.api.common.functions.FlatMapFunction; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.util.Collector; + +/** + * CountWindow的使用 + * 1:滚动窗口 + * 2:滑动窗口 + * Created by xuwei + */ +public class CountWindowOpJava { + public static void main(String[] args) throws Exception{ + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + DataStreamSource text = env.socketTextStream("localhost", 9001); + + // 注意:由于我们在这里使用keyBy, 会先对数据分组 + // 如果某个分组对应的数据窗口内达到了5个元素,这个窗口才会被触发执行 + //CountWindow之滚动窗口:每隔5个元素计算一次前5个元素 + text.flatMap(new FlatMapFunction>() { + @Override + public void flatMap(String line, Collector> out) + throws Exception { + String[] words = line.split(" "); + for (String word : words) { + out.collect(new Tuple2(word,1)); + } + } + }).keyBy(0) + //窗口大小 + .countWindow(5) + .sum(1) + .print(); + + //CountWindow之滑动窗口:每隔1个元素计算一次前5个元素 +// text.flatMap(new FlatMapFunction>() { +// @Override +// public void flatMap(String line, Collector> out) +// throws Exception { +// String[] words = line.split(" "); +// for (String word : words) { +// out.collect(new Tuple2(word,1)); +// } +// } +// }).keyBy(0) +// //第一个参数:窗口大小,第二个参数:滑动间隔 +// .countWindow(5,1) +// .sum(1) +// .print(); + + env.execute("CountWindowOpJava"); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/window/MyTimeWindowJava.java b/bigdata/flink/src/main/java/cn/cunchang/window/MyTimeWindowJava.java new file mode 100644 index 00000000..08f25ae1 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/window/MyTimeWindowJava.java @@ -0,0 +1,39 @@ +package cn.cunchang.window; + +import org.apache.flink.api.common.functions.FlatMapFunction; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.api.windowing.assigners.TumblingProcessingTimeWindows; +import org.apache.flink.streaming.api.windowing.time.Time; +import org.apache.flink.util.Collector; + +/** + * 需求:自定义MyTimeWindow + * Created by xuwei + */ +public class MyTimeWindowJava { + public static void main(String[] args) throws Exception{ + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + DataStreamSource text = env.socketTextStream("localhost", 9001); + + // timewindow和countwindow底层都用的 window + //自定义MyTimeWindow滚动窗口:每隔10秒计算一次前10秒时间窗口内的数据 + text.flatMap(new FlatMapFunction>() { + @Override + public void flatMap(String line, Collector> out) + throws Exception { + String[] words = line.split(" "); + for (String word : words) { + out.collect(new Tuple2(word,1)); + } + } + }).keyBy(0) + //窗口大小 + .window(TumblingProcessingTimeWindows.of(Time.seconds(10))) + .sum(1) + .print(); + + env.execute("MyTimeWindowJava"); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/window/TimeWindowOpJava.java b/bigdata/flink/src/main/java/cn/cunchang/window/TimeWindowOpJava.java new file mode 100644 index 00000000..c72fbc6a --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/window/TimeWindowOpJava.java @@ -0,0 +1,55 @@ +package cn.cunchang.window; + +import org.apache.flink.api.common.functions.FlatMapFunction; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.api.windowing.time.Time; +import org.apache.flink.util.Collector; + +/** + * TimeWindow的使用 + * 1:滚动窗口 + * 2:滑动窗口 + * hello + */ +public class TimeWindowOpJava { + public static void main(String[] args) throws Exception { + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + DataStreamSource text = env.socketTextStream("localhost", 9001); + + //TimeWindow之滚动窗口:每隔10秒计算一次前10秒时间窗口内的数据 +// text.flatMap(new FlatMapFunction>() { +// @Override +// public void flatMap(String line, Collector> out) +// throws Exception { +// String[] words = line.split(" "); +// for (String word : words) { +// out.collect(new Tuple2(word, 1)); +// } +// } +// }).keyBy(0) +// //窗口大小 +// .timeWindow(Time.seconds(10)) +// .sum(1) +// .print(); + + //TimeWindow之滑动窗口:每隔5秒计算一次前10秒时间窗口内的数据 + text.flatMap(new FlatMapFunction>() { + @Override + public void flatMap(String line, Collector> out) + throws Exception { + String[] words = line.split(" "); + for (String word: words) { + out.collect(new Tuple2(word,1)); + } + } + }).keyBy(0) + //第一个参数:窗口大小,第二个参数:滑动间隔 + .timeWindow(Time.seconds(10),Time.seconds(5)) + .sum(1) + .print(); + + env.execute("TimeWindowOpJava"); + } +} diff --git a/bigdata/flink/src/main/java/cn/cunchang/window/WatermarkOpJava.java b/bigdata/flink/src/main/java/cn/cunchang/window/WatermarkOpJava.java new file mode 100644 index 00000000..0930a442 --- /dev/null +++ b/bigdata/flink/src/main/java/cn/cunchang/window/WatermarkOpJava.java @@ -0,0 +1,19 @@ +package cn.cunchang.window; + +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; + +/** + * 水位线 + * + * @author cunchang + * @date 2021/10/6 3:55 下午 + */ +public class WatermarkOpJava { + + public static void main(String[] args) { + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + + } + +} diff --git a/bigdata/flink/src/main/resources/log4j.properties b/bigdata/flink/src/main/resources/log4j.properties new file mode 100644 index 00000000..cdb2da93 --- /dev/null +++ b/bigdata/flink/src/main/resources/log4j.properties @@ -0,0 +1,9 @@ +log4j.rootLogger=warn,stdout + +log4j.appender.stdout = org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target = System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c] [%p] - %m%n + + + diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/batch/BatchWordCountScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/batch/BatchWordCountScala.scala new file mode 100644 index 00000000..47b537c3 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/batch/BatchWordCountScala.scala @@ -0,0 +1,36 @@ +package com.imooc.scala.batch + +import org.apache.flink.api.scala.ExecutionEnvironment + +/** + * 需求:统计指定文件中单词出现的总次数 + * Created by xuwei + */ +object BatchWordCountScala { + def main(args: Array[String]): Unit = { + //获取执行环境 + val env = ExecutionEnvironment.getExecutionEnvironment + + val inputPath = "hdfs://bigdata01:9000/hello.txt" + val outPath = "hdfs://bigdata01:9000/out" + + //读取文件中的数据 + val text = env.readTextFile(inputPath) + + //处理数据 + import org.apache.flink.api.scala._ + val wordCount = text.flatMap(_.split(" ")) + .map((_, 1)) + .groupBy(0) + .sum(1) + .setParallelism(1)//这里面设置并行度为1是为了将所有数据写到一个文件里面,查看结果比较方便 + + //将结果数据保存到文件中 + wordCount.writeAsCsv(outPath,"\n"," ") + + //执行程序 + env.execute("BatchWordCountScala") + + } + +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/batch/transformation/BatchCrossScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/batch/transformation/BatchCrossScala.scala new file mode 100644 index 00000000..6b0375af --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/batch/transformation/BatchCrossScala.scala @@ -0,0 +1,23 @@ +package com.imooc.scala.batch.transformation + +import org.apache.flink.api.scala.ExecutionEnvironment + +/** + * cross:获取两个数据集的笛卡尔积 + * Created by xuwei + */ +object BatchCrossScala { + def main(args: Array[String]): Unit = { + val env = ExecutionEnvironment.getExecutionEnvironment + + import org.apache.flink.api.scala._ + //初始化第一份数据 + val text1 = env.fromCollection(Array(1, 2)) + //初始化第二份数据 + val text2 = env.fromCollection(Array("a", "b")) + + //执行cross操作 + text1.cross(text2).print() + } + +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/batch/transformation/BatchFirstNScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/batch/transformation/BatchFirstNScala.scala new file mode 100644 index 00000000..4092c85b --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/batch/transformation/BatchFirstNScala.scala @@ -0,0 +1,41 @@ +package com.imooc.scala.batch.transformation + +import org.apache.flink.api.common.operators.Order +import org.apache.flink.api.scala.ExecutionEnvironment + +import scala.collection.mutable.ListBuffer + +/** + * first-n:获取集合中的前N个元素 + * Created by xuwei + */ +object BatchFirstNScala { + def main(args: Array[String]): Unit = { + val env = ExecutionEnvironment.getExecutionEnvironment + val data = ListBuffer[Tuple2[Int,String]]() + data.append((2,"zs")) + data.append((4,"ls")) + data.append((3,"ww")) + data.append((1,"aw")) + data.append((1,"xw")) + data.append((1,"mw")) + + import org.apache.flink.api.scala._ + //初始化数据 + val text = env.fromCollection(data) + + //获取前3条数据,按照数据插入的顺序 + text.first(3).print() + println("===========================") + + //根据数据中的第一列进行分组,获取每组的前2个元素 + text.groupBy(0).first(2).print() + println("===========================") + + + //根据数据中的第一列分组,再根据第二列进行组内排序[倒序],获取每组的前2个元素 + //分组排序取TopN + text.groupBy(0).sortGroup(1,Order.DESCENDING).first(2).print() + } + +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/batch/transformation/BatchJoinScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/batch/transformation/BatchJoinScala.scala new file mode 100644 index 00000000..dc302d2c --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/batch/transformation/BatchJoinScala.scala @@ -0,0 +1,31 @@ +package com.imooc.scala.batch.transformation + +import org.apache.flink.api.scala.ExecutionEnvironment + +/** + * join:内连接 + * Created by xuwei + */ +object BatchJoinScala { + def main(args: Array[String]): Unit = { + val env = ExecutionEnvironment.getExecutionEnvironment + + import org.apache.flink.api.scala._ + //初始化第一份数据 Tuple2<用户id,用户姓名> + val text1 = env.fromCollection(Array((1, "jack"), (2, "tom"), (3, "mick"))) + //初始化第二份数据 Tuple2<用户id,用户所在城市> + val text2 = env.fromCollection(Array((1, "bj"), (2, "sh"), (4, "gz"))) + + //对两份数据集执行join操作 + text1.join(text2) + //注意:这里的where和equalsTo实现类似于on fieldA=fieldB的效果 + //where:指定左边数据集中参与比较的元素角标 + .where(0) + //equalTo:指定右边数据集中参与比较的元素角标 + .equalTo(0){(first,second)=>{ + (first._1,first._2,second._2) + }}.print() + + } + +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/batch/transformation/BatchMapPartitionScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/batch/transformation/BatchMapPartitionScala.scala new file mode 100644 index 00000000..e697ac26 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/batch/transformation/BatchMapPartitionScala.scala @@ -0,0 +1,40 @@ +package com.imooc.scala.batch.transformation + +import org.apache.flink.api.scala.ExecutionEnvironment + +import scala.collection.mutable.ListBuffer + +/** + * MapPartition的使用:一次处理一个分区的数据 + * Created by xuwei + */ +object BatchMapPartitionScala { + def main(args: Array[String]): Unit = { + val env = ExecutionEnvironment.getExecutionEnvironment + + import org.apache.flink.api.scala._ + //生成数据源数据 + val text = env.fromCollection(Array("hello you", "hello me")) + + //每次处理一个分区的数据 + text.mapPartition(it=>{ + //可以在此处创建数据库连接,建议把这块代码放到try-catch代码块中 + //注意:此时是每个分区获取一次数据库连接,不需要每处理一条数据就获取一次连接,性能较高 + val res = ListBuffer[String]() + it.foreach(line=>{ + val words = line.split(" ") + for(word <- words){ + res.append(word) + } + }) + res + //关闭数据库连接 + }).print() + + //No new data sinks have been defined since the last execution. + //The last execution refers to the latest call to 'execute()', 'count()', 'collect()', or 'print()'. + //注意:这对DataSetAPI,如果在后面调用的是count、collect、print,则最后不需要指定execute即可 + //env.execute("BatchMapPartitionScala") + } + +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/batch/transformation/BatchOuterJoinScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/batch/transformation/BatchOuterJoinScala.scala new file mode 100644 index 00000000..4e8b9710 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/batch/transformation/BatchOuterJoinScala.scala @@ -0,0 +1,67 @@ +package com.imooc.scala.batch.transformation + +import org.apache.flink.api.scala.ExecutionEnvironment + +/** + * outerJoin:外连接 + * 一共有三种情况 + * 1:leftOuterJoin + * 2:rightOuterJoin + * 3:fullOuterJoin + * Created by xuwei + */ +object BatchOuterJoinScala { + def main(args: Array[String]): Unit = { + val env = ExecutionEnvironment.getExecutionEnvironment + + import org.apache.flink.api.scala._ + //初始化第一份数据 Tuple2<用户id,用户姓名> + val text1 = env.fromCollection(Array((1, "jack"), (2, "tom"), (3, "mick"))) + //初始化第二份数据 Tuple2<用户id,用户所在城市> + val text2 = env.fromCollection(Array((1, "bj"), (2, "sh"), (4, "gz"))) + + //对两份数据集执行leftOuterJoin操作 + text1.leftOuterJoin(text2) + .where(0) + .equalTo(0){(first,second)=>{ + //注意:second中的元素可能为null + if(second==null){ + (first._1,first._2,"null") + }else{ + (first._1,first._2,second._2) + } + }}.print() + + println("========================================") + + //对两份数据集执行rightOuterJoin操作 + text1.rightOuterJoin(text2) + .where(0) + .equalTo(0){(first,second)=>{ + //注意:first中的元素可能为null + if(first==null){ + (second._1,"null",second._2) + }else{ + (first._1,first._2,second._2) + } + }}.print() + + println("========================================") + + //对两份数据集执行fullOuterJoin操作 + text1.fullOuterJoin(text2) + .where(0) + .equalTo(0){(first,second)=>{ + //注意:first和second中的元素都有可能为null + if(first==null){ + (second._1,"null",second._2) + }else if(second==null){ + (first._1,first._2,"null") + }else{ + (first._1,first._2,second._2) + } + }}.print() + + } + +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/kafkaconnector/StreamKafkaSinkScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/kafkaconnector/StreamKafkaSinkScala.scala new file mode 100644 index 00000000..8902da11 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/kafkaconnector/StreamKafkaSinkScala.scala @@ -0,0 +1,48 @@ +package com.imooc.scala.kafkaconnector + +import java.util.Properties + +import org.apache.flink.api.common.serialization.SimpleStringSchema +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer +import org.apache.flink.streaming.connectors.kafka.internals.KafkaSerializationSchemaWrapper +import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkFixedPartitioner + +/** + * Flink向Kafka中生产数据 + * Created by xuwei + */ +object StreamKafkaSinkScala { + def main(args: Array[String]): Unit = { + val env = StreamExecutionEnvironment.getExecutionEnvironment + + //开启checkpoint + env.enableCheckpointing(5000) + + + val text = env.socketTextStream("bigdata04", 9001) + + //指定FlinkKafkaProducer的相关配置 + val topic = "t3" + val prop = new Properties() + prop.setProperty("bootstrap.servers","bigdata01:9092,bigdata02:9092,bigdata03:9092") + + //指定kafka作为sink + /* + KafkaSerializationSchemaWrapper的几个参数 + 1:topic:指定需要写入的topic名称即可 + 2:partitioner,通过自定义分区器实现将数据写入到指定topic的具体分区中 + 默认会使用FlinkFixedPartitioner,它表示会将所有的数据都写入指定topic的一个分区里面 + 如果不想自定义分区器,也不想使用默认的,可以直接使用null即可 + 3:writeTimeStamp,向topic中写入数据的时候,是否写入时间戳 + 如果写入了,那么在watermark的案例中,使用extractTimestamp()提起时间戳的时候 + 就可以直接使用recordTimestamp即可,它表示的就是我们在这里写入的数据对应的timestamp + */ + val kafkaProducer = new FlinkKafkaProducer[String](topic, new KafkaSerializationSchemaWrapper[String](topic, null, false, new SimpleStringSchema()), prop, FlinkKafkaProducer.Semantic.EXACTLY_ONCE) + text.addSink(kafkaProducer) + + env.execute("StreamKafkaSinkScala") + + } + +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/kafkaconnector/StreamKafkaSourceScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/kafkaconnector/StreamKafkaSourceScala.scala new file mode 100644 index 00000000..1d4635d8 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/kafkaconnector/StreamKafkaSourceScala.scala @@ -0,0 +1,66 @@ +package com.imooc.scala.kafkaconnector + +import java.util.Properties + +import org.apache.flink.api.common.serialization.SimpleStringSchema +import org.apache.flink.contrib.streaming.state.RocksDBStateBackend +import org.apache.flink.streaming.api.CheckpointingMode +import org.apache.flink.streaming.api.environment.CheckpointConfig +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer + +/** + * Flink从kafka中消费数据 + * Created by xuwei + */ +object StreamKafkaSourceScala { + def main(args: Array[String]): Unit = { + val env = StreamExecutionEnvironment.getExecutionEnvironment + + //每隔5000 ms执行一次checkpoint(设置checkpoint的周期) + env.enableCheckpointing(5000) + + //针对checkpoint的相关配置 + //设置模式为.EXACTLY_ONCE (这是默认值) ,还可以设置为AT_LEAST_ONCE + env.getCheckpointConfig.setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE) + //确保两次Checkpoint之间有至少多少 ms的间隔(checkpoint最小间隔) + env.getCheckpointConfig.setMinPauseBetweenCheckpoints(500) + //Checkpoint必须在一分钟内完成,或者被丢弃(checkpoint的超时时间) + env.getCheckpointConfig.setCheckpointTimeout(60000) + //同一时间只允许执行一个Checkpoint + env.getCheckpointConfig.setMaxConcurrentCheckpoints(1) + //表示一旦Flink处理程序被cancel后,会保留Checkpoint数据,以便根据实际需要恢复到指定的Checkpoint + env.getCheckpointConfig.enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION) + //设置状态数据存储的位置 + env.setStateBackend(new RocksDBStateBackend("hdfs://bigdata01:9000/flink/checkpoints",true)) + + + //指定FlinkKafkaConsumer相关配置 + val topic = "t1" + val prop = new Properties() + prop.setProperty("bootstrap.servers","bigdata01:9092,bigdata02:9092,bigdata03:9092") + prop.setProperty("group.id","con1") + val kafkaConsumer = new FlinkKafkaConsumer[String](topic, new SimpleStringSchema(), prop) + + //kafka consumer的消费策略设置 + //默认策略,读取group.id对应保存的offset开始消费数据,读取不到则根据kafka中auto.offset.reset参数的值开始消费数据 + kafkaConsumer.setStartFromGroupOffsets() + //从最早的记录开始消费数据,忽略已提交的offset信息 + //kafkaConsumer.setStartFromEarliest() + //从最新的记录开始消费数据,忽略已提交的offset信息 + //kafkaConsumer.setStartFromLatest() + //从指定的时间戳开始消费数据,对于每个分区,其时间戳大于或等于指定时间戳的记录将被作为起始位置 + //kafkaConsumer.setStartFromTimestamp(176288819) + + + //指定kafka作为source + import org.apache.flink.api.scala._ + val text = env.addSource(kafkaConsumer) + + //将读取到的数据打印到控制台上 + text.print() + + env.execute("StreamKafkaSourceScala") + } + +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/stream/SocketWindowWordCountScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/stream/SocketWindowWordCountScala.scala new file mode 100644 index 00000000..05bb74bc --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/stream/SocketWindowWordCountScala.scala @@ -0,0 +1,40 @@ +package com.imooc.scala.stream + +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment +import org.apache.flink.streaming.api.windowing.time.Time + +/** + * 需求:通过socket实时产生一些单词 + * 使用Flink实时接收数据 + * 对指定时间窗口内(例如:2秒)的数据进行聚合统计 + * 并且把时间窗口内计算的结果打印出来 + * Created by xuwei + */ +object SocketWindowWordCountScala { + def main(args: Array[String]): Unit = { + //获取运行环境 + val env = StreamExecutionEnvironment.getExecutionEnvironment + + //连接socket获取输入数据 + val text = env.socketTextStream("bigdata04", 9001) + + //处理数据 + //注意:必须要添加这一行隐式转换的代码,否则下面的flatMap方法会报错 + import org.apache.flink.api.scala._ + val wordCount = text.flatMap(_.split(" "))//将每一行数据根据空格切分单词 + .map((_,1))//每一个单词转换为tuple2的形式(单词,1) + //.keyBy(0)//根据tuple2中的第一列进行分组 + .keyBy(tup=>tup._1)//官方推荐使用keySelector选择器选择数据 + .timeWindow(Time.seconds(2))//时间窗口为2秒,表示每隔2秒钟计算一次接收到的数据 + .sum(1)//使用sum或者reduce都可以 + //.reduce((t1,t2)=>(t1._1,t1._2+t2._2)) + + //使用一个线程执行打印操作 + wordCount.print().setParallelism(1) + + //执行程序 + env.execute("SocketWindowWordCountScala") + + } + +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/stream/sink/StreamRedisSinkScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/stream/sink/StreamRedisSinkScala.scala new file mode 100644 index 00000000..6a697503 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/stream/sink/StreamRedisSinkScala.scala @@ -0,0 +1,49 @@ +package com.imooc.scala.stream.sink + +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment +import org.apache.flink.streaming.connectors.redis.RedisSink +import org.apache.flink.streaming.connectors.redis.common.config.FlinkJedisPoolConfig +import org.apache.flink.streaming.connectors.redis.common.mapper.{RedisCommand, RedisCommandDescription, RedisMapper} + +/** + * 需求:接收socket传输过来的数据,把数据保存到redis的list队列中 + * Created by xuwei + */ +object StreamRedisSinkScala { + def main(args: Array[String]): Unit = { + val env = StreamExecutionEnvironment.getExecutionEnvironment + + //连接socket获取输入数据 + val text = env.socketTextStream("bigdata04", 9001) + + import org.apache.flink.api.scala._ + //组装数据,这里组装的是tuple2类型 + //第一个元素是指list队列的key名称 + //第二个元素是指需要向list队列中添加的元素 + val listData = text.map(word => ("l_words_scala", word)) + + //指定redissink + val conf = new FlinkJedisPoolConfig.Builder().setHost("bigdata04").setPort(6379).build() + val redisSink = new RedisSink[Tuple2[String, String]](conf, new MyRedisMapper) + listData.addSink(redisSink) + + env.execute("StreamRedisSinkScala") + } + + class MyRedisMapper extends RedisMapper[Tuple2[String,String]]{ + //指定具体的操作命令 + override def getCommandDescription: RedisCommandDescription = { + new RedisCommandDescription(RedisCommand.LPUSH) + } + + //获取key + override def getKeyFromData(data: (String, String)): String = { + data._1 + } + //获取value + override def getValueFromData(data: (String, String)): String = { + data._2 + } + } + +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/stream/source/StreamCollectionSourceScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/stream/source/StreamCollectionSourceScala.scala new file mode 100644 index 00000000..40424017 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/stream/source/StreamCollectionSourceScala.scala @@ -0,0 +1,22 @@ +package com.imooc.scala.stream.source + +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment + +/** + * 基于collection的source的应用 + * 注意:这个source的主要应用场景是模拟测试代码流程的时候使用 + * Created by xuwei + */ +object StreamCollectionSourceScala { + def main(args: Array[String]): Unit = { + val env = StreamExecutionEnvironment.getExecutionEnvironment + + //使用collection集合生成DataStream + import org.apache.flink.api.scala._ + val text = env.fromCollection(Array(1, 2, 3, 4, 5)) + + text.print().setParallelism(1) + + env.execute("StreamCollectionSourceScala") + } +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/MyPartitionerScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/MyPartitionerScala.scala new file mode 100644 index 00000000..c0a61dcf --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/MyPartitionerScala.scala @@ -0,0 +1,18 @@ +package com.imooc.scala.stream.transformation + +import org.apache.flink.api.common.functions.Partitioner + +/** + * 自定义分区规则:按照数字的奇偶性进行分区 + * Created by xuwei + */ +class MyPartitionerScala extends Partitioner[Int]{ + override def partition(key: Int, numPartitions: Int): Int = { + println("分区总数:"+numPartitions) + if(key % 2 == 0){//偶数分到0号分区 + 0 + }else{//奇数分到1号分区 + 1 + } + } +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/StreamConnectScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/StreamConnectScala.scala new file mode 100644 index 00000000..3f49c263 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/StreamConnectScala.scala @@ -0,0 +1,37 @@ +package com.imooc.scala.stream.transformation + +import org.apache.flink.streaming.api.functions.co.CoMapFunction +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment + +/** + * 只能连接两个流,两个流的数据类型可以不同 + * 应用:可以将两种不同格式的数据统一成一种格式 + * Created by xuwei + */ +object StreamConnectScala { + def main(args: Array[String]): Unit = { + val env = StreamExecutionEnvironment.getExecutionEnvironment + + import org.apache.flink.api.scala._ + //第1份数据流 + val text1 = env.fromElements("user:tom,age:18") + //第2份数据流 + val text2 = env.fromElements("user:jack_age:20") + + //连接两个流 + val connectStream = text1.connect(text2) + + connectStream.map(new CoMapFunction[String,String,String] { + //处理第1份数据流中的数据 + override def map1(value: String): String = { + value.replace(",","-") + } + //处理第2份数据流中的数据 + override def map2(value: String): String = { + value.replace("_","-") + } + }).print().setParallelism(1) + + env.execute("StreamConnectScala") + } +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/StreamPartitionOpScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/StreamPartitionOpScala.scala new file mode 100644 index 00000000..84920ca4 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/StreamPartitionOpScala.scala @@ -0,0 +1,82 @@ +package com.imooc.scala.stream.transformation + +import org.apache.flink.streaming.api.scala.{DataStream, StreamExecutionEnvironment} +import org.apache.flink.api.scala._ +/** + * 分区规则的使用 + * Created by xuwei + */ +object StreamPartitionOpScala { + def main(args: Array[String]): Unit = { + val env = StreamExecutionEnvironment.getExecutionEnvironment + + //注意:在这里将这个隐式转换代码放到类上面 + //因为默认它只在main函数生效,针对下面提取的shuffleOp是无效,否则也需要在shuffleOp添加这行代码 + //import org.apache.flink.api.scala._ + + //注意:默认情况下Flink任务中算子的并行度会读取当前机器的CPU个数 + //fromCollection的并行度为1, + val text = env.fromCollection(Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) + + //使用shuffle分区规则 + //shuffleOp(text) + + //使用rebalance分区规则 + //rebalanceOp(text) + + //使用rescale分区规则 + //rescaleOp(text) + + //使用broadcast分区规则 + //broadcastOp(text) + + //自定义分区规则:根据数据的奇偶性进行分区 + //注意:此时虽然print算子的并行度为4,但是自定义的分区规则只会把数据分发给2个并行度,所以有2个是不干活 + //custormPartitionOp(text) + + env.execute("StreamPartitionOpScala") + + } + + private def custormPartitionOp(text: DataStream[Int]) = { + text.map(num => num) + .setParallelism(2) //设置map算子的并行度为2 + //.partitionCustom(new MyPartitionerScala,0)//这种写法已经过期 + .partitionCustom(new MyPartitionerScala, num => num) //官方建议使用keySelector + .print() + .setParallelism(4) //设置print算子的并行度为4 + } + + private def broadcastOp(text: DataStream[Int]) = { + text.map(num => num) + .setParallelism(2) //设置map算子的并行度为2 + .broadcast + .print() + .setParallelism(4) //设置print算子的并行度为4 + } + + private def rescaleOp(text: DataStream[Int]) = { + text.map(num => num) + .setParallelism(2) //设置map算子的并行度为2 + .rescale + .print() + .setParallelism(4) //设置print算子的并行度为4 + } + + private def rebalanceOp(text: DataStream[Int]) = { + text.map(num => num) + .setParallelism(2) //设置map算子的并行度为2 + .rebalance + .print() + .setParallelism(4) //设置print算子的并行度为4 + } + + private def shuffleOp(text: DataStream[Int]) = { + //由于fromCollection已经设置了并行度为1,所以需要再接一个算子才能修改并行度,在这使用map算子 + text.map(num => num) + .setParallelism(2) //设置map算子的并行度为2 + .shuffle + .print() + .setParallelism(4) //设置print算子的并行度为4 + } +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/StreamSideOutputScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/StreamSideOutputScala.scala new file mode 100644 index 00000000..a1e036e0 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/StreamSideOutputScala.scala @@ -0,0 +1,65 @@ +package com.imooc.scala.stream.transformation + +import org.apache.flink.streaming.api.functions.ProcessFunction +import org.apache.flink.streaming.api.scala.{OutputTag, StreamExecutionEnvironment} +import org.apache.flink.util.Collector + +/** + * 使用sideoutput切分流 + * Created by xuwei + */ +object StreamSideOutputScala { + def main(args: Array[String]): Unit = { + val env = StreamExecutionEnvironment.getExecutionEnvironment + + import org.apache.flink.api.scala._ + val text = env.fromCollection(Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) + + //按照数据的奇偶性对数据进行分流 + //首先定义两个sideoutput来准备保存切分出来的数据 + val outputTag1 = new OutputTag[Int]("even")//保存偶数 + val outputTag2 = new OutputTag[Int]("odd")//保存奇数 + + //注意:process属于Flink中的低级api + val outputStream = text.process(new ProcessFunction[Int, Int] { + override def processElement(value: Int, ctx: ProcessFunction[Int, Int]#Context, out: Collector[Int]): Unit = { + if (value % 2 == 0) { + ctx.output(outputTag1, value) + } else { + ctx.output(outputTag2, value) + } + } + }) + + //获取偶数数据流 + val evenStream = outputStream.getSideOutput(outputTag1) + //获取奇数数据流 + val oddStream = outputStream.getSideOutput(outputTag2) + //evenStream.print().setParallelism(1) + + //对evenStream流进行二次切分 + val outputTag11 = new OutputTag[Int]("low")//保存小于等于5的数字 + val outputTag12 = new OutputTag[Int]("high")//保存大于5的数字 + + val subOutputStream = evenStream.process(new ProcessFunction[Int, Int] { + override def processElement(value: Int, ctx: ProcessFunction[Int, Int]#Context, out: Collector[Int]): Unit = { + if (value <= 5) { + ctx.output(outputTag11, value) + } else { + ctx.output(outputTag12, value) + } + } + }) + + //获取小于等于5的数据流 + val lowStream = subOutputStream.getSideOutput(outputTag11) + //获取大于5的数据流 + val highStream = subOutputStream.getSideOutput(outputTag12) + + lowStream.print().setParallelism(1) + + env.execute("StreamSideOutputScala") + + } + +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/StreamSplitScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/StreamSplitScala.scala new file mode 100644 index 00000000..8f4870e8 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/StreamSplitScala.scala @@ -0,0 +1,59 @@ +package com.imooc.scala.stream.transformation + +import java.{lang, util} + +import org.apache.flink.streaming.api.collector.selector.OutputSelector +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment + +/** + * 根据规则把一个数据流切分为多个数据流 + * 注意:split只能分一次流,切分出来的流不能继续切分 + * split需要和select配合使用,选择切分后的流 + * 应用场景:将一份数据流切分为多份,便于针对每一份数据使用不同的处理逻辑 + * Created by xuwei + */ +object StreamSplitScala { + def main(args: Array[String]): Unit = { + val env = StreamExecutionEnvironment.getExecutionEnvironment + + import org.apache.flink.api.scala._ + //初始化数据 + val text = env.fromCollection(Array(1, 2, 4, 5, 6, 7, 8, 9, 10)) + + //按照数据的奇偶性对数据进行分流 + val splitStream = text.split(new OutputSelector[Int] { + override def select(value: Int): lang.Iterable[String] = { + val list = new util.ArrayList[String]() + if(value % 2 == 0){ + list.add("even")//偶数 + }else{ + list.add("odd")//奇数 + } + list + } + }) + + //选择流 + val evenStream = splitStream.select("even") + evenStream.print().setParallelism(1) + + //二次切流会报错 + //Consecutive multiple splits are not supported. Splits are deprecated. Please use side-outputs. + /*val lowHighStream = evenStream.split(new OutputSelector[Int] { + override def select(value: Int): lang.Iterable[String] = { + val list = new util.ArrayList[String]() + if(value <= 5){ + list.add("low") + }else{ + list.add("high") + } + list + } + }) + val lowStream = lowHighStream.select("low") + lowStream.print().setParallelism(1)*/ + + + env.execute("StreamSplitScala") + } +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/StreamUnionScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/StreamUnionScala.scala new file mode 100644 index 00000000..867e80ae --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/stream/transformation/StreamUnionScala.scala @@ -0,0 +1,29 @@ +package com.imooc.scala.stream.transformation + +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment + +/** + * 合并多个流,多个流的数据类型必须一致 + * 应用场景:多种数据源的数据类型一致,数据处理规则也一致 + * Created by xuwei + */ +object StreamUnionScala { + def main(args: Array[String]): Unit = { + val env = StreamExecutionEnvironment.getExecutionEnvironment + + import org.apache.flink.api.scala._ + //第1份数据流 + val text1 = env.fromCollection(Array(1, 2, 3, 4, 5)) + //第2份数据流 + val text2 = env.fromCollection(Array(6, 7, 8, 9, 10)) + + //合并流 + val unionStream = text1.union(text2) + + //打印流中的数据 + unionStream.print().setParallelism(1) + + env.execute("StreamUnionScala") + + } +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/CreateTableEnvironmentScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/CreateTableEnvironmentScala.scala new file mode 100644 index 00000000..c5294be3 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/CreateTableEnvironmentScala.scala @@ -0,0 +1,46 @@ +package com.imooc.scala.tablesql + +import org.apache.flink.api.scala.ExecutionEnvironment +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment +import org.apache.flink.table.api.bridge.scala.{BatchTableEnvironment, StreamTableEnvironment} +import org.apache.flink.table.api.{EnvironmentSettings, TableEnvironment} + +/** + * 创建TableEnvironment对象 + * Created by xuwei + */ +object CreateTableEnvironmentScala { + def main(args: Array[String]): Unit = { + + /** + * 注意:如果Table API 和 SQL不需要和DataStream或者DataSet互相转换 + * 则针对stream和batch都可以使用TableEnvironment + */ + //指定底层引擎为Blink,以及数据处理模式-stream + val sSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build() + //创建TableEnvironment对象 + val sTableEnv = TableEnvironment.create(sSettings) + + + //指定底层引擎为Blink,以及数据处理模式-batch + val bSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inBatchMode().build() + //创建TableEnvironment对象 + val bTableEnv = TableEnvironment.create(bSettings) + + /** + * 注意:如果Table API和SQL需要和DataStream或者DataSet互相转换 + * 针对stream需要使用StreamTableEnvironment + * 针对batch需要使用BatchTableEnvironment + */ + //创建StreamTableEnvironment + val ssEnv = StreamExecutionEnvironment.getExecutionEnvironment + val ssSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build() + val ssTableEnv = StreamTableEnvironment.create(ssEnv, ssSettings) + + //创建BatchTableEnvironment + //注意:此时只能使用旧的执行引擎,新的Blink执行引擎不支持和DataSet转换 + val bbEnv = ExecutionEnvironment.getExecutionEnvironment + val bbTableEnv = BatchTableEnvironment.create(bbEnv) + + } +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/DataSetToTableScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/DataSetToTableScala.scala new file mode 100644 index 00000000..a8908acc --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/DataSetToTableScala.scala @@ -0,0 +1,33 @@ +package com.imooc.scala.tablesql + +import org.apache.flink.api.scala.ExecutionEnvironment +import org.apache.flink.table.api.bridge.scala.BatchTableEnvironment + +/** + * 将DataSet转换为表 + * Created by xuwei + */ +object DataSetToTableScala { + def main(args: Array[String]): Unit = { + //获取BatchTableEnvironment + val bbEnv = ExecutionEnvironment.getExecutionEnvironment + val bbTableEnv = BatchTableEnvironment.create(bbEnv) + + //获取DataSet + import org.apache.flink.api.scala._ + val set = bbEnv.fromCollection(Array((1, "jack"), (2, "tom"), (3, "mack"))) + + //第一种:将DataSet转换为view视图 + import org.apache.flink.table.api._ + bbTableEnv.createTemporaryView("myTable",set,'id,'name) + bbTableEnv.sqlQuery("select * from myTable where id > 1").execute().print() + + //第二种:将DataSet转换为table对象 + val table = bbTableEnv.fromDataSet(set, 'id, 'name) + table.select($"id",$"name") + .filter($"id" > 1 ) + .execute() + .print() + } + +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/DataStreamToTableScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/DataStreamToTableScala.scala new file mode 100644 index 00000000..a7935ef7 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/DataStreamToTableScala.scala @@ -0,0 +1,37 @@ +package com.imooc.scala.tablesql + +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment +import org.apache.flink.table.api.EnvironmentSettings +import org.apache.flink.table.api.bridge.scala.StreamTableEnvironment + +/** + * 将DataStream转换为表 + * Created by xuwei + */ +object DataStreamToTableScala { + def main(args: Array[String]): Unit = { + //获取StreamTableEnvironment + val ssEnv = StreamExecutionEnvironment.getExecutionEnvironment + val ssSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build() + val ssTableEnv = StreamTableEnvironment.create(ssEnv, ssSettings) + + //获取DataStream + import org.apache.flink.api.scala._ + val stream = ssEnv.fromCollection(Array((1, "jack"), (2, "tom"), (3, "mack"))) + + //第一种:将DataStream转换为view视图 + import org.apache.flink.table.api._ + ssTableEnv.createTemporaryView("myTable",stream,'id,'name) + ssTableEnv.sqlQuery("select * from myTable where id > 1").execute().print() + + + //第二种:将DataStream转换为Table对象 + val table = ssTableEnv.fromDataStream(stream, $"id", $"name") + table.select($"id",$"name") + .filter($"id" > 1) + .execute() + .print() + + //注意:'id,'name 和 $"id", $"name" 这两种写法是一样的效果 + } +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/TableAPIAndSQLOpScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/TableAPIAndSQLOpScala.scala new file mode 100644 index 00000000..5e4086ab --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/TableAPIAndSQLOpScala.scala @@ -0,0 +1,58 @@ +package com.imooc.scala.tablesql + +import org.apache.flink.table.api.{EnvironmentSettings, TableEnvironment} + +/** + * TableAPI 和 SQL的使用 + * Created by xuwei + */ +object TableAPIAndSQLOpScala { + def main(args: Array[String]): Unit = { + //获取TableEnvironment + val sSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build() + val sTableEnv = TableEnvironment.create(sSettings) + + //创建输入表 + /** + * connector.type:指定connector的类型 + * connector.path:指定文件或者目录地址 + * format.type:文件数据格式化类型,现在只支持csv格式 + * 注意:SQL语句中如果出现了换行,行尾末尾可以添加空格或者\n都可以,最后一行不用添加 + */ + sTableEnv.executeSql("" + + "create table myTable(\n" + + "id int,\n" + + "name string\n" + + ") with (\n" + + "'connector.type' = 'filesystem',\n" + + "'connector.path' = 'D:\\data\\source',\n" + + "'format.type' = 'csv'\n" + + ")") + + //使用TableAPI实现数据查询和过滤等操作 + import org.apache.flink.table.api._ + /*val result = sTableEnv.from("myTable") + .select($"id", $"name") + .filter($"id" > 1)*/ + + //使用SQL实现数据查询和过滤等操作 + val result = sTableEnv.sqlQuery("select id,name from myTable where id > 1") + + //输出结果到控制台 + result.execute().print() + + //创建输出表 + sTableEnv.executeSql("" + + "create table newTable(\n" + + "id int,\n" + + "name string\n" + + ") with (\n" + + "'connector.type' = 'filesystem',\n" + + "'connector.path' = 'D:\\data\\res',\n" + + "'format.type' = 'csv'\n" + + ")") + + //输出结果到表newTable中 + result.executeInsert("newTable") + } +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/TableToDataSetScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/TableToDataSetScala.scala new file mode 100644 index 00000000..58bf9c60 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/TableToDataSetScala.scala @@ -0,0 +1,38 @@ +package com.imooc.scala.tablesql + +import org.apache.flink.api.scala.ExecutionEnvironment +import org.apache.flink.table.api.bridge.scala.BatchTableEnvironment +import org.apache.flink.types.Row + +/** + * 将table转换成DataSet + * Created by xuwei + */ +object TableToDataSetScala { + def main(args: Array[String]): Unit = { + //获取BatchTableEnvironment + val bbEnv = ExecutionEnvironment.getExecutionEnvironment + val bbTableEnv = BatchTableEnvironment.create(bbEnv) + + //创建输入表 + bbTableEnv.executeSql("" + + "create table myTable(\n" + + "id int,\n" + + "name string\n" + + ") with (\n" + + "'connector.type' = 'filesystem',\n" + + "'connector.path' = 'D:\\data\\source',\n" + + "'format.type' = 'csv'\n" + + ")") + + //获取table + val table = bbTableEnv.from("myTable") + + //将table转换成DataSet + import org.apache.flink.api.scala._ + val set = bbTableEnv.toDataSet[Row](table) + set.map(row=>(row.getField(0).toString.toInt,row.getField(1).toString)) + .print() + + } +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/TableToDataStreamScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/TableToDataStreamScala.scala new file mode 100644 index 00000000..9fb90b16 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/tablesql/TableToDataStreamScala.scala @@ -0,0 +1,54 @@ +package com.imooc.scala.tablesql + +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment +import org.apache.flink.table.api.EnvironmentSettings +import org.apache.flink.table.api.bridge.scala.StreamTableEnvironment +import org.apache.flink.types.Row + +/** + * 将table转换成DataStream + * Created by xuwei + */ +object TableToDataStreamScala { + def main(args: Array[String]): Unit = { + //获取StreamTableEnvironment + val ssEnv = StreamExecutionEnvironment.getExecutionEnvironment + val ssSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build() + val ssTableEnv = StreamTableEnvironment.create(ssEnv, ssSettings) + + //创建输入表 + ssTableEnv.executeSql("" + + "create table myTable(\n" + + "id int,\n" + + "name string\n" + + ") with (\n" + + "'connector.type' = 'filesystem',\n" + + "'connector.path' = 'D:\\data\\source',\n" + + "'format.type' = 'csv'\n" + + ")") + + //获取table + val table = ssTableEnv.from("myTable") + + //将table转换为DataStream + //如果只有新增(追加)操作,可以使用toAppendStream + import org.apache.flink.api.scala._ + val appStream = ssTableEnv.toAppendStream[Row](table) + appStream.map(row=>(row.getField(0).toString.toInt,row.getField(1).toString)) + .print() + + + //如果有增加操作,还有删除操作,则使用toRetractStream + val retStream = ssTableEnv.toRetractStream[Row](table) + retStream.map(tup=>{ + val flag = tup._1 + val row = tup._2 + val id = row.getField(0).toString.toInt + val name = row.getField(1).toString + (flag,id,name) + }).print() + + //注意:将table转换为DataStream之后,就需要调用StreamExecutionEnvironment中的execute方法了 + ssEnv.execute("TableToDataStreamScala") + } +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/window/CountWindowOpScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/window/CountWindowOpScala.scala new file mode 100644 index 00000000..47d463ab --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/window/CountWindowOpScala.scala @@ -0,0 +1,43 @@ +package com.imooc.scala.window + +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment + +/** + * CountWindow的使用 + * 1:滚动窗口 + * 2:滑动窗口 + * Created by xuwei + */ +object CountWindowOpScala { + def main(args: Array[String]): Unit = { + val env = StreamExecutionEnvironment.getExecutionEnvironment + val text = env.socketTextStream("bigdata04", 9001) + + import org.apache.flink.api.scala._ + /** + * 注意:由于我们在这里使用keyBy,会先对数据分组 + * 如果某个分组对应的数据窗口内达到了5个元素,这个窗口才会被触发执行 + */ + //CountWindow之滚动窗口:每隔5个元素计算一次前5个元素 + /*text.flatMap(_.split(" ")) + .map((_,1)) + .keyBy(0) + //指定窗口大小 + .countWindow(5) + .sum(1) + .print()*/ + + + //CountWindow之滑动窗口:每隔1个元素计算一次前5个元素 + text.flatMap(_.split(" ")) + .map((_,1)) + .keyBy(0) + //第一个参数:窗口大小,第二个参数:滑动间隔 + .countWindow(5,1) + .sum(1) + .print() + + env.execute("CountWindowOpScala") + + } +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/window/MyTimeWindowScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/window/MyTimeWindowScala.scala new file mode 100644 index 00000000..845bceeb --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/window/MyTimeWindowScala.scala @@ -0,0 +1,29 @@ +package com.imooc.scala.window + +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment +import org.apache.flink.streaming.api.windowing.assigners.TumblingProcessingTimeWindows +import org.apache.flink.streaming.api.windowing.time.Time + +/** + * 需求:自定义MyTimeWindow + * Created by xuwei + */ +object MyTimeWindowScala { + def main(args: Array[String]): Unit = { + val env = StreamExecutionEnvironment.getExecutionEnvironment + val text = env.socketTextStream("bigdata04", 9001) + + import org.apache.flink.api.scala._ + + //自定义MyTimeWindow滚动窗口:每隔10秒计算一次前10秒时间窗口内的数据 + text.flatMap(_.split(" ")) + .map((_,1)) + .keyBy(0) + //窗口大小 + .window(TumblingProcessingTimeWindows.of(Time.seconds(10))) + .sum(1) + .print() + + env.execute("MyTimeWindowScala") + } +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/window/TimeWindowOpScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/window/TimeWindowOpScala.scala new file mode 100644 index 00000000..23b1a71e --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/window/TimeWindowOpScala.scala @@ -0,0 +1,41 @@ +package com.imooc.scala.window + +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment +import org.apache.flink.streaming.api.windowing.time.Time + +/** + * TimeWindow的使用 + * 1:滚动窗口 + * 2:滑动窗口 + * Created by xuwei + */ +object TimeWindowOpScala { + def main(args: Array[String]): Unit = { + val env = StreamExecutionEnvironment.getExecutionEnvironment + val text = env.socketTextStream("bigdata04", 9001) + + import org.apache.flink.api.scala._ + + //TimeWindow之滚动窗口:每隔10秒计算一次前10秒时间窗口内的数据 + /*text.flatMap(_.split(" ")) + .map((_,1)) + .keyBy(0) + //窗口大小 + .timeWindow(Time.seconds(10)) + .sum(1) + .print()*/ + + //TimeWindow之滑动窗口:每隔5秒计算一次前10秒时间窗口内的数据 + text.flatMap(_.split(" ")) + .map((_,1)) + .keyBy(0) + //第一个参数:窗口大小,第二个参数:滑动间隔 + .timeWindow(Time.seconds(10),Time.seconds(5)) + .sum(1) + .print() + + env.execute("TimeWindowOpScala") + + } + +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/window/WatermarkOpForAllowedLatenessScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/window/WatermarkOpForAllowedLatenessScala.scala new file mode 100644 index 00000000..48fcc062 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/window/WatermarkOpForAllowedLatenessScala.scala @@ -0,0 +1,91 @@ +package com.imooc.scala.window + +import java.text.SimpleDateFormat +import java.time.Duration + +import org.apache.flink.api.common.eventtime.{SerializableTimestampAssigner, WatermarkStrategy} +import org.apache.flink.api.java.tuple.Tuple +import org.apache.flink.streaming.api.TimeCharacteristic +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment +import org.apache.flink.streaming.api.scala.function.WindowFunction +import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows +import org.apache.flink.streaming.api.windowing.time.Time +import org.apache.flink.streaming.api.windowing.windows.TimeWindow +import org.apache.flink.util.Collector + +import scala.collection.mutable.ArrayBuffer +import scala.util.Sorting + +/** + * Watermark+EventTime解决数据乱序问题 + * Created by xuwei + */ +object WatermarkOpForAllowedLatenessScala { + def main(args: Array[String]): Unit = { + val env = StreamExecutionEnvironment.getExecutionEnvironment + //设置使用数据产生的时间:EventTime + env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime) + //设置全局并行度为1 + env.setParallelism(1) + + //设置自动周期性的产生watermark,默认值为200毫秒 + env.getConfig.setAutoWatermarkInterval(200) + + + val text = env.socketTextStream("bigdata04", 9001) + import org.apache.flink.api.scala._ + //将数据转换为tuple2的形式 + //第一列表示具体的数据,第二列表示是数据产生的时间戳 + val tupStream = text.map(line => { + val arr = line.split(",") + (arr(0), arr(1).toLong) + }) + + //分配(提取)时间戳和watermark + val waterMarkStream = tupStream.assignTimestampsAndWatermarks(WatermarkStrategy.forBoundedOutOfOrderness(Duration.ofSeconds(10)) //最大允许的数据乱序时间 10s + .withTimestampAssigner(new SerializableTimestampAssigner[Tuple2[String, Long]] { + val sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + var currentMaxTimstamp = 0L + + //从数据流中抽取时间戳作为EventTime + override def extractTimestamp(element: (String, Long), recordTimestamp: Long): Long = { + val timestamp = element._2 + currentMaxTimstamp = Math.max(timestamp, currentMaxTimstamp) + //计算当前watermark,为了打印出来方便观察数据,没有别的作用,watermark=currentMaxTimstamp-OutOfOrderness + val currentWatermark = currentMaxTimstamp - 10000L + //此print语句仅仅是为了在学习阶段观察数据的变化 + println("key:" + element._1 + "," + "eventtime:[" + element._2 + "|" + sdf.format(element._2) + "],currentMaxTimstamp:[" + currentWatermark + "|" + sdf.format(currentMaxTimstamp) + "],watermark:[" + currentWatermark + "|" + sdf.format(currentWatermark) + "]") + element._2 + } + }) + ) + + waterMarkStream.keyBy(0) + //按照消息的EventTime分配窗口,和调用TimeWindow效果一样 + .window(TumblingEventTimeWindows.of(Time.seconds(3))) + //允许数据迟到2秒 + .allowedLateness(Time.seconds(2)) + //使用全量聚合的方式处理window中的数据 + .apply(new WindowFunction[Tuple2[String,Long],String,Tuple,TimeWindow] { + override def apply(key: Tuple, window: TimeWindow, input: Iterable[(String, Long)], out: Collector[String]): Unit = { + val keyStr = key.toString + //将window中的数据保存到arrBuff中 + val arrBuff = ArrayBuffer[Long]() + input.foreach(tup=>{ + arrBuff.append(tup._2) + }) + //将arrBuff转换为arr + val arr = arrBuff.toArray + //对arr中的数据进行排序 + Sorting.quickSort(arr) + + val sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + //将目前window内排序后的数据,以及window的开始时间和window的结束时间打印出来,便于观察 + val result = keyStr+","+arr.length+","+sdf.format(arr.head)+","+sdf.format(arr.last)+","+sdf.format(window.getStart)+","+sdf.format(window.getEnd) + out.collect(result) + } + }).print() + + env.execute("WatermarkOpScala") + } +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/window/WatermarkOpForSideOutputLateDataScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/window/WatermarkOpForSideOutputLateDataScala.scala new file mode 100644 index 00000000..d6636cb3 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/window/WatermarkOpForSideOutputLateDataScala.scala @@ -0,0 +1,101 @@ +package com.imooc.scala.window + +import java.text.SimpleDateFormat +import java.time.Duration + +import org.apache.flink.api.common.eventtime.{SerializableTimestampAssigner, WatermarkStrategy} +import org.apache.flink.api.java.tuple.Tuple +import org.apache.flink.streaming.api.TimeCharacteristic +import org.apache.flink.streaming.api.scala.{OutputTag, StreamExecutionEnvironment} +import org.apache.flink.streaming.api.scala.function.WindowFunction +import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows +import org.apache.flink.streaming.api.windowing.time.Time +import org.apache.flink.streaming.api.windowing.windows.TimeWindow +import org.apache.flink.util.Collector + +import scala.collection.mutable.ArrayBuffer +import scala.util.Sorting + +/** + * Watermark+EventTime解决数据乱序问题 + * Created by xuwei + */ +object WatermarkOpForSideOutputLateDataScala { + def main(args: Array[String]): Unit = { + val env = StreamExecutionEnvironment.getExecutionEnvironment + //设置使用数据产生的时间:EventTime + env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime) + //设置全局并行度为1 + env.setParallelism(1) + + //设置自动周期性的产生watermark,默认值为200毫秒 + env.getConfig.setAutoWatermarkInterval(200) + + + val text = env.socketTextStream("bigdata04", 9001) + import org.apache.flink.api.scala._ + //将数据转换为tuple2的形式 + //第一列表示具体的数据,第二列表示是数据产生的时间戳 + val tupStream = text.map(line => { + val arr = line.split(",") + (arr(0), arr(1).toLong) + }) + + //分配(提取)时间戳和watermark + val waterMarkStream = tupStream.assignTimestampsAndWatermarks(WatermarkStrategy.forBoundedOutOfOrderness(Duration.ofSeconds(10)) //最大允许的数据乱序时间 10s + .withTimestampAssigner(new SerializableTimestampAssigner[Tuple2[String, Long]] { + val sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + var currentMaxTimstamp = 0L + + //从数据流中抽取时间戳作为EventTime + override def extractTimestamp(element: (String, Long), recordTimestamp: Long): Long = { + val timestamp = element._2 + currentMaxTimstamp = Math.max(timestamp, currentMaxTimstamp) + //计算当前watermark,为了打印出来方便观察数据,没有别的作用,watermark=currentMaxTimstamp-OutOfOrderness + val currentWatermark = currentMaxTimstamp - 10000L + //此print语句仅仅是为了在学习阶段观察数据的变化 + println("key:" + element._1 + "," + "eventtime:[" + element._2 + "|" + sdf.format(element._2) + "],currentMaxTimstamp:[" + currentWatermark + "|" + sdf.format(currentMaxTimstamp) + "],watermark:[" + currentWatermark + "|" + sdf.format(currentWatermark) + "]") + element._2 + } + }) + ) + + //保存被丢弃的数据 + val outputTag = new OutputTag[Tuple2[String,Long]]("late-data") + + val resStream = waterMarkStream.keyBy(0) + //按照消息的EventTime分配窗口,和调用TimeWindow效果一样 + .window(TumblingEventTimeWindows.of(Time.seconds(3))) + //保存被丢弃的数据 + .sideOutputLateData(outputTag) + //使用全量聚合的方式处理window中的数据 + .apply(new WindowFunction[Tuple2[String, Long], String, Tuple, TimeWindow] { + override def apply(key: Tuple, window: TimeWindow, input: Iterable[(String, Long)], out: Collector[String]): Unit = { + val keyStr = key.toString + //将window中的数据保存到arrBuff中 + val arrBuff = ArrayBuffer[Long]() + input.foreach(tup => { + arrBuff.append(tup._2) + }) + //将arrBuff转换为arr + val arr = arrBuff.toArray + //对arr中的数据进行排序 + Sorting.quickSort(arr) + + val sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + //将目前window内排序后的数据,以及window的开始时间和window的结束时间打印出来,便于观察 + val result = keyStr + "," + arr.length + "," + sdf.format(arr.head) + "," + sdf.format(arr.last) + "," + sdf.format(window.getStart) + "," + sdf.format(window.getEnd) + out.collect(result) + } + }) + + //把迟到的数据取出来,暂时打印到控制台,实际工作中可以选择存储到其它存储介质中 + //例如:redis,kafka + val sideOutput = resStream.getSideOutput(outputTag) + sideOutput.print() + + //将流中的结果数据也打印到控制台 + resStream.print() + env.execute("WatermarkOpScala") + } +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/window/WatermarkOpMoreParallelismScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/window/WatermarkOpMoreParallelismScala.scala new file mode 100644 index 00000000..d7156ab0 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/window/WatermarkOpMoreParallelismScala.scala @@ -0,0 +1,90 @@ +package com.imooc.scala.window + +import java.text.SimpleDateFormat +import java.time.Duration + +import org.apache.flink.api.common.eventtime.{SerializableTimestampAssigner, WatermarkStrategy} +import org.apache.flink.api.java.tuple.Tuple +import org.apache.flink.streaming.api.TimeCharacteristic +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment +import org.apache.flink.streaming.api.scala.function.WindowFunction +import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows +import org.apache.flink.streaming.api.windowing.time.Time +import org.apache.flink.streaming.api.windowing.windows.TimeWindow +import org.apache.flink.util.Collector + +import scala.collection.mutable.ArrayBuffer +import scala.util.Sorting + +/** + * Watermark+EventTime解决数据乱序问题 + * Created by xuwei + */ +object WatermarkOpMoreParallelismScala { + def main(args: Array[String]): Unit = { + val env = StreamExecutionEnvironment.getExecutionEnvironment + //设置使用数据产生的时间:EventTime + env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime) + //设置全局并行度为1 + env.setParallelism(2) + + //设置自动周期性的产生watermark,默认值为200毫秒 + env.getConfig.setAutoWatermarkInterval(200) + + + val text = env.socketTextStream("bigdata04", 9001) + import org.apache.flink.api.scala._ + //将数据转换为tuple2的形式 + //第一列表示具体的数据,第二列表示是数据产生的时间戳 + val tupStream = text.map(line => { + val arr = line.split(",") + (arr(0), arr(1).toLong) + }) + + //分配(提取)时间戳和watermark + val waterMarkStream = tupStream.assignTimestampsAndWatermarks(WatermarkStrategy.forBoundedOutOfOrderness(Duration.ofSeconds(10)) //最大允许的数据乱序时间 10s + .withTimestampAssigner(new SerializableTimestampAssigner[Tuple2[String, Long]] { + val sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + var currentMaxTimstamp = 0L + + //从数据流中抽取时间戳作为EventTime + override def extractTimestamp(element: (String, Long), recordTimestamp: Long): Long = { + val timestamp = element._2 + currentMaxTimstamp = Math.max(timestamp, currentMaxTimstamp) + //计算当前watermark,为了打印出来方便观察数据,没有别的作用,watermark=currentMaxTimstamp-OutOfOrderness + val currentWatermark = currentMaxTimstamp - 10000L + val threadId = Thread.currentThread().getId + //此print语句仅仅是为了在学习阶段观察数据的变化 + println("threadId:"+threadId+",key:" + element._1 + "," + "eventtime:[" + element._2 + "|" + sdf.format(element._2) + "],currentMaxTimstamp:[" + currentWatermark + "|" + sdf.format(currentMaxTimstamp) + "],watermark:[" + currentWatermark + "|" + sdf.format(currentWatermark) + "]") + element._2 + } + }) + ) + + waterMarkStream.keyBy(0) + //按照消息的EventTime分配窗口,和调用TimeWindow效果一样 + .window(TumblingEventTimeWindows.of(Time.seconds(3))) + //使用全量聚合的方式处理window中的数据 + .apply(new WindowFunction[Tuple2[String,Long],String,Tuple,TimeWindow] { + override def apply(key: Tuple, window: TimeWindow, input: Iterable[(String, Long)], out: Collector[String]): Unit = { + val keyStr = key.toString + //将window中的数据保存到arrBuff中 + val arrBuff = ArrayBuffer[Long]() + input.foreach(tup=>{ + arrBuff.append(tup._2) + }) + //将arrBuff转换为arr + val arr = arrBuff.toArray + //对arr中的数据进行排序 + Sorting.quickSort(arr) + + val sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + //将目前window内排序后的数据,以及window的开始时间和window的结束时间打印出来,便于观察 + val result = keyStr+","+arr.length+","+sdf.format(arr.head)+","+sdf.format(arr.last)+","+sdf.format(window.getStart)+","+sdf.format(window.getEnd) + out.collect(result) + } + }).print() + + env.execute("WatermarkOpScala") + } +} diff --git a/bigdata/flink/src/main/scala/com/imooc/scala/window/WatermarkOpScala.scala b/bigdata/flink/src/main/scala/com/imooc/scala/window/WatermarkOpScala.scala new file mode 100644 index 00000000..cb2b18b4 --- /dev/null +++ b/bigdata/flink/src/main/scala/com/imooc/scala/window/WatermarkOpScala.scala @@ -0,0 +1,89 @@ +package com.imooc.scala.window + +import java.text.SimpleDateFormat +import java.time.Duration + +import org.apache.flink.api.common.eventtime.{SerializableTimestampAssigner, WatermarkStrategy} +import org.apache.flink.api.java.tuple.Tuple +import org.apache.flink.streaming.api.TimeCharacteristic +import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment +import org.apache.flink.streaming.api.scala.function.WindowFunction +import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows +import org.apache.flink.streaming.api.windowing.time.Time +import org.apache.flink.streaming.api.windowing.windows.TimeWindow +import org.apache.flink.util.Collector + +import scala.collection.mutable.ArrayBuffer +import scala.util.Sorting + +/** + * Watermark+EventTime解决数据乱序问题 + * Created by xuwei + */ +object WatermarkOpScala { + def main(args: Array[String]): Unit = { + val env = StreamExecutionEnvironment.getExecutionEnvironment + //设置使用数据产生的时间:EventTime + env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime) + //设置全局并行度为1 + env.setParallelism(1) + + //设置自动周期性的产生watermark,默认值为200毫秒 + env.getConfig.setAutoWatermarkInterval(200) + + + val text = env.socketTextStream("bigdata04", 9001) + import org.apache.flink.api.scala._ + //将数据转换为tuple2的形式 + //第一列表示具体的数据,第二列表示是数据产生的时间戳 + val tupStream = text.map(line => { + val arr = line.split(",") + (arr(0), arr(1).toLong) + }) + + //分配(提取)时间戳和watermark + val waterMarkStream = tupStream.assignTimestampsAndWatermarks(WatermarkStrategy.forBoundedOutOfOrderness(Duration.ofSeconds(10)) //最大允许的数据乱序时间 10s + .withTimestampAssigner(new SerializableTimestampAssigner[Tuple2[String, Long]] { + val sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + var currentMaxTimstamp = 0L + + //从数据流中抽取时间戳作为EventTime + override def extractTimestamp(element: (String, Long), recordTimestamp: Long): Long = { + val timestamp = element._2 + currentMaxTimstamp = Math.max(timestamp, currentMaxTimstamp) + //计算当前watermark,为了打印出来方便观察数据,没有别的作用,watermark=currentMaxTimstamp-OutOfOrderness + val currentWatermark = currentMaxTimstamp - 10000L + //此print语句仅仅是为了在学习阶段观察数据的变化 + println("key:" + element._1 + "," + "eventtime:[" + element._2 + "|" + sdf.format(element._2) + "],currentMaxTimstamp:[" + currentWatermark + "|" + sdf.format(currentMaxTimstamp) + "],watermark:[" + currentWatermark + "|" + sdf.format(currentWatermark) + "]") + element._2 + } + }) + ) + + waterMarkStream.keyBy(0) + //按照消息的EventTime分配窗口,和调用TimeWindow效果一样 + .window(TumblingEventTimeWindows.of(Time.seconds(3))) + //使用全量聚合的方式处理window中的数据 + .apply(new WindowFunction[Tuple2[String,Long],String,Tuple,TimeWindow] { + override def apply(key: Tuple, window: TimeWindow, input: Iterable[(String, Long)], out: Collector[String]): Unit = { + val keyStr = key.toString + //将window中的数据保存到arrBuff中 + val arrBuff = ArrayBuffer[Long]() + input.foreach(tup=>{ + arrBuff.append(tup._2) + }) + //将arrBuff转换为arr + val arr = arrBuff.toArray + //对arr中的数据进行排序 + Sorting.quickSort(arr) + + val sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + //将目前window内排序后的数据,以及window的开始时间和window的结束时间打印出来,便于观察 + val result = keyStr+","+arr.length+","+sdf.format(arr.head)+","+sdf.format(arr.last)+","+sdf.format(window.getStart)+","+sdf.format(window.getEnd) + out.collect(result) + } + }).print() + + env.execute("WatermarkOpScala") + } +} diff --git a/bigdata/hadoop/hdfs/pom.xml b/bigdata/hadoop/hdfs/pom.xml new file mode 100644 index 00000000..52c6b311 --- /dev/null +++ b/bigdata/hadoop/hdfs/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + hdfs + cn.cunchang + 1.0-SNAPSHOT + + + 8 + 8 + + + + + + + org.apache.hadoop + hadoop-client + 3.2.0 + + + + + + org.slf4j + slf4j-api + 1.7.10 + + + org.slf4j + slf4j-log4j12 + 1.7.10 + + + + + \ No newline at end of file diff --git a/bigdata/hadoop/hdfs/src/main/java/cn/cunchang/HdfsOp.java b/bigdata/hadoop/hdfs/src/main/java/cn/cunchang/HdfsOp.java new file mode 100644 index 00000000..6550c40f --- /dev/null +++ b/bigdata/hadoop/hdfs/src/main/java/cn/cunchang/HdfsOp.java @@ -0,0 +1,83 @@ +package cn.cunchang; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FSDataInputStream; +import org.apache.hadoop.fs.FSDataOutputStream; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.io.IOUtils; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * Java代码操作HDFS + * 文件操作:上传文件,下载文件,删除文件 + * + */ +public class HdfsOp { + + public static void main(String[] args) throws Exception{ + //创建一个配置对象 + Configuration conf = new Configuration(); + //指定HDFS的地址 + conf.set("fs.defaultFS","hdfs://localhost:9000"); + //获取操作HDFS的对象 + FileSystem fileSystem = FileSystem.get(conf); + + //上传文件 + put(fileSystem); + //下载文件 +// get(fileSystem); + //删除文件 +// delete(fileSystem); + + } + + /** + * 删除文件或者目录 + * @param fileSystem + * @throws IOException + */ + private static void delete(FileSystem fileSystem) throws IOException { + //删除文件,目录也可以删除 + //如果要递归删除目录,则第二个参数需要设置为true + //如果删除的是文件或者空目录,第二个参数会被忽略 + boolean flag = fileSystem.delete(new Path("/README.txt"),true); + if(flag){ + System.out.println("删除成功!"); + }else{ + System.out.println("删除失败!"); + } + } + + /** + * 下载文件 + * @param fileSystem + * @throws IOException + */ + private static void get(FileSystem fileSystem) throws IOException { + //获取HDFS文件系统中的输入流 + FSDataInputStream fis = fileSystem.open(new Path("/README.txt")); + //获取本地文件的输出流 + FileOutputStream fos = new FileOutputStream("/Users/cunchang/workspace/github/code/bigdata/hadoop/README.txt"); + //下载文件 + IOUtils.copyBytes(fis,fos,1024,true); + } + + /** + * 上传文件 + * @param fileSystem + * @throws IOException + */ + private static void put(FileSystem fileSystem) throws IOException { + //获取本地文件的输入流 + FileInputStream fis = new FileInputStream("/data/soft/hadoop-3.2.0/README.txt"); + //获取HDFS文件系统的输出流 + FSDataOutputStream fos = fileSystem.create(new Path("/README.txt")); + //上传文件:通过工具类把输入流拷贝到输出流里面,实现本地文件上传到HDFS + IOUtils.copyBytes(fis,fos,1024,true); + } + +} diff --git a/bigdata/hadoop/hdfs/src/main/resources/log4j.properties b/bigdata/hadoop/hdfs/src/main/resources/log4j.properties new file mode 100644 index 00000000..ddf8c805 --- /dev/null +++ b/bigdata/hadoop/hdfs/src/main/resources/log4j.properties @@ -0,0 +1,9 @@ +log4j.rootLogger=info,stdout + +log4j.appender.stdout = org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target = System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c] [%p] - %m%n + + + diff --git a/bigdata/hadoop/mapreduce/pom.xml b/bigdata/hadoop/mapreduce/pom.xml new file mode 100644 index 00000000..672940ae --- /dev/null +++ b/bigdata/hadoop/mapreduce/pom.xml @@ -0,0 +1,81 @@ + + + 4.0.0 + + cn.cunchang + mapreduce + 1.0-SNAPSHOT + + + 8 + 8 + + + + + + org.apache.hadoop + hadoop-client + 3.2.0 + + provided + + + + + org.slf4j + slf4j-api + 1.7.10 + provided + + + org.slf4j + slf4j-log4j12 + 1.7.10 + provided + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + UTF-8 + 1.8 + 1.8 + true + + + + maven-assembly-plugin + + + jar-with-dependencies + + + + + + + + + + make-assembly + package + + single + + + + + + + + \ No newline at end of file diff --git a/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/GenerateDat.java b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/GenerateDat.java new file mode 100644 index 00000000..66f2e660 --- /dev/null +++ b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/GenerateDat.java @@ -0,0 +1,57 @@ +package cn.cunchang.mr; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; + +/** + * 生成测试数据 + * 1: + * Created by xuwei + */ +public class GenerateDat { + public static void main(String[] args) throws Exception{ + generate_140M(); + generate_141M(); + } + + /** + * 生成141M文件 + * @throws IOException + */ + private static void generate_141M() throws IOException { + String fileName = "D:\\s_name_141.dat"; + System.out.println("start: 开始生成141M文件->"+fileName); + BufferedWriter bfw = new BufferedWriter(new FileWriter(fileName)); + int num = 0; + while(num<8221592){ + bfw.write("zhangsan beijing"); + bfw.newLine(); + num ++; + if(num%10000==0){ + bfw.flush(); + } + } + System.out.println("end: 141M文件已生成"); + } + + /** + * 生成140M文件 + * @throws IOException + */ + private static void generate_140M() throws IOException { + String fileName = "D:\\s_name_140.dat"; + System.out.println("start: 开始生成140M文件->"+fileName); + BufferedWriter bfw = new BufferedWriter(new FileWriter(fileName)); + int num = 0; + while(num<8201592){ + bfw.write("zhangsan beijing"); + bfw.newLine(); + num ++; + if(num%10000==0){ + bfw.flush(); + } + } + System.out.println("end: 140M文件已生成"); + } +} diff --git a/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/HadoopSerialize.java b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/HadoopSerialize.java new file mode 100644 index 00000000..655d4f83 --- /dev/null +++ b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/HadoopSerialize.java @@ -0,0 +1,58 @@ +package cn.cunchang.mr; + +import org.apache.hadoop.io.Writable; + +import java.io.*; + +/** + * Hadoop序列化机制 + * Created by xuwei + */ +public class HadoopSerialize { + public static void main(String[] args) throws Exception{ + //创建Student对象,并设置id和name属性 + StudentWritable studentWritable = new StudentWritable(); + studentWritable.setId(1L); + studentWritable.setName("Hadoop"); + + //将Student对象的当前状态写入本地文件中 + FileOutputStream fos = new FileOutputStream("D:\\student_hadoop.txt"); + ObjectOutputStream oos = new ObjectOutputStream(fos); + studentWritable.write(oos); + oos.close(); + fos.close(); + } +} + +class StudentWritable implements Writable{ + private Long id; + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public void write(DataOutput out) throws IOException { + out.writeLong(this.id); + out.writeUTF(this.name); + } + + @Override + public void readFields(DataInput in) throws IOException { + this.id = in.readLong(); + this.name = in.readUTF(); + } +} diff --git a/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/JavaSerialize.java b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/JavaSerialize.java new file mode 100644 index 00000000..43915042 --- /dev/null +++ b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/JavaSerialize.java @@ -0,0 +1,47 @@ +package cn.cunchang.mr; + +import java.io.FileOutputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +/** + * Java中的序列化 + * Created by xuwei + */ +public class JavaSerialize { + public static void main(String[] args) throws Exception{ + //创建Student对象,并设置id和name属性 + StudentJava studentJava = new StudentJava(); + studentJava.setId(1L); + studentJava.setName("Hadoop"); + + //将Student对象的当前状态写入本地文件中 + FileOutputStream fos = new FileOutputStream("D:\\student_java.txt"); + ObjectOutputStream oos = new ObjectOutputStream(fos); + oos.writeObject(studentJava); + oos.close(); + fos.close(); + } +} + +class StudentJava implements Serializable{ + private static final long serialVersionUID = 1L; + private Long id; + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/README.md b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/README.md new file mode 100644 index 00000000..8aff41fa --- /dev/null +++ b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/README.md @@ -0,0 +1,11 @@ + +# mapreduce +mapreduce模块下的类,都要放到hadoop上执行 + +WordCountJob +JavaSerialize、HadoopSerialize + + +# yarn +WordCountJobQueue + diff --git a/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/SmallFileMap.java b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/SmallFileMap.java new file mode 100644 index 00000000..542bf740 --- /dev/null +++ b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/SmallFileMap.java @@ -0,0 +1,101 @@ +package cn.cunchang.mr; + +import org.apache.commons.io.FileUtils; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.io.MapFile; +import org.apache.hadoop.io.SequenceFile; +import org.apache.hadoop.io.Text; + +import java.io.File; + +/** + * 小文件解决方案之MapFile + * Created by xuwei + */ +public class SmallFileMap { + + public static void main(String[] args) throws Exception{ + //生成MapFile文件 + write("D:\\smallFile","/mapFile"); + //读取MapFile文件 + read("/mapFile"); + } + + /** + * 生成MapFile文件 + * @param inputDir 输入目录-windows目录 + * @param outputDir 输出目录-hdfs目录 + * @throws Exception + */ + private static void write(String inputDir,String outputDir) throws Exception{ + //创建一个配置对象 + Configuration conf = new Configuration(); + //指定HDFS的地址 + conf.set("fs.defaultFS","hdfs://bigdata01:9000"); + + //获取操作HDFD的对象 + FileSystem fileSystem = FileSystem.get(conf); + + //删除HDFS上的输出文件 + fileSystem.delete(new Path(outputDir),true); + + //构造opts数组,有两个元素 + /* + 第一个是key的类型 + 第二个是value的类型 + */ + SequenceFile.Writer.Option[] opts = new SequenceFile.Writer.Option[]{ + MapFile.Writer.keyClass(Text.class), + MapFile.Writer.valueClass(Text.class) + }; + //创建了一个writer实例 + MapFile.Writer writer = new MapFile.Writer(conf, new Path(outputDir), opts); + + //指定需要压缩的文件的目录 + File inputDirPath = new File(inputDir); + if(inputDirPath.isDirectory()){ + //获取目录中的文件 + File[] files = inputDirPath.listFiles(); + //迭代文件 + for (File file: files) { + //获取文件的全部内容 + String content = FileUtils.readFileToString(file, "UTF-8"); + //获取文件名 + String fileName = file.getName(); + Text key = new Text(fileName); + Text value = new Text(content); + //向SequenceFile中写入数据 + writer.append(key,value); + } + } + writer.close(); + } + + /** + * 读取MapFile文件 + * @param inputDir MapFile文件路径 + * @throws Exception + */ + private static void read(String inputDir)throws Exception{ + //创建一个配置对象 + Configuration conf = new Configuration(); + //指定HDFS的地址 + conf.set("fs.defaultFS","hdfs://bigdata01:9000"); + //创建阅读器 + MapFile.Reader reader = new MapFile.Reader(new Path(inputDir),conf); + Text key = new Text(); + Text value = new Text(); + //循环读取数据 + while(reader.next(key,value)){ + //输出文件名称 + System.out.print("文件名:"+key.toString()+","); + //输出文件内容 + System.out.println("文件内容:"+value.toString()+""); + } + reader.close(); + } + + +} diff --git a/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/SmallFileSeq.java b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/SmallFileSeq.java new file mode 100644 index 00000000..d5b68b61 --- /dev/null +++ b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/SmallFileSeq.java @@ -0,0 +1,102 @@ +package cn.cunchang.mr; + +import org.apache.commons.io.FileUtils; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.io.SequenceFile; +import org.apache.hadoop.io.Text; + +import java.io.File; + +/** + * 小文件解决方案之SequenceFile + * Created by xuwei + */ +public class SmallFileSeq { + + public static void main(String[] args) throws Exception{ + //生成SequenceFile文件 + write("D:\\smallFile","/seqFile"); + //读取SequenceFile文件 + read("/seqFile"); + } + + + /** + * 生成SequenceFile文件 + * @param inputDir 输入目录-windows目录 + * @param outputFile 输出文件-hdfs文件 + * @throws Exception + */ + private static void write(String inputDir,String outputFile) throws Exception{ + //创建一个配置对象 + Configuration conf = new Configuration(); + //指定HDFS的地址 + conf.set("fs.defaultFS","hdfs://bigdata01:9000"); + + //获取操作HDFD的对象 + FileSystem fileSystem = FileSystem.get(conf); + + //删除HDFS上的输出文件 + fileSystem.delete(new Path(outputFile),true); + + //构造opts数组,有三个元素 + /* + 第一个是输出路径【文件】 + 第二个是key的类型 + 第三个是value的类型 + */ + SequenceFile.Writer.Option[] opts = new SequenceFile.Writer.Option[]{ + SequenceFile.Writer.file(new Path(outputFile)), + SequenceFile.Writer.keyClass(Text.class), + SequenceFile.Writer.valueClass(Text.class) + }; + //创建了一个writer实例 + SequenceFile.Writer writer = SequenceFile.createWriter(conf, opts); + + //指定需要压缩的文件的目录 + File inputDirPath = new File(inputDir); + if(inputDirPath.isDirectory()){ + //获取目录中的文件 + File[] files = inputDirPath.listFiles(); + //迭代文件 + for (File file: files) { + //获取文件的全部内容 + String content = FileUtils.readFileToString(file, "UTF-8"); + //获取文件名 + String fileName = file.getName(); + Text key = new Text(fileName); + Text value = new Text(content); + //向SequenceFile中写入数据 + writer.append(key,value); + } + } + writer.close(); + } + + /** + * 读取SequenceFile文件 + * @param inputFile SequenceFile文件路径 + * @throws Exception + */ + private static void read(String inputFile) throws Exception{ + //创建一个配置对象 + Configuration conf = new Configuration(); + //指定HDFS的地址 + conf.set("fs.defaultFS","hdfs://bigdata01:9000"); + //创建阅读器 + SequenceFile.Reader reader = new SequenceFile.Reader(conf, SequenceFile.Reader.file(new Path(inputFile))); + Text key = new Text(); + Text value = new Text(); + //循环读取数据 + while(reader.next(key,value)){ + //输出文件名称 + System.out.print("文件名:"+key.toString()+","); + //输出文件内容 + System.out.println("文件内容:"+value.toString()+""); + } + reader.close(); + } + +} diff --git a/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJob.java b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJob.java new file mode 100644 index 00000000..912021b5 --- /dev/null +++ b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJob.java @@ -0,0 +1,152 @@ +package cn.cunchang.mr; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.io.LongWritable; +import org.apache.hadoop.io.Text; +import org.apache.hadoop.mapreduce.Job; +import org.apache.hadoop.mapreduce.Mapper; +import org.apache.hadoop.mapreduce.Reducer; +import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; +import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +/** + * 需求:读取hdfs上的hello.txt文件,计算文件中每个单词出现的总次数 + *

+ * 原始文件hello.txt内容如下: + * hello you + * hello me + *

+ * 最终需要的结果形式如下: + * hello 2 + * me 1 + * you 1 + *

+ * Created by xuwei + */ +public class WordCountJob { + /** + * Map阶段 + */ + public static class MyMapper extends Mapper { + Logger logger = LoggerFactory.getLogger(MyMapper.class); + + /** + * 需要实现map函数 + * 这个map函数就是可以接收,产生 + * + * @param k1 + * @param v1 + * @param context + * @throws IOException + * @throws InterruptedException + */ + @Override + protected void map(LongWritable k1, Text v1, Context context) + throws IOException, InterruptedException { + //输出k1,v1的值 + logger.info("=<"+k1.get()+","+v1.toString()+">"); + //k1 代表的是每一行数据的行首偏移量,v1代表的是每一行内容 + //对获取到的每一行数据进行切割,把单词切割出来 + String[] words = v1.toString().split(" "); + //迭代切割出来的单词数据 + for (String word : words) { + //把迭代出来的单词封装成的形式 + Text k2 = new Text(word); + LongWritable v2 = new LongWritable(1L); + //把写出去 + context.write(k2, v2); + } + } + } + + + /** + * Reduce阶段 + */ + public static class MyReducer extends Reducer { + Logger logger = LoggerFactory.getLogger(MyReducer.class); + + /** + * 针对的数据进行累加求和,并且最终把数据转化为k3,v3写出去 + * + * @param k2 + * @param v2s + * @param context + * @throws IOException + * @throws InterruptedException + */ + @Override + protected void reduce(Text k2, Iterable v2s, Context context) + throws IOException, InterruptedException { + //创建一个sum变量,保存v2s的和 + long sum = 0L; + //对v2s中的数据进行累加求和 + for (LongWritable v2 : v2s) { + //输出k2,v2的值 + logger.info("=<"+k2.toString()+","+v2.get()+">"); + sum += v2.get(); + } + + //组装k3,v3 + Text k3 = k2; + LongWritable v3 = new LongWritable(sum); + //输出k3,v3的值 + logger.info("=<"+k3.toString()+","+v3.get()+">"); + // 把结果写出去 + context.write(k3, v3); + } + } + + /** + * 组装Job=Map+Reduce + */ + public static void main(String[] args) { + try { + if (args.length != 2) { + //如果传递的参数不够,程序直接退出 + System.exit(100); + } + + //指定Job需要的配置参数 + Configuration conf = new Configuration(); + //创建一个Job + Job job = Job.getInstance(conf); + + //注意了:这一行必须设置,否则在集群中执行的时候是找不到WordCountJob这个类的 + job.setJarByClass(WordCountJob.class); + + //指定输入路径(可以是文件,也可以是目录) + FileInputFormat.setInputPaths(job, new Path(args[0])); + //指定输出路径(只能指定一个不存在的目录) + FileOutputFormat.setOutputPath(job, new Path(args[1])); + + //指定map相关的代码 + job.setMapperClass(MyMapper.class); + //指定k2的类型 + job.setMapOutputKeyClass(Text.class); + //指定v2的类型 + job.setMapOutputValueClass(LongWritable.class); + + + //指定reduce相关的代码 + job.setReducerClass(MyReducer.class); + //指定k3的类型 + job.setOutputKeyClass(Text.class); + //指定v3的类型 + job.setOutputValueClass(LongWritable.class); + + //提交job + job.waitForCompletion(true); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + +} diff --git a/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJobNoReduce.java b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJobNoReduce.java new file mode 100644 index 00000000..7db549e8 --- /dev/null +++ b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJobNoReduce.java @@ -0,0 +1,101 @@ +package cn.cunchang.mr; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.io.LongWritable; +import org.apache.hadoop.io.Text; +import org.apache.hadoop.mapreduce.Job; +import org.apache.hadoop.mapreduce.Mapper; +import org.apache.hadoop.mapreduce.Reducer; +import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; +import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +/** + * 只有Map阶段,不包含Reduce阶段 + * + * Created by xuwei + */ +public class WordCountJobNoReduce { + /** + * Map阶段 + */ + public static class MyMapper extends Mapper{ + Logger logger = LoggerFactory.getLogger(MyMapper.class); + /** + * 需要实现map函数 + * 这个map函数就是可以接收,产生 + * @param k1 + * @param v1 + * @param context + * @throws IOException + * @throws InterruptedException + */ + @Override + protected void map(LongWritable k1, Text v1, Context context) + throws IOException, InterruptedException { + //输出k1,v1的值 + logger.info("=<"+k1.get()+","+v1.toString()+">"); + //k1 代表的是每一行数据的行首偏移量,v1代表的是每一行内容 + //对获取到的每一行数据进行切割,把单词切割出来 + String[] words = v1.toString().split(" "); + //迭代切割出来的单词数据 + for (String word : words) { + //把迭代出来的单词封装成的形式 + Text k2 = new Text(word); + LongWritable v2 = new LongWritable(1L); + //把写出去 + context.write(k2,v2); + } + } + } + + + + + /** + * 组装Job=Map+Reduce + */ + public static void main(String[] args) { + try{ + if(args.length!=2){ + //如果传递的参数不够,程序直接退出 + System.exit(100); + } + + //指定Job需要的配置参数 + Configuration conf = new Configuration(); + //创建一个Job + Job job = Job.getInstance(conf); + + //注意了:这一行必须设置,否则在集群中执行的时候是找不到WordCountJob这个类的 + job.setJarByClass(WordCountJobNoReduce.class); + + //指定输入路径(可以是文件,也可以是目录) + FileInputFormat.setInputPaths(job,new Path(args[0])); + //指定输出路径(只能指定一个不存在的目录) + FileOutputFormat.setOutputPath(job,new Path(args[1])); + + //指定map相关的代码 + job.setMapperClass(MyMapper.class); + //指定k2的类型 + job.setMapOutputKeyClass(Text.class); + //指定v2的类型 + job.setMapOutputValueClass(LongWritable.class); + + //禁用Reduce + job.setNumReduceTasks(0); + + //提交job + job.waitForCompletion(true); + }catch(Exception e){ + e.printStackTrace(); + } + + } + + +} diff --git a/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJobQueue.java b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJobQueue.java new file mode 100644 index 00000000..6f3c7638 --- /dev/null +++ b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJobQueue.java @@ -0,0 +1,139 @@ +package cn.cunchang.mr; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.io.LongWritable; +import org.apache.hadoop.io.Text; +import org.apache.hadoop.mapreduce.Job; +import org.apache.hadoop.mapreduce.Mapper; +import org.apache.hadoop.mapreduce.Reducer; +import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; +import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; +import org.apache.hadoop.util.GenericOptionsParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +/** + * 指定队列名称 + * + * Created by xuwei + */ +public class WordCountJobQueue { + /** + * Map阶段 + */ + public static class MyMapper extends Mapper{ + Logger logger = LoggerFactory.getLogger(MyMapper.class); + /** + * 需要实现map函数 + * 这个map函数就是可以接收,产生 + * @param k1 + * @param v1 + * @param context + * @throws IOException + * @throws InterruptedException + */ + @Override + protected void map(LongWritable k1, Text v1, Context context) + throws IOException, InterruptedException { + //输出k1,v1的值 + logger.info("=<"+k1.get()+","+v1.toString()+">"); + //k1 代表的是每一行数据的行首偏移量,v1代表的是每一行内容 + //对获取到的每一行数据进行切割,把单词切割出来 + String[] words = v1.toString().split(" "); + //迭代切割出来的单词数据 + for (String word : words) { + //把迭代出来的单词封装成的形式 + Text k2 = new Text(word); + LongWritable v2 = new LongWritable(1L); + //把写出去 + context.write(k2,v2); + } + } + } + + + /** + * Reduce阶段 + */ + public static class MyReducer extends Reducer{ + Logger logger = LoggerFactory.getLogger(MyReducer.class); + /** + * 针对的数据进行累加求和,并且最终把数据转化为k3,v3写出去 + * @param k2 + * @param v2s + * @param context + * @throws IOException + * @throws InterruptedException + */ + @Override + protected void reduce(Text k2, Iterable v2s, Context context) + throws IOException, InterruptedException { + //创建一个sum变量,保存v2s的和 + long sum = 0L; + //对v2s中的数据进行累加求和 + for(LongWritable v2: v2s){ + //输出k2,v2的值 + logger.info("=<"+k2.toString()+","+v2.get()+">"); + sum += v2.get(); + } + + //组装k3,v3 + Text k3 = k2; + LongWritable v3 = new LongWritable(sum); + //输出k3,v3的值 + logger.info("=<"+k3.toString()+","+v3.get()+">"); + // 把结果写出去 + context.write(k3,v3); + } + } + + /** + * 组装Job=Map+Reduce + */ + public static void main(String[] args) { + try{ + + //指定Job需要的配置参数 + Configuration conf = new Configuration(); + //解析命令行中通过-D传递过来的参数,添加到conf中 + String[] remainingArgs = new GenericOptionsParser(conf, args).getRemainingArgs(); + + //创建一个Job + Job job = Job.getInstance(conf); + + //注意了:这一行必须设置,否则在集群中执行的时候是找不到WordCountJob这个类的 + job.setJarByClass(WordCountJobQueue.class); + + //指定输入路径(可以是文件,也可以是目录) + FileInputFormat.setInputPaths(job,new Path(remainingArgs[0])); + //指定输出路径(只能指定一个不存在的目录) + FileOutputFormat.setOutputPath(job,new Path(remainingArgs[1])); + + //指定map相关的代码 + job.setMapperClass(MyMapper.class); + //指定k2的类型 + job.setMapOutputKeyClass(Text.class); + //指定v2的类型 + job.setMapOutputValueClass(LongWritable.class); + + + //指定reduce相关的代码 + job.setReducerClass(MyReducer.class); + //指定k3的类型 + job.setOutputKeyClass(Text.class); + //指定v3的类型 + job.setOutputValueClass(LongWritable.class); + + //提交job + job.waitForCompletion(true); + }catch(Exception e){ + e.printStackTrace(); + } + + } + + +} diff --git a/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJobSeq.java b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJobSeq.java new file mode 100644 index 00000000..6d359f7e --- /dev/null +++ b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJobSeq.java @@ -0,0 +1,146 @@ +package cn.cunchang.mr; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.io.LongWritable; +import org.apache.hadoop.io.Text; +import org.apache.hadoop.mapreduce.Job; +import org.apache.hadoop.mapreduce.Mapper; +import org.apache.hadoop.mapreduce.Reducer; +import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; +import org.apache.hadoop.mapreduce.lib.input.SequenceFileInputFormat; +import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +/** + * 需求:读取SequenceFile文件 + * + * Created by xuwei + */ +public class WordCountJobSeq { + /** + * Map阶段 + */ + public static class MyMapper extends Mapper{ + Logger logger = LoggerFactory.getLogger(MyMapper.class); + /** + * 需要实现map函数 + * 这个map函数就是可以接收,产生 + * @param k1 + * @param v1 + * @param context + * @throws IOException + * @throws InterruptedException + */ + @Override + protected void map(Text k1, Text v1, Context context) + throws IOException, InterruptedException { + //输出k1,v1的值 + System.out.println("=<"+k1.toString()+","+v1.toString()+">"); + //logger.info("=<"+k1.get()+","+v1.toString()+">"); + //k1 代表的是每一行数据的行首偏移量,v1代表的是每一行内容 + //对获取到的每一行数据进行切割,把单词切割出来 + String[] words = v1.toString().split(" "); + //迭代切割出来的单词数据 + for (String word : words) { + //把迭代出来的单词封装成的形式 + Text k2 = new Text(word); + LongWritable v2 = new LongWritable(1L); + //把写出去 + context.write(k2,v2); + } + } + } + + + /** + * Reduce阶段 + */ + public static class MyReducer extends Reducer{ + Logger logger = LoggerFactory.getLogger(MyReducer.class); + /** + * 针对的数据进行累加求和,并且最终把数据转化为k3,v3写出去 + * @param k2 + * @param v2s + * @param context + * @throws IOException + * @throws InterruptedException + */ + @Override + protected void reduce(Text k2, Iterable v2s, Context context) + throws IOException, InterruptedException { + //创建一个sum变量,保存v2s的和 + long sum = 0L; + //对v2s中的数据进行累加求和 + for(LongWritable v2: v2s){ + //输出k2,v2的值 + //System.out.println("=<"+k2.toString()+","+v2.get()+">"); + //logger.info("=<"+k2.toString()+","+v2.get()+">"); + sum += v2.get(); + } + + //组装k3,v3 + Text k3 = k2; + LongWritable v3 = new LongWritable(sum); + //输出k3,v3的值 + //System.out.println("=<"+k3.toString()+","+v3.get()+">"); + //logger.info("=<"+k3.toString()+","+v3.get()+">"); + // 把结果写出去 + context.write(k3,v3); + } + } + + /** + * 组装Job=Map+Reduce + */ + public static void main(String[] args) { + try{ + if(args.length!=2){ + //如果传递的参数不够,程序直接退出 + System.exit(100); + } + + //指定Job需要的配置参数 + Configuration conf = new Configuration(); + //创建一个Job + Job job = Job.getInstance(conf); + + //注意了:这一行必须设置,否则在集群中执行的时候是找不到WordCountJob这个类的 + job.setJarByClass(WordCountJobSeq.class); + + //指定输入路径(可以是文件,也可以是目录) + FileInputFormat.setInputPaths(job,new Path(args[0])); + //指定输出路径(只能指定一个不存在的目录) + FileOutputFormat.setOutputPath(job,new Path(args[1])); + + //指定map相关的代码 + job.setMapperClass(MyMapper.class); + //指定k2的类型 + job.setMapOutputKeyClass(Text.class); + //指定v2的类型 + job.setMapOutputValueClass(LongWritable.class); + + //设置输入数据处理类 + job.setInputFormatClass(SequenceFileInputFormat.class); + + + //指定reduce相关的代码 + job.setReducerClass(MyReducer.class); + //指定k3的类型 + job.setOutputKeyClass(Text.class); + //指定v3的类型 + job.setOutputValueClass(LongWritable.class); + + //提交job + job.waitForCompletion(true); + }catch(Exception e){ + e.printStackTrace(); + } + + } + + +} diff --git a/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJobSkew.java b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJobSkew.java new file mode 100644 index 00000000..6512784c --- /dev/null +++ b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJobSkew.java @@ -0,0 +1,146 @@ +package cn.cunchang.mr; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.io.LongWritable; +import org.apache.hadoop.io.Text; +import org.apache.hadoop.mapreduce.Job; +import org.apache.hadoop.mapreduce.Mapper; +import org.apache.hadoop.mapreduce.Reducer; +import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; +import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +/** + * 数据倾斜-增加Reduce任务个数 + * + * Created by xuwei + */ +public class WordCountJobSkew { + /** + * Map阶段 + */ + public static class MyMapper extends Mapper{ + Logger logger = LoggerFactory.getLogger(MyMapper.class); + /** + * 需要实现map函数 + * 这个map函数就是可以接收,产生 + * @param k1 + * @param v1 + * @param context + * @throws IOException + * @throws InterruptedException + */ + @Override + protected void map(LongWritable k1, Text v1, Context context) + throws IOException, InterruptedException { + //输出k1,v1的值 + //System.out.println("=<"+k1.get()+","+v1.toString()+">"); + //logger.info("=<"+k1.get()+","+v1.toString()+">"); + //k1 代表的是每一行数据的行首偏移量,v1代表的是每一行内容 + //对获取到的每一行数据进行切割,把单词切割出来 + String[] words = v1.toString().split(" "); + //把迭代出来的单词封装成的形式 + Text k2 = new Text(words[0]); + LongWritable v2 = new LongWritable(1L); + //把写出去 + context.write(k2,v2); + } + } + + + /** + * Reduce阶段 + */ + public static class MyReducer extends Reducer{ + Logger logger = LoggerFactory.getLogger(MyReducer.class); + /** + * 针对的数据进行累加求和,并且最终把数据转化为k3,v3写出去 + * @param k2 + * @param v2s + * @param context + * @throws IOException + * @throws InterruptedException + */ + @Override + protected void reduce(Text k2, Iterable v2s, Context context) + throws IOException, InterruptedException { + //创建一个sum变量,保存v2s的和 + long sum = 0L; + //对v2s中的数据进行累加求和 + for(LongWritable v2: v2s){ + //输出k2,v2的值 + //System.out.println("=<"+k2.toString()+","+v2.get()+">"); + //logger.info("=<"+k2.toString()+","+v2.get()+">"); + sum += v2.get(); + //模拟Reduce的复杂计算消耗的时间 + if(sum%200 == 0){ + Thread.sleep(1); + } + } + + //组装k3,v3 + Text k3 = k2; + LongWritable v3 = new LongWritable(sum); + //输出k3,v3的值 + //System.out.println("=<"+k3.toString()+","+v3.get()+">"); + //logger.info("=<"+k3.toString()+","+v3.get()+">"); + // 把结果写出去 + context.write(k3,v3); + } + } + + /** + * 组装Job=Map+Reduce + */ + public static void main(String[] args) { + try{ + if(args.length!=3){ + //如果传递的参数不够,程序直接退出 + System.exit(100); + } + + //指定Job需要的配置参数 + Configuration conf = new Configuration(); + //创建一个Job + Job job = Job.getInstance(conf); + + //注意了:这一行必须设置,否则在集群中执行的时候是找不到WordCountJob这个类的 + job.setJarByClass(WordCountJobSkew.class); + + //指定输入路径(可以是文件,也可以是目录) + FileInputFormat.setInputPaths(job,new Path(args[0])); + //指定输出路径(只能指定一个不存在的目录) + FileOutputFormat.setOutputPath(job,new Path(args[1])); + + //指定map相关的代码 + job.setMapperClass(MyMapper.class); + //指定k2的类型 + job.setMapOutputKeyClass(Text.class); + //指定v2的类型 + job.setMapOutputValueClass(LongWritable.class); + + + //指定reduce相关的代码 + job.setReducerClass(MyReducer.class); + //指定k3的类型 + job.setOutputKeyClass(Text.class); + //指定v3的类型 + job.setOutputValueClass(LongWritable.class); + + //设置Reduce任务个数 + job.setNumReduceTasks(Integer.parseInt(args[2])); + + //提交job + job.waitForCompletion(true); + }catch(Exception e){ + e.printStackTrace(); + } + + } + + +} diff --git a/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJobSkewRandKey.java b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJobSkewRandKey.java new file mode 100644 index 00000000..a5c7609c --- /dev/null +++ b/bigdata/hadoop/mapreduce/src/main/java/cn/cunchang/mr/WordCountJobSkewRandKey.java @@ -0,0 +1,153 @@ +package cn.cunchang.mr; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.io.LongWritable; +import org.apache.hadoop.io.Text; +import org.apache.hadoop.mapreduce.Job; +import org.apache.hadoop.mapreduce.Mapper; +import org.apache.hadoop.mapreduce.Reducer; +import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; +import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.Random; + +/** + * 数据倾斜-把倾斜的数据打散 + * + * Created by xuwei + */ +public class WordCountJobSkewRandKey { + /** + * Map阶段 + */ + public static class MyMapper extends Mapper{ + Logger logger = LoggerFactory.getLogger(MyMapper.class); + Random random = new Random(); + /** + * 需要实现map函数 + * 这个map函数就是可以接收,产生 + * @param k1 + * @param v1 + * @param context + * @throws IOException + * @throws InterruptedException + */ + @Override + protected void map(LongWritable k1, Text v1, Context context) + throws IOException, InterruptedException { + //输出k1,v1的值 + //System.out.println("=<"+k1.get()+","+v1.toString()+">"); + //logger.info("=<"+k1.get()+","+v1.toString()+">"); + //k1 代表的是每一行数据的行首偏移量,v1代表的是每一行内容 + //对获取到的每一行数据进行切割,把单词切割出来 + String[] words = v1.toString().split(" "); + //把迭代出来的单词封装成的形式 + String key = words[0]; + if("5".equals(key)){ + //把倾斜的key打散,分成10份 + key= "5"+"_"+random.nextInt(10); + } + Text k2 = new Text(key); + LongWritable v2 = new LongWritable(1L); + //把写出去 + context.write(k2,v2); + } + } + + + /** + * Reduce阶段 + */ + public static class MyReducer extends Reducer{ + Logger logger = LoggerFactory.getLogger(MyReducer.class); + /** + * 针对的数据进行累加求和,并且最终把数据转化为k3,v3写出去 + * @param k2 + * @param v2s + * @param context + * @throws IOException + * @throws InterruptedException + */ + @Override + protected void reduce(Text k2, Iterable v2s, Context context) + throws IOException, InterruptedException { + //创建一个sum变量,保存v2s的和 + long sum = 0L; + //对v2s中的数据进行累加求和 + for(LongWritable v2: v2s){ + //输出k2,v2的值 + //System.out.println("=<"+k2.toString()+","+v2.get()+">"); + //logger.info("=<"+k2.toString()+","+v2.get()+">"); + sum += v2.get(); + //模拟Reduce的复杂计算消耗的时间 + if(sum%200 == 0){ + Thread.sleep(1); + } + } + + //组装k3,v3 + Text k3 = k2; + LongWritable v3 = new LongWritable(sum); + //输出k3,v3的值 + //System.out.println("=<"+k3.toString()+","+v3.get()+">"); + //logger.info("=<"+k3.toString()+","+v3.get()+">"); + // 把结果写出去 + context.write(k3,v3); + } + } + + /** + * 组装Job=Map+Reduce + */ + public static void main(String[] args) { + try{ + if(args.length!=3){ + //如果传递的参数不够,程序直接退出 + System.exit(100); + } + + //指定Job需要的配置参数 + Configuration conf = new Configuration(); + //创建一个Job + Job job = Job.getInstance(conf); + + //注意了:这一行必须设置,否则在集群中执行的时候是找不到WordCountJob这个类的 + job.setJarByClass(WordCountJobSkewRandKey.class); + + //指定输入路径(可以是文件,也可以是目录) + FileInputFormat.setInputPaths(job,new Path(args[0])); + //指定输出路径(只能指定一个不存在的目录) + FileOutputFormat.setOutputPath(job,new Path(args[1])); + + //指定map相关的代码 + job.setMapperClass(MyMapper.class); + //指定k2的类型 + job.setMapOutputKeyClass(Text.class); + //指定v2的类型 + job.setMapOutputValueClass(LongWritable.class); + + + //指定reduce相关的代码 + job.setReducerClass(MyReducer.class); + //指定k3的类型 + job.setOutputKeyClass(Text.class); + //指定v3的类型 + job.setOutputValueClass(LongWritable.class); + + //设置Reduce任务个数 + job.setNumReduceTasks(Integer.parseInt(args[2])); + + //提交job + job.waitForCompletion(true); + }catch(Exception e){ + e.printStackTrace(); + } + + } + + +} diff --git a/bigdata/hadoop/mapreduce/src/main/resources/log4j.properties b/bigdata/hadoop/mapreduce/src/main/resources/log4j.properties new file mode 100644 index 00000000..ddf8c805 --- /dev/null +++ b/bigdata/hadoop/mapreduce/src/main/resources/log4j.properties @@ -0,0 +1,9 @@ +log4j.rootLogger=info,stdout + +log4j.appender.stdout = org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target = System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c] [%p] - %m%n + + + diff --git a/bigdata/hadoop/pom.xml b/bigdata/hadoop/pom.xml new file mode 100644 index 00000000..db28f7b5 --- /dev/null +++ b/bigdata/hadoop/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + cn.cunchang + hadoop + jar + 1.0-SNAPSHOT + + + 8 + 8 + + + \ No newline at end of file diff --git a/bigdata/imooc-flink/data/access.json b/bigdata/imooc-flink/data/access.json new file mode 100644 index 00000000..a13328ff --- /dev/null +++ b/bigdata/imooc-flink/data/access.json @@ -0,0 +1,10007 @@ +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"startup","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"startup","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"startup","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"startup","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"startup","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"startup","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"startup","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195061,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195061,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195061,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195061,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195061,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195062,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195062,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195062,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195062,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195062,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"宝马"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"cart","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"户外","name":"运动包"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"华为商城","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-4444-89a7-ee7558603cfd","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_6","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"pay","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"实战Spark3实时处理掌握两套企业级处理方案"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"华为商城","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奔驰"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"pay","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"525a230a-aebd-4999-89a7-ee7558603cfc","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"车","name":"奥迪"},"time":1647195063,"uid":"user_5","version":"V1.2.4"} +{"channel":"Appstore","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"视频饮料","name":"咖啡"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df","deviceType":"iPhone 10","event":"cart","ip":"114.247.50.2","net":"5G","nu":1,"os":"iOS","product":{"category":"车","name":"保时捷"},"time":1647195063,"uid":"user_1","version":"V1.2.2"} +{"channel":"Appstore","device":"525a230a-aebd-3333-89a7-ee7558603cfe","deviceType":"小米11 Ultra","event":"cart","ip":"114.247.50.2","net":"5G","nu":0,"os":"Android","product":{"category":"户外","name":"帆布鞋"},"time":1647195063,"uid":"user_7","version":"V1.2.3"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 8","event":"browse","ip":"114.247.50.2","net":"4G","nu":0,"os":"iOS","product":{"category":"大数据实战","name":"Spark进阶大数据离线与实时项目开发"},"time":1647195063,"uid":"user_3","version":"V1.2.4"} +{"channel":"华为商城","device":"c041bc98-55c2-4fad-b4a4-ad0c79a11b78","deviceType":"iPhone 10","event":"browse","ip":"114.247.50.2","net":"5G","nu":0,"os":"iOS","product":{"category":"视频饮料","name":"五子"},"time":1647195063,"uid":"user_2","version":"V1.2.4"} +{"channel":"Appstore","device":"cad4d506-1552-4137-8c9a-067156791777","deviceType":"小米10","event":"browse","ip":"114.247.50.2","net":"5G","nu":1,"os":"Android","product":{"category":"食品饮料","name":"矿泉水"},"time":1647195063,"uid":"user_4","version":"V1.2.3"} \ No newline at end of file diff --git a/bigdata/imooc-flink/data/access.log b/bigdata/imooc-flink/data/access.log new file mode 100644 index 00000000..4ad1ae20 --- /dev/null +++ b/bigdata/imooc-flink/data/access.log @@ -0,0 +1,5 @@ +202512120010,imooc.com,2000 +202512120010,a.com,6000 +202512120010,b.com,5000 +202512120010,imooc.com,4000 +202512120010,a.com,1000 \ No newline at end of file diff --git a/bigdata/imooc-flink/data/nest/1/a.txt b/bigdata/imooc-flink/data/nest/1/a.txt new file mode 100644 index 00000000..1d5782d2 --- /dev/null +++ b/bigdata/imooc-flink/data/nest/1/a.txt @@ -0,0 +1,3 @@ +a +a +a \ No newline at end of file diff --git a/bigdata/imooc-flink/data/nest/1/b.txt b/bigdata/imooc-flink/data/nest/1/b.txt new file mode 100644 index 00000000..30ed1225 --- /dev/null +++ b/bigdata/imooc-flink/data/nest/1/b.txt @@ -0,0 +1,3 @@ +b +b +b \ No newline at end of file diff --git a/bigdata/imooc-flink/data/nest/2/c.txt b/bigdata/imooc-flink/data/nest/2/c.txt new file mode 100644 index 00000000..1cc8fc36 --- /dev/null +++ b/bigdata/imooc-flink/data/nest/2/c.txt @@ -0,0 +1,2 @@ +c +c \ No newline at end of file diff --git a/bigdata/imooc-flink/data/nest/2/d.txt b/bigdata/imooc-flink/data/nest/2/d.txt new file mode 100644 index 00000000..c59d9b63 --- /dev/null +++ b/bigdata/imooc-flink/data/nest/2/d.txt @@ -0,0 +1 @@ +d \ No newline at end of file diff --git a/bigdata/imooc-flink/data/nest/wc.txt b/bigdata/imooc-flink/data/nest/wc.txt new file mode 100644 index 00000000..6e32fced --- /dev/null +++ b/bigdata/imooc-flink/data/nest/wc.txt @@ -0,0 +1,2 @@ +pk,pk,pk +flink,flink \ No newline at end of file diff --git a/bigdata/imooc-flink/data/people.csv b/bigdata/imooc-flink/data/people.csv new file mode 100644 index 00000000..116efcd3 --- /dev/null +++ b/bigdata/imooc-flink/data/people.csv @@ -0,0 +1,3 @@ +name;age;job +Jorge;30;Developer +Bob;32;Developer \ No newline at end of file diff --git a/bigdata/imooc-flink/data/wc.data b/bigdata/imooc-flink/data/wc.data new file mode 100644 index 00000000..28d9e00f --- /dev/null +++ b/bigdata/imooc-flink/data/wc.data @@ -0,0 +1,2 @@ +pk,pk,pk,flink,flink +pk,pk,pk,flink,flink \ No newline at end of file diff --git a/bigdata/imooc-flink/data/wc.txt b/bigdata/imooc-flink/data/wc.txt new file mode 100644 index 00000000..6e32fced --- /dev/null +++ b/bigdata/imooc-flink/data/wc.txt @@ -0,0 +1,2 @@ +pk,pk,pk +flink,flink \ No newline at end of file diff --git a/bigdata/imooc-flink/imooc-clickhouse/pom.xml b/bigdata/imooc-flink/imooc-clickhouse/pom.xml new file mode 100644 index 00000000..f53174fc --- /dev/null +++ b/bigdata/imooc-flink/imooc-clickhouse/pom.xml @@ -0,0 +1,22 @@ + + + + imooc-flink + com.imooc.flink + 1.0 + + 4.0.0 + + imooc-clickhouse + + + + ru.yandex.clickhouse + clickhouse-jdbc + 0.1.54 + + + + \ No newline at end of file diff --git a/bigdata/imooc-flink/imooc-flink-basic/pom.xml b/bigdata/imooc-flink/imooc-flink-basic/pom.xml new file mode 100644 index 00000000..b62d0937 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-basic/pom.xml @@ -0,0 +1,26 @@ + + + + imooc-flink + com.imooc.flink + 1.0 + + 4.0.0 + + imooc-flink-basic + + + + + org.apache.flink + flink-streaming-java_${scala.binary.version} + + + + org.apache.flink + flink-clients_${scala.binary.version} + + + \ No newline at end of file diff --git a/bigdata/imooc-flink/imooc-flink-basic/src/main/java/com/imooc/flink/basic/BatchWCApp.java b/bigdata/imooc-flink/imooc-flink-basic/src/main/java/com/imooc/flink/basic/BatchWCApp.java new file mode 100644 index 00000000..3c2b07ad --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-basic/src/main/java/com/imooc/flink/basic/BatchWCApp.java @@ -0,0 +1,45 @@ +package com.imooc.flink.basic; + +import org.apache.flink.api.common.functions.FlatMapFunction; +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.java.ExecutionEnvironment; +import org.apache.flink.api.java.operators.DataSource; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.util.Collector; + +/** + * 第一个基于Flink批处理快速入门案例 + */ +public class BatchWCApp { + + public static void main(String[] args) throws Exception { + ExecutionEnvironment environment = ExecutionEnvironment.getExecutionEnvironment(); + + DataSource source = environment.readTextFile("data/wc.data"); + + source.flatMap(new PKFlatMapFunction()) + .map(new PKMapFunction()) + .groupBy(0) + .sum(1) + .print(); + + } +} + +class PKFlatMapFunction implements FlatMapFunction { + + @Override + public void flatMap(String value, Collector out) throws Exception { + String[] words = value.split(","); + for(String word : words) { + out.collect(word.toLowerCase().trim()); + } + } +} + +class PKMapFunction implements MapFunction> { + @Override + public Tuple2 map(String value) throws Exception { + return new Tuple2<>(value, 1); + } +} \ No newline at end of file diff --git a/bigdata/imooc-flink/imooc-flink-basic/src/main/java/com/imooc/flink/basic/StreamingWCApp.java b/bigdata/imooc-flink/imooc-flink-basic/src/main/java/com/imooc/flink/basic/StreamingWCApp.java new file mode 100644 index 00000000..1a2f0c7e --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-basic/src/main/java/com/imooc/flink/basic/StreamingWCApp.java @@ -0,0 +1,54 @@ +package com.imooc.flink.basic; + +import org.apache.commons.lang3.StringUtils; +import org.apache.flink.api.common.functions.FilterFunction; +import org.apache.flink.api.common.functions.FlatMapFunction; +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.java.functions.KeySelector; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.util.Collector; + +/** + * 第一个基于Flink实时处理快速入门案例 + */ +public class StreamingWCApp { + public static void main(String[] args) throws Exception { + + // 创建上下文 + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + // 对接数据源的数据 + DataStreamSource source = env.socketTextStream("localhost", 9527); + + // 业务逻辑处理: transformation + source.flatMap(new FlatMapFunction() { + @Override + public void flatMap(String value, Collector out) throws Exception { + String[] words = value.split(","); + for(String word : words) { + out.collect(word.toLowerCase().trim()); + } + } + }).filter(new FilterFunction() { + @Override + public boolean filter(String value) throws Exception { + return StringUtils.isNotEmpty(value); + } + }).map(new MapFunction>() { + @Override + public Tuple2 map(String value) throws Exception { + return new Tuple2<>(value, 1); + } + }).keyBy(new KeySelector, String>() { + @Override + public String getKey(Tuple2 value) throws Exception { + return value.f0; + } + }).sum(1) + .print(); + + env.execute("StreamgingWCApp"); + } +} diff --git a/bigdata/imooc-flink/imooc-flink-dataset/pom.xml b/bigdata/imooc-flink/imooc-flink-dataset/pom.xml new file mode 100644 index 00000000..32391353 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-dataset/pom.xml @@ -0,0 +1,26 @@ + + + + imooc-flink + com.imooc.flink + 1.0 + + 4.0.0 + + imooc-flink-dataset + + + + org.apache.flink + flink-streaming-java_${scala.binary.version} + + + + org.apache.flink + flink-clients_${scala.binary.version} + + + + \ No newline at end of file diff --git a/bigdata/imooc-flink/imooc-flink-datastream/README.md b/bigdata/imooc-flink/imooc-flink-datastream/README.md new file mode 100644 index 00000000..654ffdce --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/README.md @@ -0,0 +1,49 @@ +# 1、source +数据源 +SourceApp +- test01,官方提供数据源实现,socketTextStream数据源 +- test02,官方提供数据源实现,数值序列迭代器数据源 +- test03,自定义数据源,SourceFunction、ParallelSourceFunction +- test04,自定义数据源,RichSourceFunction +- test05,官方提供数据源实现,kafka + + +# 2、transformation +算子处理数据源 +TransformationApp + + +# 3、partitioner +分区,让某个并行度只处理某个分区数据 +PartitionerApp + +# 4、sink +输出算子处理结果 +SinkApp +- PKMySQLSink,输出到mysql +- PKRedisSink,输出到redis + + +# 5、windows +无界流按窗口拆成有界流 + +WindowApp +- test01 window实例 +- test02 窗口函数,增量 reduce +- test03 窗口函数,全量 ProcessWindowFunction + +# 6、wm +watermark + +EventTimeWMApp,延迟窗口,以及对延迟数据处理 + +# 7、state +状态 +- Keyed State +- 算子状态 (Operator State) ,Kafka consumer 每个并行实例维护了 topic partitions 和偏移量的 map 作为它的算子状态。 + +StateApp,state使用 + + + + diff --git a/bigdata/imooc-flink/imooc-flink-datastream/pom.xml b/bigdata/imooc-flink/imooc-flink-datastream/pom.xml new file mode 100644 index 00000000..e5f11979 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/pom.xml @@ -0,0 +1,51 @@ + + + + imooc-flink + com.imooc.flink + 1.0 + + 4.0.0 + + imooc-flink-datastream + + + + org.apache.flink + flink-streaming-java_${scala.binary.version} + + + + org.apache.flink + flink-clients_${scala.binary.version} + + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + + + + mysql + mysql-connector-java + 5.1.47 + + + + org.apache.bahir + flink-connector-redis_2.11 + 1.0 + + + + org.apache.flink + flink-connector-kafka_${scala.binary.version} + ${flink.version} + + + + + \ No newline at end of file diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/partitioner/PKPartitioner.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/partitioner/PKPartitioner.java new file mode 100644 index 00000000..0490f196 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/partitioner/PKPartitioner.java @@ -0,0 +1,19 @@ +package com.imooc.flink.partitioner; + +import org.apache.flink.api.common.functions.Partitioner; + +public class PKPartitioner implements Partitioner{ + @Override + public int partition(String key, int numPartitions) { + + System.out.println("numPartitions:" + numPartitions); + + if("imooc.com".equals(key)) { + return 0; + } else if("a.com".equals(key)) { + return 1; + } else { + return 2; + } + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/partitioner/PartitionerApp.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/partitioner/PartitionerApp.java new file mode 100644 index 00000000..973f890c --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/partitioner/PartitionerApp.java @@ -0,0 +1,36 @@ +package com.imooc.flink.partitioner; + +import com.imooc.flink.source.AccessSourceV2; +import com.imooc.flink.transformation.Access; +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; + +public class PartitionerApp { + public static void main(String[] args) throws Exception{ + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + env.setParallelism(3); + DataStreamSource source = env.addSource(new AccessSourceV2()); + System.out.println(source.getParallelism()); + + source.map(new MapFunction>() { + @Override + public Tuple2 map(Access value) throws Exception { + return Tuple2.of(value.getDomain(), value); + } + }).partitionCustom(new PKPartitioner(), 0) + .map(new MapFunction, Access>() { + @Override + public Access map(Tuple2 value) throws Exception { + + System.out.println("current thread id is:" + Thread.currentThread().getId()+ ", value is:" + value.f1); + + return value.f1; + } + }).print(); + + + env.execute("PartitionerApp"); + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/sink/PKMySQLSink.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/sink/PKMySQLSink.java new file mode 100644 index 00000000..a268ce3f --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/sink/PKMySQLSink.java @@ -0,0 +1,61 @@ +package com.imooc.flink.sink; + +import com.imooc.flink.utils.MySQLUtils; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; +import org.apache.flink.streaming.api.functions.sink.SinkFunction; + +import java.sql.Connection; +import java.sql.PreparedStatement; + +/** + * domain traffic + */ +public class PKMySQLSink extends RichSinkFunction> { + + + Connection connection; + PreparedStatement insertPstmt; + PreparedStatement updatePstmt; + + + @Override + public void open(Configuration parameters) throws Exception { + super.open(parameters); + + connection = MySQLUtils.getConnection(); + insertPstmt = connection.prepareStatement("insert into pk_traffic(domain,traffic) values (?,?)"); + updatePstmt = connection.prepareStatement("update pk_traffic set traffic=? where domain=?"); + + } + + @Override + public void close() throws Exception { + super.close(); + if(insertPstmt != null) insertPstmt.close(); + if(updatePstmt != null) updatePstmt.close(); + if(connection != null) connection.close(); + } + + /** + * 来一条数据就执行一次 + * + * 1000w的数据 1000w次 + */ + @Override + public void invoke(Tuple2 value, Context context) throws Exception { + System.out.println("=====invoke======" + value.f0 + "-->" + value.f1); + + updatePstmt.setDouble(1, value.f1); + updatePstmt.setString(2 , value.f0); + updatePstmt.execute(); + + if(updatePstmt.getUpdateCount() == 0) { + insertPstmt.setString(1, value.f0); + insertPstmt.setDouble(2, value.f1); + insertPstmt.execute(); + } + + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/sink/PKRedisSink.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/sink/PKRedisSink.java new file mode 100644 index 00000000..a02910d7 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/sink/PKRedisSink.java @@ -0,0 +1,36 @@ +package com.imooc.flink.sink; + +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisCommand; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisCommandDescription; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisMapper; + +/** + * 在生产环境中, + * + * 软件的版本做了升级 + * 代码有了很大变化 + * + * ==> diff + * + * + */ +public class PKRedisSink implements RedisMapper> { + + @Override + public RedisCommandDescription getCommandDescription() { + return new RedisCommandDescription(RedisCommand.HSET, "pk-traffic"); + } + + @Override + public String getKeyFromData(Tuple2 data) { + return data.f0; + } + + @Override + public String getValueFromData(Tuple2 data) { + return data.f1 +""; + } +} + + diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/sink/SinkApp.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/sink/SinkApp.java new file mode 100644 index 00000000..a411fccd --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/sink/SinkApp.java @@ -0,0 +1,75 @@ +package com.imooc.flink.sink; + +import com.imooc.flink.transformation.Access; +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.java.functions.KeySelector; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.connectors.redis.RedisSink; +import org.apache.flink.streaming.connectors.redis.common.config.FlinkJedisPoolConfig; + +public class SinkApp { + + public static void main(String[] args) throws Exception { + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + + toMySQL(env); + + env.execute("SinkApp"); + } + + public static void toMySQL(StreamExecutionEnvironment env) { + + DataStreamSource source = env.readTextFile("data/access.log"); + + SingleOutputStreamOperator mapStream = source.map(new MapFunction() { + @Override + public Access map(String value) throws Exception { + String[] splits = value.split(","); + Long time = Long.parseLong(splits[0].trim()); + String domain = splits[1].trim(); + Double traffic = Double.parseDouble(splits[2].trim()); + + return new Access(time, domain, traffic); + } + }); + + SingleOutputStreamOperator result = mapStream.keyBy(new KeySelector() { + @Override + public String getKey(Access value) throws Exception { + return value.getDomain(); + } + }).sum("traffic"); + + result.print(); + + // mysql + result.map(new MapFunction>() { + @Override + public Tuple2 map(Access value) throws Exception { + return Tuple2.of(value.getDomain(), value.getTraffic()); + } + }).addSink(new PKMySQLSink()); + + // redis +// FlinkJedisPoolConfig conf = new FlinkJedisPoolConfig.Builder().setHost("127.0.0.1").build(); +// result.map(new MapFunction>() { +// @Override +// public Tuple2 map(Access value) throws Exception { +// return Tuple2.of(value.getDomain(), value.getTraffic()); +// } +// }).addSink(new RedisSink>(conf, new PKRedisSink())); + } + + + public static void print(StreamExecutionEnvironment env) { + DataStreamSource source = env.socketTextStream("localhost", 9527); + + System.out.println("source:" + source.getParallelism()); + + source.print().setParallelism(2); + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/source/AccessSource.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/source/AccessSource.java new file mode 100644 index 00000000..8a3553d9 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/source/AccessSource.java @@ -0,0 +1,37 @@ +package com.imooc.flink.source; + +import com.imooc.flink.transformation.Access; +import org.apache.flink.streaming.api.functions.source.SourceFunction; + +import java.util.Random; + +public class AccessSource implements SourceFunction { + + boolean running = true; + + @Override + public void run(SourceContext ctx) throws Exception { + + String[] domains = {"imooc.com", "a.com","b.com"}; + + Random random = new Random(); + + while (running) { + for (int i = 0; i < 10 ; i++) { + Access access = new Access(); + access.setTime(1234567L); + access.setDomain(domains[random.nextInt(domains.length)]); + access.setTraffic(random.nextDouble() + 1000); + + ctx.collect(access); + } + + Thread.sleep(5000); + } + } + + @Override + public void cancel() { + running = false; + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/source/AccessSourceV2.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/source/AccessSourceV2.java new file mode 100644 index 00000000..d8504e6e --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/source/AccessSourceV2.java @@ -0,0 +1,38 @@ +package com.imooc.flink.source; + +import com.imooc.flink.transformation.Access; +import org.apache.flink.streaming.api.functions.source.ParallelSourceFunction; +import org.apache.flink.streaming.api.functions.source.SourceFunction; + +import java.util.Random; + +public class AccessSourceV2 implements ParallelSourceFunction { + + boolean running = true; + + @Override + public void run(SourceContext ctx) throws Exception { + + String[] domains = {"imooc.com", "a.com","b.com"}; + + Random random = new Random(); + + while (running) { + for (int i = 0; i < 10 ; i++) { + Access access = new Access(); + access.setTime(1234567L); + access.setDomain(domains[random.nextInt(domains.length)]); + access.setTraffic(random.nextDouble() + 1000); + + ctx.collect(access); + } + + Thread.sleep(5000); + } + } + + @Override + public void cancel() { + running = false; + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/source/SourceApp.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/source/SourceApp.java new file mode 100644 index 00000000..ba1a74bb --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/source/SourceApp.java @@ -0,0 +1,106 @@ +package com.imooc.flink.source; + +import com.imooc.flink.transformation.Access; +import org.apache.flink.api.common.functions.FilterFunction; +import org.apache.flink.api.common.serialization.SimpleStringSchema; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer; +import org.apache.flink.util.NumberSequenceIterator; + +import java.util.Properties; + +public class SourceApp { + + public static void main(String[] args) throws Exception { + // 创建上下文 + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + +// test01(env); +// test02(env); +// test03(env); + test04(env); +// test05(env); + env.execute("SourceApp"); + } + + public static void test05(StreamExecutionEnvironment env) { + + Properties properties = new Properties(); + properties.setProperty("bootstrap.servers", "localhost:9092"); + properties.setProperty("group.id", "test"); + DataStream stream = env + .addSource(new FlinkKafkaConsumer<>("flinktopic", new SimpleStringSchema(), properties)); + + System.out.println(stream.getParallelism()); + stream.print(); + } + + public static void test04(StreamExecutionEnvironment env) { + DataStreamSource source = env.addSource(new StudentSource()).setParallelism(1); + System.out.println(source.getParallelism()); + source.print(); + } + + public static void test03(StreamExecutionEnvironment env) { + + DataStreamSource source = env.addSource(new AccessSource()).setParallelism(1); +// DataStreamSource source = env.addSource(new AccessSourceV2()).setParallelism(3); + System.out.println(source.getParallelism()); + source.print(); + } + + public static void test02(StreamExecutionEnvironment env) { + + env.setParallelism(5); // 对于env设置的并行度 是一个全局的概念 + + DataStreamSource source = env.fromParallelCollection( + new NumberSequenceIterator(1, 10), Long.class + );//.setParallelism(4); + + System.out.println("source:" + source.getParallelism()); + + SingleOutputStreamOperator filterStream = source.filter(new FilterFunction() { + @Override + public boolean filter(Long value) throws Exception { + return value >= 5; + } + }).setParallelism(3); // 对于算子层面的并行度,如果全局设置,以本算子的并行度为准 + System.out.println("filterStream:" + filterStream.getParallelism()); + + filterStream.print(); + + } + + + public static void test01(StreamExecutionEnvironment env) { + + env.setParallelism(5); + +// StreamExecutionEnvironment.createLocalEnvironment(); +// StreamExecutionEnvironment.createLocalEnvironment(3); +// StreamExecutionEnvironment.createLocalEnvironment(new Configuration()); +// StreamExecutionEnvironment.createLocalEnvironmentWithWebUI(new Configuration()); +// StreamExecutionEnvironment.createRemoteEnvironment() + + DataStreamSource source = env.socketTextStream("localhost", 9527); + System.out.println("source...." + source.getParallelism()); // ? 1 + + // 接收socket过来的数据,一行一个单词, 把pk的过滤掉 + SingleOutputStreamOperator filterStream = source.filter(new FilterFunction() { + @Override + public boolean filter(String value) throws Exception { + return !"pk".equals(value); + } +// }); + }).setParallelism(6); + + + System.out.println("filter...." + filterStream.getParallelism()); + + + filterStream.print(); + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/source/Student.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/source/Student.java new file mode 100644 index 00000000..720df946 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/source/Student.java @@ -0,0 +1,49 @@ +package com.imooc.flink.source; + +public class Student { + private int id; + private String name; + private int age; + + public Student() { + } + + @Override + public String toString() { + return "Student{" + + "id=" + id + + ", name='" + name + '\'' + + ", age=" + age + + '}'; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public Student(int id, String name, int age) { + this.id = id; + this.name = name; + this.age = age; + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/source/StudentSource.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/source/StudentSource.java new file mode 100644 index 00000000..7316606b --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/source/StudentSource.java @@ -0,0 +1,43 @@ +package com.imooc.flink.source; + +import com.imooc.flink.utils.MySQLUtils; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.streaming.api.functions.source.RichSourceFunction; +import org.apache.flink.streaming.api.functions.source.SourceFunction; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; + +public class StudentSource extends RichSourceFunction { + + Connection connection; + PreparedStatement psmt; + + @Override + public void open(Configuration parameters) throws Exception { + connection = MySQLUtils.getConnection(); + psmt = connection.prepareStatement("select * from student"); + } + + @Override + public void close() throws Exception { + MySQLUtils.close(connection, psmt); + } + + @Override + public void run(SourceContext ctx) throws Exception { + ResultSet rs = psmt.executeQuery(); + while (rs.next()) { + int id = rs.getInt("id"); + String name = rs.getString("name"); + int age = rs.getInt("age"); + ctx.collect(new Student(id, name, age)); + } + } + + @Override + public void cancel() { + + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/state/CheckpointApp.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/state/CheckpointApp.java new file mode 100644 index 00000000..17d3b7e4 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/state/CheckpointApp.java @@ -0,0 +1,99 @@ +package com.imooc.flink.state; + +import org.apache.flink.api.common.functions.FlatMapFunction; +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.common.restartstrategy.RestartStrategies; +import org.apache.flink.api.common.time.Time; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.runtime.state.filesystem.FsStateBackend; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.environment.CheckpointConfig; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.util.Collector; + +import java.util.concurrent.TimeUnit; + +public class CheckpointApp { + public static void main(String[] args) throws Exception { +// System.setProperty("HADOOP_USER_NAME", "hadoop"); + + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); +// test1(env); + test2(env); + + env.execute("CheckpointApp"); + } + + private static void test1(StreamExecutionEnvironment env) { + + env.enableCheckpointing(5000); + + DataStreamSource streamSource = env.socketTextStream("localhost", 9527); + + streamSource + .print(); + + } + + private static void test2(StreamExecutionEnvironment env) { + /** + * 不开启checkpoint:不重启 + * + * 开启了checkpoint + * 1) 没有配置重启策略:Integer.MAX_VALUE + * 2) 如果配置了重启策略,就使用我们配置的重启策略覆盖默认的 + * + * 重启策略的配置: + * 1) code + * 2) yaml + * + */ + env.enableCheckpointing(5000); +// env.enableCheckpointing(5000, CheckpointingMode.EXACTLY_ONCE); + + // 是否保留Checkpoint; + env.getCheckpointConfig().enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION); + + // 设置StateBackend + env.setStateBackend(new FsStateBackend("file:///D:\\tmp\\imooc-flink\\checkpoints")); + + +// env.setStateBackend(new FsStateBackend("hdfs://ruozedata001:8020/imooc-flink-checkpoints")); + + // 自定义设置我们需要的重启策略 + env.setRestartStrategy(RestartStrategies.fixedDelayRestart( + 3, // 尝试重启的次数 + Time.of(5, TimeUnit.SECONDS) // 间隔 + )); + + + DataStreamSource source = env.socketTextStream("localhost", 9527); + source.map(new MapFunction() { + @Override + public String map(String value) throws Exception { + if (value.contains("pk")) { + throw new RuntimeException("PK哥来了,快跑.."); + } else { + return value.toLowerCase(); + } + } + }) + .flatMap(new FlatMapFunction() { + @Override + public void flatMap(String value, Collector out) throws Exception { + String[] splits = value.split(","); + for (String split : splits) { + out.collect(split); + } + } + }).map(new MapFunction>() { + @Override + public Tuple2 map(String value) throws Exception { + return Tuple2.of(value, 1); + } + }).keyBy(x -> x.f0) + .sum(1) + + .print(); + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/state/StateApp.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/state/StateApp.java new file mode 100644 index 00000000..4760b5b1 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/state/StateApp.java @@ -0,0 +1,123 @@ +package com.imooc.flink.state; + +import org.apache.flink.api.common.functions.RichFlatMapFunction; +import org.apache.flink.api.common.state.MapState; +import org.apache.flink.api.common.state.MapStateDescriptor; +import org.apache.flink.api.common.state.ValueState; +import org.apache.flink.api.common.state.ValueStateDescriptor; +import org.apache.flink.api.common.typeinfo.Types; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.shaded.guava18.com.google.common.collect.Lists; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.util.Collector; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class StateApp { + + public static void main(String[] args) throws Exception { + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + + test01(env); + + env.execute("SourceApp"); + } + + /** + * 使用ValueState实现平均数 + */ + public static void test01(StreamExecutionEnvironment env) throws Exception { + List> list = new ArrayList<>(); + list.add(Tuple2.of(1L, 3L)); + list.add(Tuple2.of(1L, 7L)); + list.add(Tuple2.of(2L, 4L)); + list.add(Tuple2.of(1L, 5L)); + list.add(Tuple2.of(1L, 15L)); + list.add(Tuple2.of(2L, 2L)); + list.add(Tuple2.of(2L, 5L)); + + env.fromCollection(list) + .keyBy(x -> x.f0) +// .flatMap(new AvgWithValueState()) + .flatMap(new AvgWithMapState()) + .print(); + + } +} + + +class AvgWithMapState extends RichFlatMapFunction ,Tuple2> { + + private transient MapState mapState; + + @Override + public void open(Configuration parameters) throws Exception { + MapStateDescriptor descriptor = new MapStateDescriptor("avg", String.class, Long.class); + mapState = getRuntimeContext().getMapState(descriptor); + } + + @Override + public void flatMap(Tuple2 value, Collector> out) throws Exception { + mapState.put(UUID.randomUUID().toString(), value.f1); + + ArrayList elements = Lists.newArrayList(mapState.values()); + + if(elements.size() == 3) { + Long count = 0L; + Long sum = 0L; + + for (Long element : elements) { + count += 1; + sum += element; + } + + Double avg = sum / count.doubleValue(); + out.collect(Tuple2.of(value.f0, avg)); + + mapState.clear(); + } + } +} + +class AvgWithValueState extends RichFlatMapFunction,Tuple2> { + + // 求平均数:记录条数 总和 + private transient ValueState> sum; + + @Override + public void open(Configuration parameters) throws Exception { + + ValueStateDescriptor> descriptor + = new ValueStateDescriptor<>("avg", Types.TUPLE(Types.LONG, Types.LONG)); + + sum = getRuntimeContext().getState(descriptor); + } + + @Override + public void flatMap(Tuple2 value, Collector> out) throws Exception { + // TODO... ==> state 次数 和 总和 + + Tuple2 currentState = sum.value(); + + if(null == currentState) { + currentState = Tuple2.of(0L,0L); + } + + currentState.f0 += 1; // 次数 + currentState.f1 += value.f1; // 求和 + + + sum.update(currentState); + + // 达到3条数据 ==> 求平均数 clear + if(currentState.f0 >=3 ){ + // key,平均数 + out.collect(Tuple2.of(value.f0, currentState.f1/currentState.f0.doubleValue())); + sum.clear(); + } + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/transformation/Access.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/transformation/Access.java new file mode 100644 index 00000000..d9301d5e --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/transformation/Access.java @@ -0,0 +1,49 @@ +package com.imooc.flink.transformation; + +public class Access { + private Long time; + private String domain; + private Double traffic; + + public Access() { + } + + public Access(Long time, String domain, Double traffic) { + this.time = time; + this.domain = domain; + this.traffic = traffic; + } + + @Override + public String toString() { + return "Access{" + + "time=" + time + + ", domain='" + domain + '\'' + + ", traffic=" + traffic + + '}'; + } + + public Long getTime() { + return time; + } + + public void setTime(Long time) { + this.time = time; + } + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + + public Double getTraffic() { + return traffic; + } + + public void setTraffic(Double traffic) { + this.traffic = traffic; + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/transformation/PKMapFunction.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/transformation/PKMapFunction.java new file mode 100644 index 00000000..49e5ef7a --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/transformation/PKMapFunction.java @@ -0,0 +1,46 @@ +package com.imooc.flink.transformation; + +import org.apache.flink.api.common.functions.RichMapFunction; +import org.apache.flink.api.common.functions.RuntimeContext; +import org.apache.flink.configuration.Configuration; + +public class PKMapFunction extends RichMapFunction { + + /** + * 初始化操作;初始化几次与并行度有关 + * Connection + */ + @Override + public void open(Configuration parameters) throws Exception { + super.open(parameters); + System.out.println("~~~~open~~~~"); + } + + /** + * 清理操作 + */ + @Override + public void close() throws Exception { + super.close(); + System.out.println("~~~~close~~~~"); + } + + @Override + public RuntimeContext getRuntimeContext() { + return super.getRuntimeContext(); + } + + /** + * 每条数据执行一次 + */ + @Override + public Access map(String value) throws Exception { + System.out.println("=====map====="); + + String[] splits = value.split(","); + Long time = Long.parseLong(splits[0].trim()); + String domain = splits[1].trim(); + Double traffic = Double.parseDouble(splits[2].trim()); + return new Access(time, domain, traffic); + } +} \ No newline at end of file diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/transformation/TransformationApp.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/transformation/TransformationApp.java new file mode 100644 index 00000000..f6314588 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/transformation/TransformationApp.java @@ -0,0 +1,317 @@ +package com.imooc.flink.transformation; + +import com.imooc.flink.source.AccessSource; +import org.apache.flink.api.common.functions.FilterFunction; +import org.apache.flink.api.common.functions.FlatMapFunction; +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.common.functions.ReduceFunction; +import org.apache.flink.api.java.functions.KeySelector; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.api.datastream.*; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.api.functions.co.CoFlatMapFunction; +import org.apache.flink.streaming.api.functions.co.CoMapFunction; +import org.apache.flink.util.Collector; + +import java.util.ArrayList; + +public class TransformationApp { + + public static void main(String[] args) throws Exception { + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + +// map(env); +// filter(env); +// flatMap(env); +// keyBy(env); +// reduce(env); + +// richMap(env); +// union(env); +// connect(env); +// coMap(env); + coFlatMap(env); + + env.execute("SourceApp"); + } + + public static void coFlatMap(StreamExecutionEnvironment env) { + DataStreamSource stream1 = env.fromElements("a b c", "d e f"); + DataStreamSource stream2 = env.fromElements("1,2,3", "4,5,6"); + + stream1.connect(stream2) + .flatMap(new CoFlatMapFunction() { + @Override + public void flatMap1(String value, Collector out) throws Exception { + String[] splits = value.split(" "); + for(String split : splits) { + out.collect(split); + } + } + + @Override + public void flatMap2(String value, Collector out) throws Exception { + String[] splits = value.split(","); + for(String split : splits) { + out.collect(split); + } + } + }).print(); + } + + public static void coMap(StreamExecutionEnvironment env) { + DataStreamSource stream1 = env.socketTextStream("localhost", 9527); + SingleOutputStreamOperator stream2 = env.socketTextStream("localhost", 9528) // 数值类型 + .map(new MapFunction() { + @Override + public Integer map(String value) throws Exception { + return Integer.parseInt(value); + } + }); + + // 将2个流连接在一起 + stream1.connect(stream2).map(new CoMapFunction() { + + // 处理第一个流的业务逻辑 + @Override + public String map1(String value) throws Exception { + return value.toUpperCase(); + } + + // 处理第二个流的业务逻辑 + @Override + public String map2(Integer value) throws Exception { + return value * 10 + ""; + } + }).print(); + } + + /** + * union 多流合并 数据结构必须相同 + * connect 双流 数据结构可以不同, 更加灵活 + */ + public static void connect(StreamExecutionEnvironment env) { + + DataStreamSource stream1 = env.addSource(new AccessSource()); + DataStreamSource stream2 = env.addSource(new AccessSource()); + + SingleOutputStreamOperator> stream2new = stream2.map(new MapFunction>() { + @Override + public Tuple2 map(Access value) throws Exception { + return Tuple2.of("pk", value); + } + }); + + stream1.connect(stream2new).map(new CoMapFunction, String>() { + @Override + public String map1(Access value) throws Exception { + return value.toString(); + } + + @Override + public String map2(Tuple2 value) throws Exception { + return value.f0 + "==>" + value.f1.toString(); + } + }).print(); + +// ConnectedStreams connect = stream1.connect(stream2); +// +// connect.map(new CoMapFunction() { +// @Override +// public Access map1(Access value) throws Exception { +// return value; +// } +// +// @Override +// public Access map2(Access value) throws Exception { +// return value; +// } +// }).print(); + + } + + + public static void union(StreamExecutionEnvironment env) { + + DataStreamSource stream1 = env.socketTextStream("localhost", 9527); + DataStreamSource stream2 = env.socketTextStream("localhost", 9528); + + DataStream union = stream1.union(stream2); +// stream1.union(stream2).print(); + stream1.union(stream1).print(); + } + + public static void richMap(StreamExecutionEnvironment env) { + env.setParallelism(3); + DataStreamSource source = env.readTextFile("data/access.log"); + + SingleOutputStreamOperator mapStream = source.map(new PKMapFunction()); + mapStream.print(); + + } + + /** + * wc: socket + * + * 进来的数据:pk,pk,flink pk,spark,spark + * + * + * wc需求分析: + * 1) 读进来数据 + * 2) 按照指定分隔符进行拆分 pk pk flink pk spark spark + * 3) 为每个单词赋上一个出现次数为1的值 (pk,1) (pk,1) ... + * 4) 按照单词进行keyBy + * 5) 分组求和 + * + */ + public static void reduce(StreamExecutionEnvironment env) { + + DataStreamSource source = env.socketTextStream("localhost", 9527); + + source.flatMap(new FlatMapFunction() { + @Override + public void flatMap(String value, Collector out) throws Exception { + String[] splits = value.split(","); + for(String word : splits) { + out.collect(word); + } + } + }).map(new MapFunction>() { + @Override + public Tuple2 map(String value) throws Exception { + return Tuple2.of(value, 1); + } + }).keyBy(x -> x.f0) // word相同的都会分到一个task中去执行 + .reduce(new ReduceFunction>() { + @Override + public Tuple2 reduce(Tuple2 value1, Tuple2 value2) throws Exception { + return Tuple2.of(value1.f0, value1.f1 + value2.f1); + } + }).print(); + } + + /** + * 按照domain分组,求traffic和 + */ + public static void keyBy(StreamExecutionEnvironment env) { + DataStreamSource source = env.readTextFile("data/access.log"); + + SingleOutputStreamOperator mapStream = source.map(new MapFunction() { + @Override + public Access map(String value) throws Exception { + String[] splits = value.split(","); + Long time = Long.parseLong(splits[0].trim()); + String domain = splits[1].trim(); + Double traffic = Double.parseDouble(splits[2].trim()); + + return new Access(time, domain, traffic); + } + }); + + mapStream.keyBy("domain").sum("traffic").print(); +// mapStream.keyBy(new KeySelector() { +// @Override +// public String getKey(Access value) throws Exception { +// return value.getDomain(); +// } +// }).sum("traffic").print(); +// KeyedStream keyedStream = mapStream.keyBy(Access::getDomain); +// keyedStream.sum("traffic").print(); + } + + /** + * 进来是一行行的数据: pk,pk,flink pk,spark,spark + * 需求: + * 1) 把一行数据按照逗号进行分割 + * 2) 过滤掉pk + */ + public static void flatMap(StreamExecutionEnvironment env) { + DataStreamSource source = env.socketTextStream("localhost", 9527); + source.flatMap(new FlatMapFunction() { + @Override + public void flatMap(String value, Collector out) throws Exception { + String[] splits = value.split(","); + for(String split : splits) { + out.collect(split); + } + } + }).filter(new FilterFunction() { + @Override + public boolean filter(String value) throws Exception { + return !"pk".equals(value); + } + }).print(); + } + /** + * filter 就是对DataStream中的数据进行过滤操作 + * 保留true + */ + public static void filter(StreamExecutionEnvironment env) { + DataStreamSource source = env.readTextFile("data/access.log"); + + SingleOutputStreamOperator mapStream = source.map(new MapFunction() { + @Override + public Access map(String value) throws Exception { + String[] splits = value.split(","); + Long time = Long.parseLong(splits[0].trim()); + String domain = splits[1].trim(); + Double traffic = Double.parseDouble(splits[2].trim()); + + return new Access(time, domain, traffic); + } + }); + + SingleOutputStreamOperator filterStream = mapStream.filter(new FilterFunction() { + @Override + public boolean filter(Access value) throws Exception { + return value.getTraffic() > 4000; + } + }); + + filterStream.print(); + } + + /** + * 读进来的数据是一行行的,也字符串类型 + * + * 每一行数据 ==> Access + * + * 将map算子对应的函数作用到DataStream,产生一个新的DataStream + * + * map会作用到已有的DataStream这个数据集中的每一个元素上 + * + */ + public static void map(StreamExecutionEnvironment env) { + +// DataStreamSource source = env.readTextFile("data/access.log"); +// +// SingleOutputStreamOperator mapStream = source.map(new MapFunction() { +// @Override +// public Access map(String value) throws Exception { +// String[] splits = value.split(","); +// Long time = Long.parseLong(splits[0].trim()); +// String domain = splits[1].trim(); +// Double traffic = Double.parseDouble(splits[2].trim()); +// +// return new Access(time, domain, traffic); +// } +// }); +// +// mapStream.print(); + + ArrayList list = new ArrayList<>(); + list.add(1); // map * 2 = 2 + list.add(2); // map * 2 = 4 + list.add(3); // map * 2 = 6 + DataStreamSource source = env.fromCollection(list); + + source.map(new MapFunction() { + @Override + public Integer map(Integer value) throws Exception { + return value * 2; + } + }).print(); + + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/utils/MySQLUtils.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/utils/MySQLUtils.java new file mode 100644 index 00000000..201901b6 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/utils/MySQLUtils.java @@ -0,0 +1,43 @@ +package com.imooc.flink.utils; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +public class MySQLUtils { + + public static Connection getConnection() { + + try { + Class.forName("com.mysql.jdbc.Driver"); + return DriverManager.getConnection("jdbc:mysql://localhost:3306/pk_flink_imooc?useSSL=false", "root", "123456"); + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + public static void close(Connection connection, PreparedStatement pstmt) { + if(null != pstmt) { + try { + pstmt.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + if(null != connection) { + try { + connection.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + + public static void main(String[] args) { + System.out.println(getConnection()); + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/window/PKProcessWindowFunction.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/window/PKProcessWindowFunction.java new file mode 100644 index 00000000..aecfe085 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/window/PKProcessWindowFunction.java @@ -0,0 +1,27 @@ +package com.imooc.flink.window; + +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.api.functions.windowing.ProcessWindowFunction; +import org.apache.flink.streaming.api.windowing.windows.TimeWindow; +import org.apache.flink.util.Collector; + +/** + * IN:待处理DataStream中每个元素的类型 + * OUT:结果DataStream中每个元素的类型 + * KEY:keyBy中指定key的类型 + * W extends Window: TimeWindow + */ +public class PKProcessWindowFunction extends ProcessWindowFunction, String, String, TimeWindow> { + @Override + public void process(String s, Context context, Iterable> elements, Collector out) throws Exception { + + System.out.println("----process invoked...----"); + + int maxValue = Integer.MIN_VALUE; + for (Tuple2 element : elements) { + maxValue = Math.max(element.f1, maxValue); + } + + out.collect("当前窗口的最大值是:" + maxValue); + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/window/WindowApp.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/window/WindowApp.java new file mode 100644 index 00000000..03a4f6c5 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/window/WindowApp.java @@ -0,0 +1,95 @@ +package com.imooc.flink.window; + +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.common.functions.ReduceFunction; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.api.windowing.assigners.TumblingProcessingTimeWindows; +import org.apache.flink.streaming.api.windowing.time.Time; + +public class WindowApp { + + public static void main(String[] args) throws Exception { + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + test01(env); + +// test02(env); +// test03(env); + env.execute("WindowApp"); + } + + public static void test03(StreamExecutionEnvironment env) { + env.socketTextStream("localhost", 9527) + .map(new MapFunction>() { + @Override + public Tuple2 map(String value) throws Exception { + return Tuple2.of("pk", Integer.parseInt(value)); + } + }).keyBy(x -> x.f0) + .window(TumblingProcessingTimeWindows.of(Time.seconds(5))) + .process(new PKProcessWindowFunction()) + .print(); + } + + + public static void test02(StreamExecutionEnvironment env) { + env.socketTextStream("localhost", 9527) + .map(new MapFunction>() { + @Override + public Tuple2 map(String value) throws Exception { + String[] splits = value.split(","); + return Tuple2.of(splits[0].trim(), Integer.parseInt(splits[1].trim())); + } + }).keyBy(x -> x.f0) + .window(TumblingProcessingTimeWindows.of(Time.seconds(5))) + .reduce(new ReduceFunction>() { + @Override + public Tuple2 reduce(Tuple2 value1, Tuple2 value2) throws Exception { + + System.out.println("value1 = [" + value1 + "], value2 = [" + value2 + "]"); + return Tuple2.of(value1.f0, value1.f1+value2.f1); + } + }) + .print(); + } + + + public static void test01(StreamExecutionEnvironment env) { + env.socketTextStream("localhost", 9527) + .map(new MapFunction() { + @Override + public Integer map(String value) throws Exception { + return Integer.parseInt(value); + } + }) + .windowAll(TumblingProcessingTimeWindows.of(Time.seconds(5))) + .sum(0) + .print(); + +// env.socketTextStream("localhost", 9527) +// .map(new MapFunction() { +// @Override +// public Integer map(String value) throws Exception { +// return Integer.parseInt(value); +// } +// }) +// .windowAll(TumblingProcessingTimeWindows.of(Time.seconds(5))) +// .sum(0) +// .print(); + + + // hadoop,1 spark,1 +// env.socketTextStream("localhost", 9527) +// .map(new MapFunction>() { +// @Override +// public Tuple2 map(String value) throws Exception { +// String[] splits = value.split(","); +// return Tuple2.of(splits[0].trim(), Integer.parseInt(splits[1].trim())); +// } +// }).keyBy(x -> x.f0) +// .window(TumblingProcessingTimeWindows.of(Time.seconds(5))) +// .sum(1) +// .print(); + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/wm/EventTimeWMApp.java b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/wm/EventTimeWMApp.java new file mode 100644 index 00000000..9feb0a5f --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/java/com/imooc/flink/wm/EventTimeWMApp.java @@ -0,0 +1,85 @@ +package com.imooc.flink.wm; + +import org.apache.commons.lang3.time.FastDateFormat; +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.common.functions.ReduceFunction; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; +import org.apache.flink.streaming.api.functions.windowing.ProcessWindowFunction; +import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows; +import org.apache.flink.streaming.api.windowing.time.Time; +import org.apache.flink.streaming.api.windowing.windows.TimeWindow; +import org.apache.flink.util.Collector; +import org.apache.flink.util.OutputTag; + +/** + * EventTime结合WM的使用 + * + * 输入数据的格式:时间字段,单词,次数 + */ +public class EventTimeWMApp { + public static void main(String[] args) throws Exception { + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + test01(env); + env.execute("EventTimeWMApp"); + } + + public static void test01(StreamExecutionEnvironment env) { + OutputTag> outputTag = new OutputTag>("late-data"){ + + }; + + SingleOutputStreamOperator lines = env.socketTextStream("localhost", 9527) + .assignTimestampsAndWatermarks( + new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(0)) { + @Override + public long extractTimestamp(String element) { + return Long.parseLong(element.split(",")[0]); + } + } + ); + SingleOutputStreamOperator> mapStream = lines.map(new MapFunction>() { + @Override + public Tuple2 map(String value) throws Exception { + String[] splits = value.split(","); + return Tuple2.of(splits[1].trim(), Integer.parseInt(splits[2].trim())); + } + }); + + // [0000,5000) [5000,10000) + SingleOutputStreamOperator window = mapStream.keyBy(x -> x.f0) + .window(TumblingEventTimeWindows.of(Time.seconds(5))) + .sideOutputLateData(outputTag) + .reduce(new ReduceFunction>() { + @Override + public Tuple2 reduce(Tuple2 value1, Tuple2 value2) throws Exception { + System.out.println("-----reduce invoked----" + value1.f0 + "==>" + (value1.f1 + value2.f1)); + return Tuple2.of(value1.f0, value1.f1 + value2.f1); + } + }, new ProcessWindowFunction, String, String, TimeWindow>() { + + FastDateFormat format = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss"); + + @Override + public void process(String s, Context context, Iterable> elements, Collector out) throws Exception { + for (Tuple2 element : elements) { + out.collect("[" + format.format(context.window().getStart()) + "==>" + format.format(context.window().getEnd()) + "], " + element.f0 + "==>" + element.f1); + } + } + }); + window.print(); + DataStream> sideOutput = window.getSideOutput(outputTag); + sideOutput.printToErr(); + + /** + * WM其实就是延迟触发的一种机制 + * WM = 数据所携带的时间(窗口中最大的时间) - 延迟执行的时间 + * WM >= 上一个窗口的结束边界 就会触发窗口的执行 + * 6999 - 2000 = 4999 >= 上一个窗口的结束边界 + */ + } +} diff --git a/bigdata/imooc-flink/imooc-flink-datastream/src/main/resources/log4j.properties b/bigdata/imooc-flink/imooc-flink-datastream/src/main/resources/log4j.properties new file mode 100644 index 00000000..dcecfce2 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/src/main/resources/log4j.properties @@ -0,0 +1,15 @@ +# 指定 RootLogger 顶级父元素默认配置信息 +# 指定日志级别=trace,使用的 apeender 为=console +log4j.rootLogger = console + +# 自定义 logger 对象设置 +log4j.logger.com.imooc.flink = info,console +log4j.logger.org.apache.flink = warn,console + +# 指定控制台日志输出的 appender +log4j.appender.console = org.apache.log4j.ConsoleAppender +# 指定消息格式 layout +log4j.appender.console.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.console.layout.conversionPattern = %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n + diff --git a/bigdata/imooc-flink/imooc-flink-datastream/test.sql b/bigdata/imooc-flink/imooc-flink-datastream/test.sql new file mode 100644 index 00000000..ad8f988e --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-datastream/test.sql @@ -0,0 +1,16 @@ +CREATE TABLE pk_flink_imooc.student +( + id int NOT NULL DEFAULT '0', + name varchar(255) NOT NULL DEFAULT '', + age int NOT NULL DEFAULT '0', + PRIMARY KEY (id) +); + +CREATE TABLE `pk_flink_imooc`.`pk_traffic` +( + `domain` varchar(255) NOT NULL DEFAULT '', + `traffic` double NOT NULL DEFAULT '0.0', + PRIMARY KEY (domain) +); + + diff --git a/distributed/netty/README.md b/bigdata/imooc-flink/imooc-flink-project/README.md similarity index 100% rename from distributed/netty/README.md rename to bigdata/imooc-flink/imooc-flink-project/README.md diff --git a/bigdata/imooc-flink/imooc-flink-project/pom.xml b/bigdata/imooc-flink/imooc-flink-project/pom.xml new file mode 100644 index 00000000..fa1d86e8 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-project/pom.xml @@ -0,0 +1,66 @@ + + + + imooc-flink + com.imooc.flink + 1.0 + + 4.0.0 + + imooc-flink-project + + + + org.apache.flink + flink-streaming-java_${scala.binary.version} + + + + org.apache.flink + flink-clients_${scala.binary.version} + + + + com.alibaba + fastjson + 1.2.57 + + + + + mysql + mysql-connector-java + 5.1.47 + + + + + org.apache.httpcomponents + httpclient + 4.5.6 + + + + + org.apache.httpcomponents + httpasyncclient + 4.1.4 + + + + + org.apache.bahir + flink-connector-redis_2.11 + 1.0 + + + + org.apache.flink + flink-connector-kafka_${scala.binary.version} + ${flink.version} + + + + \ No newline at end of file diff --git a/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/GaodeApp.java b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/GaodeApp.java new file mode 100644 index 00000000..f9118d56 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/GaodeApp.java @@ -0,0 +1,55 @@ +package com.imooc.flink.app; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.imooc.flink.utils.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; + +public class GaodeApp { + + public static void main(String[] args) { + String ip = "114.247.50.2"; + + + String province = "-"; + String city = "-"; + + String url = "https://restapi.amap.com/v3/ip?ip="+ip+"&output=json&key="+ StringUtils.GAODE_KEY; + + CloseableHttpClient httpClient = HttpClients.createDefault(); + + CloseableHttpResponse response = null; + + try { + HttpGet httpGet = new HttpGet(url); + response = httpClient.execute(httpGet); + int statusCode = response.getStatusLine().getStatusCode(); + if(statusCode == 200) { + HttpEntity entity = response.getEntity(); + String result = EntityUtils.toString(entity, "UTF-8"); + + + JSONObject jsonObject = JSON.parseObject(result); + province = jsonObject.getString("province"); + city = jsonObject.getString("city"); + + System.out.println(province + "\t" + city); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + if(null != response) try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} diff --git a/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/OsUserCntAppV1.java b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/OsUserCntAppV1.java new file mode 100644 index 00000000..14d004a5 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/OsUserCntAppV1.java @@ -0,0 +1,99 @@ +package com.imooc.flink.app; + +import com.alibaba.fastjson.JSON; +import com.imooc.flink.domain.Access; +import org.apache.flink.api.common.functions.FilterFunction; +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.java.functions.KeySelector; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.api.java.tuple.Tuple3; +import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.connectors.redis.RedisSink; +import org.apache.flink.streaming.connectors.redis.common.config.FlinkJedisPoolConfig; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisCommand; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisCommandDescription; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisMapper; + +import java.util.Objects; + +/** + * 按照操作系统维度进行新老用户的统计分析 + */ +public class OsUserCntAppV1 { + + public static void main(String[] args) throws Exception { + + StreamExecutionEnvironment environment = StreamExecutionEnvironment.getExecutionEnvironment(); + + SingleOutputStreamOperator cleanStream = environment.readTextFile("data/access.json") + .map(new MapFunction() { + @Override + public Access map(String value) throws Exception { + // TODO... json ==> Access + + // 注意事项:一定要考虑解析的容错性 + try { + return JSON.parseObject(value, Access.class); + } catch (Exception e) { + e.printStackTrace(); // 写到某个地方 + return null; + } + + } + }).filter(Objects::nonNull) + .filter(new FilterFunction() { + @Override + public boolean filter(Access value) throws Exception { + return "startup".equals(value.event); + } + }); + + // 操作系统维度 新老用户 ==> wc + SingleOutputStreamOperator> result = cleanStream.map(new MapFunction>() { + @Override + public Tuple3 map(Access value) throws Exception { + return Tuple3.of(value.os, value.nu, 1); + } + }).keyBy(new KeySelector, Tuple2>() { + @Override + public Tuple2 getKey(Tuple3 value) throws Exception { + return Tuple2.of(value.f0, value.f1); + } + }).sum(2);// .print().setParallelism(1); + + /** + * (iOS,1,38) + * (Android,1,29) + * (iOS,0,17) + * (Android,0,16) + */ + + FlinkJedisPoolConfig conf = new FlinkJedisPoolConfig.Builder().setHost("127.0.0.1").build(); + + result.addSink(new RedisSink>(conf, new RedisExampleMapper())); + + environment.execute("OsUserCntAppV1"); + + } + + + static class RedisExampleMapper implements RedisMapper> { + + @Override + public RedisCommandDescription getCommandDescription() { + return new RedisCommandDescription(RedisCommand.HSET, "os-user-cnt:20301002"); + } + + @Override + public String getKeyFromData(Tuple3 data) { + return data.f0 + "_" + data.f1; + } + + @Override + public String getValueFromData(Tuple3 data) { + return data.f2+""; + } + + } +} diff --git a/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/OsUserCntAppV2.java b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/OsUserCntAppV2.java new file mode 100644 index 00000000..1b2a1d80 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/OsUserCntAppV2.java @@ -0,0 +1,72 @@ +package com.imooc.flink.app; + +import com.alibaba.fastjson.JSON; +import com.imooc.flink.domain.Access; +import org.apache.flink.api.common.functions.FilterFunction; +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.java.functions.KeySelector; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.api.java.tuple.Tuple3; +import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.connectors.redis.RedisSink; +import org.apache.flink.streaming.connectors.redis.common.config.FlinkJedisPoolConfig; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisCommand; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisCommandDescription; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisMapper; + +/** + * 新老用户的统计分析 + */ +public class OsUserCntAppV2 { + + public static void main(String[] args) throws Exception { + + StreamExecutionEnvironment environment = StreamExecutionEnvironment.getExecutionEnvironment(); + + SingleOutputStreamOperator cleanStream = environment.readTextFile("data/access.json") + .map(new MapFunction() { + @Override + public Access map(String value) throws Exception { + // TODO... json ==> Access + + try { + return JSON.parseObject(value, Access.class); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + } + }).filter(x -> x != null) + .filter(new FilterFunction() { + @Override + public boolean filter(Access value) throws Exception { + return "startup".equals(value.event); + } + }); + + cleanStream.map(new MapFunction>() { + @Override + public Tuple2 map(Access value) throws Exception { + return Tuple2.of(value.nu, 1); + } + }).keyBy(x -> x.f0) + .sum(1).print("总的新老用户:").setParallelism(1); + + + /** + * (iOS,1,38) + * (Android,1,29) + * (iOS,0,17) + * (Android,0,16) + * + * ==> + * (1, 67) + * (0, 33) + */ + + environment.execute("OsUserCntAppV2"); + + } +} diff --git a/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/OsUserCntAppV3.java b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/OsUserCntAppV3.java new file mode 100644 index 00000000..f6e3997a --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/OsUserCntAppV3.java @@ -0,0 +1,92 @@ +package com.imooc.flink.app; + +import com.alibaba.fastjson.JSON; +import com.imooc.flink.domain.Access; +import org.apache.flink.api.common.functions.FilterFunction; +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.common.state.ValueState; +import org.apache.flink.api.common.state.ValueStateDescriptor; +import org.apache.flink.api.common.typeinfo.TypeHint; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.shaded.guava18.com.google.common.hash.BloomFilter; +import org.apache.flink.shaded.guava18.com.google.common.hash.Funnels; +import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.api.functions.KeyedProcessFunction; +import org.apache.flink.util.Collector; + +/** + * 新老用户的统计分析 + * + * 原来是根据数据中的某个字段 + * 现在我们是根据每个device来进行判断是否是新老用户 + * + * 思考:device放到state里面去呢 + * + * 我们的实现:状态 + 布隆过滤器 + * + */ +public class OsUserCntAppV3 { + + public static void main(String[] args) throws Exception { + + StreamExecutionEnvironment environment = StreamExecutionEnvironment.getExecutionEnvironment(); + + SingleOutputStreamOperator cleanStream = environment.readTextFile("data/access.json") + .map(new MapFunction() { + @Override + public Access map(String value) throws Exception { + // TODO... json ==> Access + + try { + return JSON.parseObject(value, Access.class); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + } + }).filter(x -> x != null) + .filter(new FilterFunction() { + @Override + public boolean filter(Access value) throws Exception { + return "startup".equals(value.event); + } + }); + + + cleanStream.keyBy(x -> x.deviceType) + .process(new KeyedProcessFunction() { + + private transient ValueState> state; + + @Override + public void open(Configuration parameters) throws Exception { + ValueStateDescriptor> descriptor = new ValueStateDescriptor<>("s", TypeInformation.of(new TypeHint>() {})); + state = getRuntimeContext().getState(descriptor); + } + + @Override + public void processElement(Access value, Context ctx, Collector out) throws Exception { + String device = value.device; + BloomFilter bloomFilter = state.value(); + if(null == bloomFilter) { + bloomFilter = BloomFilter.create(Funnels.unencodedCharsFunnel(), 100000); + } + + if(!bloomFilter.mightContain(device)) { + bloomFilter.put(device); + value.nu2 = 1; + state.update(bloomFilter); + } + + out.collect(value); + } + }).print(); + + + environment.execute("OsUserCntAppV3"); + + } +} diff --git a/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/OsUserCntAppV4.java b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/OsUserCntAppV4.java new file mode 100644 index 00000000..e8bc28d9 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/OsUserCntAppV4.java @@ -0,0 +1,81 @@ +package com.imooc.flink.app; + +import com.alibaba.fastjson.JSON; +import com.imooc.flink.domain.Access; +import org.apache.flink.api.common.functions.FilterFunction; +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.common.state.ValueState; +import org.apache.flink.api.common.state.ValueStateDescriptor; +import org.apache.flink.api.common.typeinfo.TypeHint; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.shaded.guava18.com.google.common.hash.BloomFilter; +import org.apache.flink.shaded.guava18.com.google.common.hash.Funnels; +import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.api.functions.KeyedProcessFunction; +import org.apache.flink.util.Collector; + +public class OsUserCntAppV4 { + + public static void main(String[] args) throws Exception { + + StreamExecutionEnvironment environment = StreamExecutionEnvironment.getExecutionEnvironment(); + + SingleOutputStreamOperator cleanStream = environment.socketTextStream("localhost", 9527) + .map(new MapFunction() { + @Override + public Access map(String value) throws Exception { + // TODO... json ==> Access + + try { + return JSON.parseObject(value, Access.class); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + } + }).filter(x -> x != null) + .filter(new FilterFunction() { + @Override + public boolean filter(Access value) throws Exception { + return "startup".equals(value.event); + } + }); + + + cleanStream.keyBy(x -> x.deviceType) + .process(new KeyedProcessFunction() { + + private transient ValueState> state; + + @Override + public void open(Configuration parameters) throws Exception { + ValueStateDescriptor> descriptor = new ValueStateDescriptor<>("s", TypeInformation.of(new TypeHint>() {})); + state = getRuntimeContext().getState(descriptor); + } + + @Override + public void processElement(Access value, Context ctx, Collector out) throws Exception { + String device = value.device; + BloomFilter bloomFilter = state.value(); + if(null == bloomFilter) { + bloomFilter = BloomFilter.create(Funnels.unencodedCharsFunnel(), 100000); + } + + if(!bloomFilter.mightContain(device)) { + bloomFilter.put(device); + value.nu2 = 1; + state.update(bloomFilter); + } + + out.collect(value); + } + }).print(); + + + environment.execute("OsUserCntAppV2"); + + } +} diff --git a/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/ProvinceUserCntAppV1.java b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/ProvinceUserCntAppV1.java new file mode 100644 index 00000000..76abcca1 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/ProvinceUserCntAppV1.java @@ -0,0 +1,91 @@ +package com.imooc.flink.app; + +import com.alibaba.fastjson.JSON; +import com.imooc.flink.domain.Access; +import com.imooc.flink.udf.GaodeLocationMapFunction; +import org.apache.flink.api.common.functions.FilterFunction; +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.java.functions.KeySelector; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.api.java.tuple.Tuple3; +import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.connectors.redis.RedisSink; +import org.apache.flink.streaming.connectors.redis.common.config.FlinkJedisPoolConfig; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisCommand; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisCommandDescription; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisMapper; + +/** + * 按照省份维度进行新老用户的统计分析 + */ +public class ProvinceUserCntAppV1 { + + public static void main(String[] args) throws Exception { + + StreamExecutionEnvironment environment = StreamExecutionEnvironment.getExecutionEnvironment(); + + SingleOutputStreamOperator cleanStream = environment.readTextFile("data/access.json") + .map(new MapFunction() { + @Override + public Access map(String value) throws Exception { + // TODO... json ==> Access + + try { + return JSON.parseObject(value, Access.class); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + } + }).filter(x -> x != null) + .filter(new FilterFunction() { + @Override + public boolean filter(Access value) throws Exception { + return "startup".equals(value.event); + } + }) + .map(new GaodeLocationMapFunction()); + + SingleOutputStreamOperator> result = cleanStream.map(new MapFunction>() { + @Override + public Tuple3 map(Access value) throws Exception { + return Tuple3.of(value.province, value.nu, 1); + } + }).keyBy(new KeySelector, Tuple2>() { + @Override + public Tuple2 getKey(Tuple3 value) throws Exception { + return Tuple2.of(value.f0, value.f1); + } + }).sum(2);//.print("省份维度统计新老用户:").setParallelism(1); + + + FlinkJedisPoolConfig conf = new FlinkJedisPoolConfig.Builder().setHost("127.0.0.1").build(); + + result.addSink(new RedisSink>(conf, new RedisExampleMapper())); + + + environment.execute("ProvinceUserCntAppV1"); + + } + + static class RedisExampleMapper implements RedisMapper> { + + @Override + public RedisCommandDescription getCommandDescription() { + return new RedisCommandDescription(RedisCommand.HSET, "province-user-cnt:20301002"); + } + + @Override + public String getKeyFromData(Tuple3 data) { + return data.f0 + "_" + data.f1; + } + + @Override + public String getValueFromData(Tuple3 data) { + return data.f2+""; + } + + } +} diff --git a/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/TopNAppV1.java b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/TopNAppV1.java new file mode 100644 index 00000000..b26463f9 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/TopNAppV1.java @@ -0,0 +1,125 @@ +package com.imooc.flink.app; + +import com.alibaba.fastjson.JSON; +import com.imooc.flink.domain.Access; +import com.imooc.flink.domain.EventCatagoryProductCount; +import com.imooc.flink.udf.TopNAggregateFunction; +import com.imooc.flink.udf.TopNWindowFunction; +import org.apache.flink.api.common.functions.FilterFunction; +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.common.state.ListState; +import org.apache.flink.api.common.state.ListStateDescriptor; +import org.apache.flink.api.java.functions.KeySelector; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.api.java.tuple.Tuple3; +import org.apache.flink.api.java.tuple.Tuple4; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.shaded.guava18.com.google.common.collect.Lists; +import org.apache.flink.streaming.api.datastream.KeyedStream; +import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; +import org.apache.flink.streaming.api.datastream.WindowedStream; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.api.functions.KeyedProcessFunction; +import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; +import org.apache.flink.streaming.api.windowing.assigners.SlidingEventTimeWindows; +import org.apache.flink.streaming.api.windowing.time.Time; +import org.apache.flink.streaming.api.windowing.windows.TimeWindow; +import org.apache.flink.streaming.connectors.redis.RedisSink; +import org.apache.flink.streaming.connectors.redis.common.config.FlinkJedisPoolConfig; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisCommand; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisCommandDescription; +import org.apache.flink.streaming.connectors.redis.common.mapper.RedisMapper; +import org.apache.flink.util.Collector; + +import java.util.ArrayList; +import java.util.List; + +public class TopNAppV1 { + public static void main(String[] args) throws Exception { + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + + SingleOutputStreamOperator cleanStream = env.readTextFile("data/access.json") + .map(new MapFunction() { + @Override + public Access map(String value) throws Exception { + // json ==> 自定义对象 + try { + return JSON.parseObject(value, Access.class); + } catch (Exception e) { + e.printStackTrace(); + // TODO... 把这些异常的数据记录到某个地方去 + return null; + } + } + }).filter(x -> x != null) + .assignTimestampsAndWatermarks( + new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(20)) { + @Override + public long extractTimestamp(Access element) { + return element.time; + } + } + ).filter(new FilterFunction() { + @Override + public boolean filter(Access value) throws Exception { + return !"startup".equals(value.event); + } + }); + + WindowedStream, TimeWindow> windowStream = cleanStream.keyBy(new KeySelector>() { + @Override + public Tuple3 getKey(Access value) throws Exception { + return Tuple3.of(value.event, value.product.category, value.product.name); + } + }).window(SlidingEventTimeWindows.of(Time.minutes(5), Time.minutes(1))); + + // 作用上WindowFunction + + SingleOutputStreamOperator aggStream = windowStream.aggregate(new TopNAggregateFunction(), new TopNWindowFunction()); + + aggStream.keyBy(new KeySelector>() { + @Override + public Tuple4 getKey(EventCatagoryProductCount value) throws Exception { + return Tuple4.of(value.event, value.catagory, value.start, value.end); + } + }).process(new KeyedProcessFunction, EventCatagoryProductCount, List>() { + + private transient ListState listState; + + @Override + public void open(Configuration parameters) throws Exception { + listState = getRuntimeContext().getListState(new ListStateDescriptor("cnt-state", EventCatagoryProductCount.class)); + } + + @Override + public void processElement(EventCatagoryProductCount value, Context ctx, Collector> out) throws Exception { + listState.add(value); + + // 注册一个定时器 + ctx.timerService().registerEventTimeTimer(value.end + 1); + } + + + // 在这里完成TopN操作 + @Override + public void onTimer(long timestamp, OnTimerContext ctx, Collector> out) throws Exception { + ArrayList list = Lists.newArrayList(listState.get()); + + list.sort((x,y) -> Long.compare(y.count, x.count)); + + ArrayList sorted = new ArrayList<>(); + + for (int i = 0; i < Math.min(3, list.size()); i++) { + EventCatagoryProductCount bean = list.get(i); + sorted.add(bean); + } + + out.collect(sorted); + } + }).print().setParallelism(1); + + env.execute(); + } + +} diff --git a/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/TopNTest.java b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/TopNTest.java new file mode 100644 index 00000000..f733506e --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/app/TopNTest.java @@ -0,0 +1,133 @@ +package com.imooc.flink.app; + +import com.alibaba.fastjson.JSON; +import com.imooc.flink.domain.Access; +import com.imooc.flink.domain.EventCatagoryProductCount; +import com.imooc.flink.udf.TopNAggregateFunction; +import com.imooc.flink.udf.TopNWindowFunction; +import org.apache.flink.api.common.functions.FilterFunction; +import org.apache.flink.api.common.functions.MapFunction; +import org.apache.flink.api.common.state.ListState; +import org.apache.flink.api.common.state.ListStateDescriptor; +import org.apache.flink.api.java.functions.KeySelector; +import org.apache.flink.api.java.tuple.Tuple3; +import org.apache.flink.api.java.tuple.Tuple4; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.shaded.guava18.com.google.common.collect.Lists; +import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; +import org.apache.flink.streaming.api.datastream.WindowedStream; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.api.functions.KeyedProcessFunction; +import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; +import org.apache.flink.streaming.api.windowing.assigners.SlidingEventTimeWindows; +import org.apache.flink.streaming.api.windowing.time.Time; +import org.apache.flink.streaming.api.windowing.windows.TimeWindow; +import org.apache.flink.util.Collector; +import redis.clients.jedis.Tuple; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class TopNTest { + + /** + * 统计五分钟内的不同event(加购物车、浏览...)类型、类别、商品的TOPN + *

+ * {"channel":"华为商城","device":"8fe721d6-cd41-4869-a14d-23b4fbfc70df", + * "deviceType":"iPhone 10","event":"startup","ip":"114.247.50.2","net":"5G", + * "nu":1,"os":"iOS","time":1647195061,"uid":"user_1","version":"V1.2.2"} + */ + public static void main(String[] args) throws Exception { + + // 五分钟内,用window实现,滚动窗口 + + StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + + SingleOutputStreamOperator cleanStream = env.readTextFile("data/access.json") + .map(new MapFunction() { + @Override + public Access map(String value) throws Exception { + // json ==> 自定义对象 + try { + return JSON.parseObject(value, Access.class); + } catch (Exception e) { + e.printStackTrace(); + // TODO... 把这些异常的数据记录到某个地方去 + return null; + } + } + }).filter(Objects::nonNull) + .assignTimestampsAndWatermarks( + new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(20)) { + @Override + public long extractTimestamp(Access element) { + return element.time; + } + } + ).filter(new FilterFunction() { + @Override + public boolean filter(Access value) throws Exception { + return !"startup".equals(value.event); + } + }); + + // 窗口按“类型、类别、商品”划分 + WindowedStream, TimeWindow> windowStream = cleanStream.keyBy(new KeySelector>() { + @Override + public Tuple3 getKey(Access access) throws Exception { + return Tuple3.of(access.event, access.product.category, access.product.name); + } + }).window(SlidingEventTimeWindows.of(Time.minutes(5), Time.minutes(1))); + + // 同窗口汇总 + SingleOutputStreamOperator aggStream = windowStream.aggregate(new TopNAggregateFunction(), new TopNWindowFunction()); + + // 汇总后排序 + + aggStream.keyBy(new KeySelector>() { + @Override + public Tuple4 getKey(EventCatagoryProductCount value) throws Exception { + return Tuple4.of(value.event, value.catagory, value.start, value.end); + } + }).process(new KeyedProcessFunction, EventCatagoryProductCount, List>() { + + private transient ListState listState; + + @Override + public void open(Configuration parameters) throws Exception { + listState = getRuntimeContext().getListState(new ListStateDescriptor("cnt-state", EventCatagoryProductCount.class)); + } + + @Override + public void processElement(EventCatagoryProductCount value, Context ctx, Collector> out) throws Exception { + listState.add(value); + + // 注册一个定时器 + ctx.timerService().registerEventTimeTimer(value.end + 1); + } + + // 在这里完成TopN操作 + @Override + public void onTimer(long timestamp, OnTimerContext ctx, Collector> out) throws Exception { + ArrayList list = Lists.newArrayList(listState.get()); + + list.sort((x,y) -> Long.compare(y.count, x.count)); + + ArrayList sorted = new ArrayList<>(); + + for (int i = 0; i < Math.min(3, list.size()); i++) { + EventCatagoryProductCount bean = list.get(i); + sorted.add(bean); + } + + out.collect(sorted); + } + }).print().setParallelism(1); + + env.execute(); + } + + +} diff --git a/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/domain/Access.java b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/domain/Access.java new file mode 100644 index 00000000..a0548e7e --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/domain/Access.java @@ -0,0 +1,43 @@ +package com.imooc.flink.domain; + +public class Access { + + public String device; + public String deviceType; + public String os; + // startup启动; + public String event; + public String net; + public String channel; + public String uid; + public int nu; // 1新 + public int nu2; + public String ip; // ==> ip去解析 + public long time; + public String version; + public String province; + public String city; + + public Product product; + + @Override + public String toString() { + return "Access{" + + "device='" + device + '\'' + + ", deviceType='" + deviceType + '\'' + + ", os='" + os + '\'' + + ", event='" + event + '\'' + + ", net='" + net + '\'' + + ", channel='" + channel + '\'' + + ", uid='" + uid + '\'' + + ", nu=" + nu + + ", nu2=" + nu2 + + ", ip='" + ip + '\'' + + ", time=" + time + + ", version='" + version + '\'' + + ", province='" + province + '\'' + + ", city='" + city + '\'' + + ", product=" + product + + '}'; + } +} diff --git a/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/domain/EventCatagoryProductCount.java b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/domain/EventCatagoryProductCount.java new file mode 100644 index 00000000..0d70a1bf --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/domain/EventCatagoryProductCount.java @@ -0,0 +1,28 @@ +package com.imooc.flink.domain; + +public class EventCatagoryProductCount { + + public String event; + public String catagory; + public String product; + public long count; + public long start; + public long end; + + public EventCatagoryProductCount() { + } + + public EventCatagoryProductCount(String event, String catagory, String product, long count, long start, long end) { + this.event = event; + this.catagory = catagory; + this.product = product; + this.count = count; + this.start = start; + this.end = end; + } + + @Override + public String toString() { + return event + "\t" + catagory + "\t" + product + "\t" + count + "\t" + start + "\t" + end; + } +} diff --git a/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/domain/Product.java b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/domain/Product.java new file mode 100644 index 00000000..47a7a957 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/domain/Product.java @@ -0,0 +1,15 @@ +package com.imooc.flink.domain; + +public class Product { + + public String category; + public String name; + + @Override + public String toString() { + return "Product{" + + "category='" + category + '\'' + + ", name='" + name + '\'' + + '}'; + } +} diff --git a/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/udf/GaodeLocationMapFunction.java b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/udf/GaodeLocationMapFunction.java new file mode 100644 index 00000000..44f60b39 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/udf/GaodeLocationMapFunction.java @@ -0,0 +1,65 @@ +package com.imooc.flink.udf; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.imooc.flink.domain.Access; +import com.imooc.flink.utils.StringUtils; +import com.mysql.jdbc.AbandonedConnectionCleanupThread; +import org.apache.flink.api.common.functions.RichMapFunction; +import org.apache.flink.configuration.Configuration; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; + +public class GaodeLocationMapFunction extends RichMapFunction { + + CloseableHttpClient httpClient; + + @Override + public void open(Configuration parameters) throws Exception { + httpClient = HttpClients.createDefault(); + } + + @Override + public void close() throws Exception { + if(httpClient != null) httpClient.close(); + } + + @Override + public Access map(Access value) throws Exception { + String url = "https://restapi.amap.com/v3/ip?ip="+value.ip+"&output=json&key="+ StringUtils.GAODE_KEY; + + CloseableHttpResponse response = null; + + String province = "-"; + String city = "-"; + + try { + HttpGet httpGet = new HttpGet(url); + response = httpClient.execute(httpGet); + int statusCode = response.getStatusLine().getStatusCode(); + if(statusCode == 200) { + HttpEntity entity = response.getEntity(); + String result = EntityUtils.toString(entity, "UTF-8"); + + + JSONObject jsonObject = JSON.parseObject(result); + province = jsonObject.getString("province"); + city = jsonObject.getString("city"); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + response.close(); + value.province = province; + value.city = city; + } + + return value; + } +} diff --git a/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/udf/TopNAggregateFunction.java b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/udf/TopNAggregateFunction.java new file mode 100644 index 00000000..ac9a20b0 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/udf/TopNAggregateFunction.java @@ -0,0 +1,26 @@ +package com.imooc.flink.udf; + +import com.imooc.flink.domain.Access; +import org.apache.flink.api.common.functions.AggregateFunction; + +public class TopNAggregateFunction implements AggregateFunction { + @Override + public Long createAccumulator() { + return 0L; + } + + @Override + public Long add(Access value, Long accumulator) { + return accumulator + 1; + } + + @Override + public Long getResult(Long accumulator) { + return accumulator; + } + + @Override + public Long merge(Long a, Long b) { + return null; + } +} diff --git a/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/udf/TopNWindowFunction.java b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/udf/TopNWindowFunction.java new file mode 100644 index 00000000..4b427d0b --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/udf/TopNWindowFunction.java @@ -0,0 +1,22 @@ +package com.imooc.flink.udf; + +import com.imooc.flink.domain.EventCatagoryProductCount; +import org.apache.flink.api.java.tuple.Tuple3; +import org.apache.flink.streaming.api.functions.windowing.WindowFunction; +import org.apache.flink.streaming.api.windowing.windows.TimeWindow; +import org.apache.flink.util.Collector; + +public class TopNWindowFunction implements WindowFunction, TimeWindow> { + @Override + public void apply(Tuple3 value, TimeWindow window, Iterable input, Collector out) throws Exception { + + String event = value.f0; + String category = value.f1; + String product = value.f2; + Long count = input.iterator().next(); + long start = window.getStart(); + long end = window.getEnd(); + + out.collect(new EventCatagoryProductCount(event, category, product,count,start, end)); + } +} diff --git a/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/utils/StringUtils.java b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/utils/StringUtils.java new file mode 100644 index 00000000..cf785a3d --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-project/src/main/java/com/imooc/flink/utils/StringUtils.java @@ -0,0 +1,6 @@ +package com.imooc.flink.utils; + +public class StringUtils { + + public static final String GAODE_KEY = "6d5be617aa12cd42f6c7421cbfa8883a"; +} diff --git a/bigdata/imooc-flink/imooc-flink-sql/pom.xml b/bigdata/imooc-flink/imooc-flink-sql/pom.xml new file mode 100644 index 00000000..64b5f783 --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-sql/pom.xml @@ -0,0 +1,52 @@ + + + + imooc-flink + com.imooc.flink + 1.0 + + 4.0.0 + + imooc-flink-sql + + + + org.apache.flink + flink-table-api-java-bridge_${scala.binary.version} + ${flink.version} + + + + + org.apache.flink + flink-csv + ${flink.version} + + + + org.apache.flink + flink-clients_${scala.binary.version} + + + + org.apache.flink + flink-table-planner-blink_${scala.binary.version} + ${flink.version} + + + org.apache.flink + flink-streaming-scala_${scala.binary.version} + ${flink.version} + + + + com.fasterxml.jackson.core + jackson-databind + 2.6.7 + compile + + + + \ No newline at end of file diff --git a/bigdata/imooc-flink/imooc-flink-upgrade/pom.xml b/bigdata/imooc-flink/imooc-flink-upgrade/pom.xml new file mode 100644 index 00000000..783c13aa --- /dev/null +++ b/bigdata/imooc-flink/imooc-flink-upgrade/pom.xml @@ -0,0 +1,67 @@ + + + + imooc-flink + com.imooc.flink + 1.0 + + 4.0.0 + + imooc-flink-upgrade + + + + UTF-8 + + 1.10.0 + 2.12 + 1.8 + ${target.java.version} + ${target.java.version} + 2.12.1 + + + + + org.apache.flink + flink-streaming-java_${scala.binary.version} + ${flink.version} + + + + org.apache.flink + flink-clients_${scala.binary.version} + ${flink.version} + + + + org.apache.flink + flink-table-planner_${scala.binary.version} + ${flink.version} + + + + + + + + + + org.apache.logging.log4j + log4j-slf4j-impl + ${log4j.version} + + + org.apache.logging.log4j + log4j-api + ${log4j.version} + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + + + \ No newline at end of file diff --git a/bigdata/imooc-flink/pom.xml b/bigdata/imooc-flink/pom.xml new file mode 100644 index 00000000..2eeea636 --- /dev/null +++ b/bigdata/imooc-flink/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + com.imooc.flink + imooc-flink + pom + 1.0 + + + imooc-flink-datastream + imooc-flink-sql + imooc-flink-dataset + imooc-flink-basic + imooc-flink-project + imooc-clickhouse + imooc-flink-upgrade + + + + + UTF-8 + 1.12.1 + 2.12 + 1.8 + ${target.java.version} + ${target.java.version} + 2.12.1 + + + + + + org.apache.flink + flink-streaming-java_${scala.binary.version} + ${flink.version} + + + + org.apache.flink + flink-clients_${scala.binary.version} + ${flink.version} + + + + + diff --git a/database/elasticsearch/pom.xml b/database/elasticsearch/pom.xml deleted file mode 100644 index 7e7ceae8..00000000 --- a/database/elasticsearch/pom.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - 4.0.0 - - cn.lastwhisper - elasticsearch - 1.0-SNAPSHOT - - - - - org.elasticsearch.client - elasticsearch-rest-high-level-client - 6.5.3 - - - - - mysql - mysql-connector-java - 5.1.48 - - - - - - commons-dbutils - commons-dbutils - 1.7 - - - - - com.alibaba - fastjson - 1.2.62 - - - - org.apache.logging.log4j - log4j-core - 2.9.1 - - - - org.apache.logging.log4j - log4j-api - 2.9.1 - - - - junit - junit - 4.12 - test - - - \ No newline at end of file diff --git a/database/elasticsearch/src/main/java/cn/lastwhisper/elasticsearch/operation/EsDataAdapter.java b/database/elasticsearch/src/main/java/cn/lastwhisper/elasticsearch/operation/EsDataAdapter.java deleted file mode 100644 index 068ae92b..00000000 --- a/database/elasticsearch/src/main/java/cn/lastwhisper/elasticsearch/operation/EsDataAdapter.java +++ /dev/null @@ -1,155 +0,0 @@ -package cn.lastwhisper.elasticsearch.operation; - -import cn.lastwhisper.elasticsearch.operation.entity.Sku; -import cn.lastwhisper.elasticsearch.operation.enums.DbConfig; -import cn.lastwhisper.elasticsearch.operation.utils.DateUtils; -import com.alibaba.fastjson.JSON; -import org.apache.commons.dbutils.QueryRunner; -import org.apache.commons.dbutils.handlers.BeanListHandler; -import org.apache.commons.dbutils.handlers.ScalarHandler; -import org.apache.http.HttpHost; -import org.elasticsearch.action.bulk.BulkRequest; -import org.elasticsearch.action.bulk.BulkResponse; -import org.elasticsearch.action.index.IndexRequest; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.RestHighLevelClient; - -import java.io.IOException; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * 青橙商城数据导入 - * @author lastwhisper - * @date 2019/12/1 - */ -public class EsDataAdapter { - - private static Connection conn; - private static QueryRunner queryRunner; - - private static RestHighLevelClient restHighLevelClient; - - static { - try { - // 初始化mysql连接 - Class.forName(DbConfig.DB_DRIVER.getValue()); - conn = DriverManager.getConnection(DbConfig.DB_URL.getValue(), DbConfig.DB_USERNAME.getValue(), DbConfig.DB_PASSWORD.getValue()); - // dbutils - queryRunner = new QueryRunner(); - // 初始化es连接 - HttpHost http = new HttpHost(DbConfig.ES_HOSTNAME.getValue(), 9200, DbConfig.ES_SCHEMA.getValue()); - RestClientBuilder builder = RestClient.builder(http); - restHighLevelClient = new RestHighLevelClient(builder); - } catch (Exception e) { - e.printStackTrace(); - } - - - } - - public static void main(String[] args) throws SQLException, IOException { - long beginTime = System.currentTimeMillis(); - - // http:200 耗时:22.1s - // 总耗时:25910 - fullImport(); - - // 总耗时:26995 - //batchImport(); - - long endTime = System.currentTimeMillis(); - System.out.println("总耗时:" + (endTime - beginTime)); - } - - - public static void fullImport() throws SQLException, IOException { - try { - List skuList = fetchData(); - BulkResponse response = bulkImport(skuList); - System.out.println("http:" + response.status().getStatus() - + " 耗时:" + response.getTook()); - if (response.hasFailures()) System.out.println("失败原因:" + response.buildFailureMessage()); - } catch (SQLException e) { - e.printStackTrace(); - } finally { - conn.close(); - restHighLevelClient.close(); - } - } - - public static void batchImport() throws SQLException, IOException { - try { - int frequency = 0; - Long total = total();//导入数据的总数 - Long basicTotal = 10000L;//每次导入的量 - Long start = 0L, end = basicTotal; - while (total > 0L) { - List skuList = fetchData(start, end); - BulkResponse response = bulkImport(skuList); - System.out.println("http:" + response.status().getStatus() - + " 耗时:" + response.getTook()); - - if (response.hasFailures()) System.out.println("失败原因:" + response.buildFailureMessage()); - - if (total <= basicTotal) { - basicTotal = total; - } - total -= basicTotal; - start += basicTotal; - end += basicTotal; - frequency++; - } - System.out.println("分批次数:" + frequency); - } catch (SQLException e) { - e.printStackTrace(); - } finally { - conn.close(); - restHighLevelClient.close(); - } - } - - public static Long total() throws SQLException { - String sql = "SELECT COUNT(*) FROM tb_sku"; - return queryRunner.query(conn, sql, new ScalarHandler<>()); - } - - public static List fetchData(Long start, Long end) throws SQLException { - String sql = "SELECT id skuId,name,price,image,create_time createTime,category_name categoryName,brand_name brandName,spec,comment_num commentNum,sale_num saleNum,spu_id spuId FROM tb_sku limit ?,?"; - return queryRunner.query(conn, sql, new BeanListHandler<>(Sku.class), start, end); - } - - public static List fetchData() throws SQLException { - String sql = "SELECT id skuId,name,price,image,create_time createTime,category_name categoryName,brand_name brandName,spec,comment_num commentNum,sale_num saleNum,spu_id spuId FROM tb_sku"; - return queryRunner.query(conn, sql, new BeanListHandler<>(Sku.class)); - } - - public static BulkResponse bulkImport(List skuList) throws IOException { - BulkRequest bulkRequest = new BulkRequest(); - for (Sku sku : skuList) { - Map skuMap = new HashMap(); - IndexRequest indexRequest = new IndexRequest("sku", "doc", sku.getSkuId()); - skuMap.put("name", sku.getName()); - skuMap.put("price", sku.getPrice()); - skuMap.put("image", sku.getImage()); - skuMap.put("createTime", DateUtils.dateFormat(sku.getCreateTime())); - skuMap.put("categoryName", sku.getCategoryName()); - skuMap.put("brandName", sku.getBrandName()); - // "{'颜色': '红色', '版本': '8GB+128GB'}" - Map spec = JSON.parseObject(sku.getSpec()); - skuMap.put("spec", spec); - skuMap.put("commentNum", sku.getCommentNum()); - skuMap.put("saleNum", sku.getSaleNum()); - skuMap.put("spuId", sku.getSpuId()); - indexRequest.source(skuMap); - bulkRequest.add(indexRequest); - } - return restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT); - } -} diff --git a/database/elasticsearch/src/main/java/cn/lastwhisper/elasticsearch/operation/entity/Sku.java b/database/elasticsearch/src/main/java/cn/lastwhisper/elasticsearch/operation/entity/Sku.java deleted file mode 100644 index 1fe9ffaa..00000000 --- a/database/elasticsearch/src/main/java/cn/lastwhisper/elasticsearch/operation/entity/Sku.java +++ /dev/null @@ -1,111 +0,0 @@ -package cn.lastwhisper.elasticsearch.operation.entity; - -import java.util.Date; - -/** - * - * @author lastwhisper - * @date 2019/12/1 - */ -public class Sku { - private String skuId; - private String name; - private Integer price; - private String image; - private Date createTime; - private String categoryName; - private String brandName; - private String spec; - private Integer commentNum; - private Integer saleNum; - private String spuId; - - public String getSkuId() { - return skuId; - } - - public void setSkuId(String skuId) { - this.skuId = skuId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Integer getPrice() { - return price; - } - - public void setPrice(Integer price) { - this.price = price; - } - - public String getImage() { - return image; - } - - public void setImage(String image) { - this.image = image; - } - - public Date getCreateTime() { - return createTime; - } - - public void setCreateTime(Date createTime) { - this.createTime = createTime; - } - - public String getCategoryName() { - return categoryName; - } - - public void setCategoryName(String categoryName) { - this.categoryName = categoryName; - } - - public String getBrandName() { - return brandName; - } - - public void setBrandName(String brandName) { - this.brandName = brandName; - } - - public String getSpec() { - return spec; - } - - public void setSpec(String spec) { - this.spec = spec; - } - - public Integer getCommentNum() { - return commentNum; - } - - public void setCommentNum(Integer commentNum) { - this.commentNum = commentNum; - } - - public Integer getSaleNum() { - return saleNum; - } - - public void setSaleNum(Integer saleNum) { - this.saleNum = saleNum; - } - - public String getSpuId() { - return spuId; - } - - public void setSpuId(String spuId) { - this.spuId = spuId; - } - -} diff --git a/database/elasticsearch/src/main/java/cn/lastwhisper/elasticsearch/operation/enums/DbConfig.java b/database/elasticsearch/src/main/java/cn/lastwhisper/elasticsearch/operation/enums/DbConfig.java deleted file mode 100644 index b04757cf..00000000 --- a/database/elasticsearch/src/main/java/cn/lastwhisper/elasticsearch/operation/enums/DbConfig.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.lastwhisper.elasticsearch.operation.enums; - -public enum DbConfig { - DB_DRIVER("com.mysql.jdbc.Driver"), - DB_URL("jdbc:mysql://127.0.0.1:3306/qingcheng_goods?useUnicode=true&characterEncoding=utf8&useSSL=true"), - DB_USERNAME("root"), - DB_PASSWORD("root"), - - ES_HOSTNAME("127.0.0.1"), - ES_SCHEMA("http"), - ; - - String value; - - DbConfig(String value) { - this.value = value; - } - - public String getValue() { - return value; - } -} \ No newline at end of file diff --git a/database/elasticsearch/src/main/java/cn/lastwhisper/elasticsearch/operation/utils/DateUtils.java b/database/elasticsearch/src/main/java/cn/lastwhisper/elasticsearch/operation/utils/DateUtils.java deleted file mode 100644 index fc942509..00000000 --- a/database/elasticsearch/src/main/java/cn/lastwhisper/elasticsearch/operation/utils/DateUtils.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.lastwhisper.elasticsearch.operation.utils; - -import java.text.SimpleDateFormat; -import java.util.Date; - -/** - * 时间工具类 - * @author lastwhisper - * @date 2019/12/1 - */ -public class DateUtils { - - static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - - public static String dateFormat(Date date) { - return sdf.format(date); - } - -} diff --git a/database/elasticsearch/src/test/java/cn/lastwhisper/elasticsearch/operation/BulkSave.java b/database/elasticsearch/src/test/java/cn/lastwhisper/elasticsearch/operation/BulkSave.java deleted file mode 100644 index a6ebea53..00000000 --- a/database/elasticsearch/src/test/java/cn/lastwhisper/elasticsearch/operation/BulkSave.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.lastwhisper.elasticsearch.operation; - -import org.apache.http.HttpHost; -import org.elasticsearch.action.bulk.BulkRequest; -import org.elasticsearch.action.bulk.BulkResponse; -import org.elasticsearch.action.index.IndexRequest; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.RestHighLevelClient; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - - -/** - * - * @author lastwhisper - * @date 2019/12/1 - */ -public class BulkSave { - - public static void main(String[] args) throws IOException { - //1.连接rest接口 - HttpHost http = new HttpHost("127.0.0.1", 9200, "http"); - RestClientBuilder builder = RestClient.builder(http);//rest构建器 - RestHighLevelClient restHighLevelClient = new - RestHighLevelClient(builder);//高级客户端对象 - //2.封装请求对象 - BulkRequest bulkRequest = new BulkRequest(); - IndexRequest indexRequest = new IndexRequest("sku", "doc", "4"); - Map skuMap = new HashMap(); - skuMap.put("name", "华为p30pro 火爆上市"); - skuMap.put("brandName", "华为"); - skuMap.put("categoryName", "手机"); - skuMap.put("price", 1010221); - skuMap.put("createTime", "2019‐05‐01"); - skuMap.put("saleNum", 101021); - skuMap.put("commentNum", 10102321); - Map spec = new HashMap(); - spec.put("网络制式", "移动4G"); - spec.put("屏幕尺寸", "5"); - skuMap.put("spec", spec); - indexRequest.source(skuMap); - bulkRequest.add(indexRequest);//可以多次添加 - //3.获取响应结果 - BulkResponse response = - restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT); - int status = response.status().getStatus(); - System.out.println(status); - String message = response.buildFailureMessage(); - System.out.println(message); - restHighLevelClient.close(); - } - -} diff --git a/database/elasticsearch/src/test/java/cn/lastwhisper/elasticsearch/operation/Save.java b/database/elasticsearch/src/test/java/cn/lastwhisper/elasticsearch/operation/Save.java deleted file mode 100644 index 9c7aeb92..00000000 --- a/database/elasticsearch/src/test/java/cn/lastwhisper/elasticsearch/operation/Save.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.lastwhisper.elasticsearch.operation; - -import org.apache.http.HttpHost; -import org.elasticsearch.action.index.IndexRequest; -import org.elasticsearch.action.index.IndexResponse; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.RestHighLevelClient; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -/** - * 新增或修改数据 - * @author lastwhisper - * @date 2019/11/26 - */ -public class Save { - /** - * HttpHost : url地址封装 - * RestClientBuilder: rest客户端构建器 - * RestHighLevelClient: rest高级客户端 - * IndexRequest: 新增或修改请求 - * IndexResponse:新增或修改的响应结果 - */ - public static void main(String[] args) throws IOException { - //1.连接rest接口 - HttpHost http = new HttpHost("127.0.0.1", 9200, "http"); - // rest构建器 - RestClientBuilder builder = RestClient.builder(http); - // 高级客户端对象 - RestHighLevelClient restHighLevelClient = new RestHighLevelClient(builder); - //2.封装请求对象 - IndexRequest indexRequest = new IndexRequest("sku", "doc", "3"); - Map skuMap = new HashMap(); - skuMap.put("name", "华为p30pro"); - skuMap.put("brandName", "华为"); - skuMap.put("categoryName", "手机"); - skuMap.put("price", 1010221); - skuMap.put("createTime", "2019-05-01"); - skuMap.put("saleNum", 101021); - skuMap.put("commentNum", 10102321); - Map spec = new HashMap(); - spec.put("网络制式", "移动4G"); - spec.put("屏幕尺寸", "5"); - skuMap.put("spec", spec); - indexRequest.source(skuMap); - //3.获取响应结果 - IndexResponse response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT); - int status = response.status().getStatus(); - System.out.println("响应状态:" + status); - restHighLevelClient.close(); - } - -} diff --git a/database/elasticsearch/src/test/java/cn/lastwhisper/elasticsearch/operation/Select.java b/database/elasticsearch/src/test/java/cn/lastwhisper/elasticsearch/operation/Select.java deleted file mode 100644 index 3f4633a4..00000000 --- a/database/elasticsearch/src/test/java/cn/lastwhisper/elasticsearch/operation/Select.java +++ /dev/null @@ -1,225 +0,0 @@ -package cn.lastwhisper.elasticsearch.operation; - -import org.apache.http.HttpHost; -import org.elasticsearch.action.search.SearchRequest; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.index.query.BoolQueryBuilder; -import org.elasticsearch.index.query.MatchQueryBuilder; -import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.index.query.TermQueryBuilder; -import org.elasticsearch.search.SearchHit; -import org.elasticsearch.search.SearchHits; -import org.elasticsearch.search.aggregations.Aggregation; -import org.elasticsearch.search.aggregations.AggregationBuilders; -import org.elasticsearch.search.aggregations.Aggregations; -import org.elasticsearch.search.aggregations.bucket.terms.Terms; -import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder; -import org.elasticsearch.search.builder.SearchSourceBuilder; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - -/** - * 各种查询 - * @author lastwhisper - * @date 2019/11/26 - */ -public class Select { - - private RestHighLevelClient restHighLevelClient = null; - private SearchRequest searchRequest = null; - - @Before - public void init() { - //1.连接rest接口 - HttpHost http = new HttpHost("127.0.0.1", 9200, "http"); - RestClientBuilder builder = RestClient.builder(http);//rest构建器 - restHighLevelClient = new - RestHighLevelClient(builder);//高级客户端对象 - //2.封装查询请求 - searchRequest = new SearchRequest("sku"); - searchRequest.types("doc"); //设置查询的类型 - } - - //@After - public void after() throws IOException { - //3.获取查询结果 - SearchResponse searchResponse = restHighLevelClient.search(searchRequest, - RequestOptions.DEFAULT); - - // 查询花费时间,单位是毫秒 - TimeValue took = searchResponse.getTook(); - // 分片信息 - int total = searchResponse.getTotalShards(); - int success = searchResponse.getSuccessfulShards(); - int skipped = searchResponse.getSkippedShards(); - int failed = searchResponse.getFailedShards(); - // 搜索结果总览对象 - SearchHits searchHits = searchResponse.getHits(); - // 搜索到的总条数 - long totalHits = searchHits.getTotalHits(); - // 所有结果中文档得分的最高分 - float maxScore = searchHits.getMaxScore(); - - System.out.println("took:" + took); - System.out.println("_shards:"); - System.out.println(" total:" + total); - System.out.println(" success:" + success); - System.out.println(" skipped:" + skipped); - System.out.println(" failed:" + failed); - System.out.println("hits:"); - System.out.println(" total:" + totalHits); - System.out.println(" max_score:" + maxScore); - System.out.println(" hits:"); - // 搜索结果的文档对象数组,每个元素是一条搜索到的文档信息 - SearchHit[] hits = searchHits.getHits(); - for (SearchHit hit : hits) { - // 索引库 - String index = hit.getIndex(); - // 文档类型 - String type = hit.getType(); - // 文档id - String id = hit.getId(); - // 文档得分 - float score = hit.getScore(); - // 文档的源数据 - String source = hit.getSourceAsString(); - System.out.println(" _index:" + index); - System.out.println(" _type:" + type); - System.out.println(" _id:" + id); - System.out.println(" _score:" + score); - System.out.println(" _source:" + source); - } - restHighLevelClient.close(); - } - - - /** - * 匹配查询 - * 语法: - * SearchRequest: 查询请求对象 - * SearchResponse:查询响应对象 - * SearchSourceBuilder:查询源构建器 - * MatchQueryBuilder:匹配查询构建器 - * 示例: - * 查询商品名称包含手机的记录。 - */ - @Test - public void test1() throws IOException { - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", "小米电视"); - searchSourceBuilder.query(matchQueryBuilder); - searchRequest.source(searchSourceBuilder); - } - - /** - * 布尔与词条查询 - * 语法: - * QueryBuilders:查询构建器工厂 - * BoolQueryBuilder:布尔查询构建器 - * TermQueryBuilder:词条查询构建器 - * 示例: - * 查询名称包含手机的,并且品牌为小米的记录 - */ - @Test - public void test2() throws IOException { - //2.封装查询请求 - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - // 布尔查询构建器 - BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); - MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", "手机"); - // 词条查询构建器 - TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("brandName", "小米"); - - boolQueryBuilder.must(matchQueryBuilder); - boolQueryBuilder.must(termQueryBuilder); - - searchSourceBuilder.query(boolQueryBuilder); - searchRequest.source(searchSourceBuilder); - - } - - /** - * 过滤查询 - * 示例:筛选品牌为小米的记录 - */ - @Test - public void test3() throws IOException { - //2.封装查询请求 - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - // 布尔查询构建器 - BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); - // 词条查询构建器 - TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("brandName", "小米"); - - boolQueryBuilder.filter(termQueryBuilder); - - searchSourceBuilder.query(boolQueryBuilder); - searchRequest.source(searchSourceBuilder); - } - - /** - * 分组(聚合)查询 - * 语法: - * AggregationBuilders:聚合构建器工厂 - * TermsAggregationBuilder:词条聚合构建器 - * Aggregations:分组结果封装 - * Terms.Bucket: 桶 - * 示例: - * 按商品分类分组查询,求出每个分类的文档数 - */ - @Test - public void test4() throws IOException { - //1.连接rest接口 - HttpHost http = new HttpHost("127.0.0.1", 9200, "http"); - RestClientBuilder builder = RestClient.builder(http);//rest构建器 - RestHighLevelClient restHighLevelClient = new - RestHighLevelClient(builder);//高级客户端对象 - //2.封装查询请求 - SearchRequest searchRequest = new SearchRequest("sku"); - searchRequest.types("doc"); //设置查询的类型 - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - - TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders - .terms("sku_category").field("categoryName"); - searchSourceBuilder.aggregation(termsAggregationBuilder); - searchSourceBuilder.size(0); - searchRequest.source(searchSourceBuilder); - - //3.获取查询结果 - SearchResponse searchResponse = restHighLevelClient.search(searchRequest, - RequestOptions.DEFAULT); - Aggregations aggregations = searchResponse.getAggregations(); - - Map asMap = aggregations.getAsMap(); - Terms terms = (Terms) asMap.get("sku_category"); - List buckets = terms.getBuckets(); - for (Terms.Bucket bucket : buckets) { - System.out.println(bucket.getKeyAsString() + ":" + bucket.getDocCount() - ); - } - restHighLevelClient.close(); - } - - /** - * 范围查询 - * RangeQueryBuilder rangeQueryBuilder = - * QueryBuilders.rangeQuery("price").gte(10000).lte(20000); - */ - - /** - * 分页查询 - * searchSourceBuilder.size(30); - * searchSourceBuilder.from(60); - */ - -} diff --git a/database/mysql/mysql1/pom.xml b/database/mysql/mysql1/pom.xml deleted file mode 100644 index 186c2480..00000000 --- a/database/mysql/mysql1/pom.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - mysql - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - cn.lastwhisper - mysql1 - mysql主从复制,读写分离,java实现多数据源 - - \ No newline at end of file diff --git a/database/mysql/mysql1/src/main/java/cn/lastwhisper/v1/db/DbContextHolder.java b/database/mysql/mysql1/src/main/java/cn/lastwhisper/v1/db/DbContextHolder.java deleted file mode 100644 index f1149802..00000000 --- a/database/mysql/mysql1/src/main/java/cn/lastwhisper/v1/db/DbContextHolder.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.lastwhisper.v1.db; - -/** - * @author lastwhisper - */ -public class DbContextHolder { - - public static final String MASTER = "master"; - public static final String SLAVE = "slave"; - - private static ThreadLocal datasource = new ThreadLocal<>(); - - public static void set(String name) { - datasource.set(name); - } - - public static String get() { - return datasource.get(); - } - -} diff --git a/database/mysql/mysql1/src/main/java/cn/lastwhisper/v1/db/DynamicDataSource.java b/database/mysql/mysql1/src/main/java/cn/lastwhisper/v1/db/DynamicDataSource.java deleted file mode 100644 index f7dd831d..00000000 --- a/database/mysql/mysql1/src/main/java/cn/lastwhisper/v1/db/DynamicDataSource.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.v1.db; - -import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; - -/** - * @author lastwhisper - */ -public class DynamicDataSource extends AbstractRoutingDataSource { - - @Override - protected Object determineCurrentLookupKey() { - - return DbContextHolder.get(); - } - -} diff --git a/database/mysql/mysql1/src/main/java/cn/lastwhisper/v1/mapper/AppMapper.java b/database/mysql/mysql1/src/main/java/cn/lastwhisper/v1/mapper/AppMapper.java deleted file mode 100644 index 62404507..00000000 --- a/database/mysql/mysql1/src/main/java/cn/lastwhisper/v1/mapper/AppMapper.java +++ /dev/null @@ -1,10 +0,0 @@ -package cn.lastwhisper.v1.mapper; - -import org.apache.ibatis.annotations.Param; - -import java.util.List; -import java.util.Map; - -public interface AppMapper { - List> executeQuery(@Param("sql") String sql); -} diff --git a/database/mysql/mysql1/src/main/java/cn/lastwhisper/v1/mapper/AppMapper.xml b/database/mysql/mysql1/src/main/java/cn/lastwhisper/v1/mapper/AppMapper.xml deleted file mode 100644 index 2ddeb064..00000000 --- a/database/mysql/mysql1/src/main/java/cn/lastwhisper/v1/mapper/AppMapper.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/database/mysql/mysql1/src/main/java/cn/lastwhisper/v1/test/Main.java b/database/mysql/mysql1/src/main/java/cn/lastwhisper/v1/test/Main.java deleted file mode 100644 index 49340d67..00000000 --- a/database/mysql/mysql1/src/main/java/cn/lastwhisper/v1/test/Main.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.lastwhisper.v1.test; - -import cn.lastwhisper.v1.db.DbContextHolder; -import cn.lastwhisper.v1.mapper.AppMapper; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * @author lastwhisper - */ -public class Main { - - public static void main(String[] args){ - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - AppMapper mapper = context.getBean(AppMapper.class); - //DbContextHolder.set(DbContextHolder.MASTER); - DbContextHolder.set(DbContextHolder.SLAVE); - System.out.println(mapper.executeQuery("select * from user")); - context.close(); - } - -} diff --git a/database/mysql/mysql1/src/main/resources/applicationContext.xml b/database/mysql/mysql1/src/main/resources/applicationContext.xml deleted file mode 100644 index 27ccb43a..00000000 --- a/database/mysql/mysql1/src/main/resources/applicationContext.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/database/mysql/mysql1/src/main/resources/db.properties b/database/mysql/mysql1/src/main/resources/db.properties deleted file mode 100644 index fbe66283..00000000 --- a/database/mysql/mysql1/src/main/resources/db.properties +++ /dev/null @@ -1,8 +0,0 @@ -master.jdbc.driver=com.mysql.jdbc.Driver -master.jdbc.url=jdbc:mysql://192.168.108.66:3306/mytest -master.jdbc.username=root -master.jdbc.password=root -slave.jdbc.driver=com.mysql.jdbc.Driver -slave.jdbc.url=jdbc:mysql://192.168.108.67:3306/mytest -slave.jdbc.username=root -slave.jdbc.password=root \ No newline at end of file diff --git a/database/mysql/mysql1/src/main/resources/log4j.properties b/database/mysql/mysql1/src/main/resources/log4j.properties deleted file mode 100644 index ef7157ce..00000000 --- a/database/mysql/mysql1/src/main/resources/log4j.properties +++ /dev/null @@ -1,11 +0,0 @@ -# Global logging configuration\uff0c\u5efa\u8bae\u5f00\u53d1\u73af\u5883\u4e2d\u8981\u7528debug -log4j.rootLogger=DEBUG, stdout -# Console output... -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n -[java] view plain copy -log4j.rootLogger = ${log.level},Console,default,allfile -log4j.logger.com.ibatis=debug -log4j.logger.java.sql=debug -log4j.logger.com.sf.egmas.dcn.web.mapper=debug \ No newline at end of file diff --git a/database/mysql/mysql1/src/main/resources/sqlMapConfig.xml b/database/mysql/mysql1/src/main/resources/sqlMapConfig.xml deleted file mode 100644 index 40055365..00000000 --- a/database/mysql/mysql1/src/main/resources/sqlMapConfig.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - diff --git a/database/mysql/mysql2/pom.xml b/database/mysql/mysql2/pom.xml deleted file mode 100644 index 0947f570..00000000 --- a/database/mysql/mysql2/pom.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - mysql - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - cn.lastwhisper - mysql2 - mysql主从复制,读写分离,SpringAop实现多数据源 - - \ No newline at end of file diff --git a/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/annotation/DataSource.java b/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/annotation/DataSource.java deleted file mode 100644 index 8da48f14..00000000 --- a/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/annotation/DataSource.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.lastwhisper.v2.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD,ElementType.FIELD}) -public @interface DataSource { - String value(); -} diff --git a/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/aop/DataSourceAspect.java b/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/aop/DataSourceAspect.java deleted file mode 100644 index 9263bb77..00000000 --- a/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/aop/DataSourceAspect.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.lastwhisper.v2.aop; - -import cn.lastwhisper.v2.annotation.DataSource; -import cn.lastwhisper.v2.db.DbContextHolder; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.reflect.MethodSignature; - -import java.lang.reflect.Method; - -/** - * @author lastwhisper - */ -public class DataSourceAspect { - - public void before(JoinPoint point) { - MethodSignature signature = (MethodSignature) point.getSignature(); - Method method = signature.getMethod(); - - DataSource dataSource = method.getAnnotation(DataSource.class); - - String source = dataSource.value(); - System.out.println(source); - // 设置数据源 - DbContextHolder.set(source); - } - - public void after() { - DbContextHolder.clear(); - } - -} diff --git a/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/db/DbContextHolder.java b/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/db/DbContextHolder.java deleted file mode 100644 index 22f218bb..00000000 --- a/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/db/DbContextHolder.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.lastwhisper.v2.db; - -/** - * @author lastwhisper - */ -public class DbContextHolder { - - public static final String MASTER = "master"; - public static final String SLAVE = "slave"; - - private static ThreadLocal datasource = new ThreadLocal<>(); - - public static void set(String name) { - datasource.set(name); - } - - public static String get() { - String source = datasource.get() == null ? DbContextHolder.MASTER : datasource.get(); - return source; - } - - // 清空数据类型 - public static void clear() { - datasource.remove(); - } -} diff --git a/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/db/DynamicDataSource.java b/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/db/DynamicDataSource.java deleted file mode 100644 index 710ce078..00000000 --- a/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/db/DynamicDataSource.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.v2.db; - -import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; - -/** - * @author lastwhisper - */ -public class DynamicDataSource extends AbstractRoutingDataSource { - - @Override - protected Object determineCurrentLookupKey() { - String source = DbContextHolder.get(); - return source; - } - -} diff --git a/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/mapper/AppMapper.java b/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/mapper/AppMapper.java deleted file mode 100644 index 3f9ffc16..00000000 --- a/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/mapper/AppMapper.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.lastwhisper.v2.mapper; - -import cn.lastwhisper.v2.annotation.DataSource; -import cn.lastwhisper.v2.db.DbContextHolder; -import org.apache.ibatis.annotations.Param; - -import java.util.List; -import java.util.Map; - -public interface AppMapper { - - @DataSource(value = DbContextHolder.MASTER) - List> executeQuery(@Param("sql") String sql); - - @DataSource(value = DbContextHolder.SLAVE) - List> executeQuery2(@Param("sql") String sql); -} diff --git a/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/mapper/AppMapper.xml b/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/mapper/AppMapper.xml deleted file mode 100644 index daa963fe..00000000 --- a/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/mapper/AppMapper.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/test/Main.java b/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/test/Main.java deleted file mode 100644 index 25d331ea..00000000 --- a/database/mysql/mysql2/src/main/java/cn/lastwhisper/v2/test/Main.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.lastwhisper.v2.test; - -import cn.lastwhisper.v2.db.DbContextHolder; -import cn.lastwhisper.v2.mapper.AppMapper; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * @author lastwhisper - */ -public class Main { - - public static void main(String[] args){ - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - AppMapper mapper = context.getBean(AppMapper.class); - //DbContextHolder.set(DbContextHolder.MASTER); - System.out.println(mapper.executeQuery("select * from user")); - //DbContextHolder.set(DbContextHolder.SLAVE); - System.out.println(mapper.executeQuery2("select * from user")); - context.close(); - } - -} diff --git a/database/mysql/mysql2/src/main/resources/applicationContext.xml b/database/mysql/mysql2/src/main/resources/applicationContext.xml deleted file mode 100644 index 8a49b1de..00000000 --- a/database/mysql/mysql2/src/main/resources/applicationContext.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/database/mysql/mysql2/src/main/resources/db.properties b/database/mysql/mysql2/src/main/resources/db.properties deleted file mode 100644 index fbe66283..00000000 --- a/database/mysql/mysql2/src/main/resources/db.properties +++ /dev/null @@ -1,8 +0,0 @@ -master.jdbc.driver=com.mysql.jdbc.Driver -master.jdbc.url=jdbc:mysql://192.168.108.66:3306/mytest -master.jdbc.username=root -master.jdbc.password=root -slave.jdbc.driver=com.mysql.jdbc.Driver -slave.jdbc.url=jdbc:mysql://192.168.108.67:3306/mytest -slave.jdbc.username=root -slave.jdbc.password=root \ No newline at end of file diff --git a/database/mysql/mysql2/src/main/resources/log4j.properties b/database/mysql/mysql2/src/main/resources/log4j.properties deleted file mode 100644 index 70cce320..00000000 --- a/database/mysql/mysql2/src/main/resources/log4j.properties +++ /dev/null @@ -1,11 +0,0 @@ -# Global logging configuration\uff0c\u5efa\u8bae\u5f00\u53d1\u73af\u5883\u4e2d\u8981\u7528debug -log4j.rootLogger=DEBUG, stdout -# Console output... -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n -[java] view plain copy -log4j.rootLogger = ${log.level},Console,default,allfile -log4j.logger.com.ibatis=debug -log4j.logger.java.sql=debug -log4j.logger.cn.lastwhisper.v2.mapper=debug \ No newline at end of file diff --git a/database/mysql/mysql2/src/main/resources/sqlMapConfig.xml b/database/mysql/mysql2/src/main/resources/sqlMapConfig.xml deleted file mode 100644 index 1ad521f4..00000000 --- a/database/mysql/mysql2/src/main/resources/sqlMapConfig.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/database/mysql/mysql3/pom.xml b/database/mysql/mysql3/pom.xml deleted file mode 100644 index 9a9898b9..00000000 --- a/database/mysql/mysql3/pom.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - mysql - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - cn.lastwhisper - mysql3 - mysql逻辑分表,水平分表 - - \ No newline at end of file diff --git a/database/mysql/mysql3/src/main/java/cn/lastwhisper/v3/domain/Archievement.java b/database/mysql/mysql3/src/main/java/cn/lastwhisper/v3/domain/Archievement.java deleted file mode 100644 index ca6c865a..00000000 --- a/database/mysql/mysql3/src/main/java/cn/lastwhisper/v3/domain/Archievement.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.lastwhisper.v3.domain; - -/** - * @author lastwhisper - */ -public class Archievement { - private Integer id; - private String name; - - public Integer getId() { - return id; - } - - public void setId(Integer id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} diff --git a/database/mysql/mysql3/src/main/java/cn/lastwhisper/v3/mapper/AppMapper.java b/database/mysql/mysql3/src/main/java/cn/lastwhisper/v3/mapper/AppMapper.java deleted file mode 100644 index f0bbffe7..00000000 --- a/database/mysql/mysql3/src/main/java/cn/lastwhisper/v3/mapper/AppMapper.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.lastwhisper.v3.mapper; - -import org.apache.ibatis.annotations.Param; - -import java.util.List; -import java.util.Map; - -public interface AppMapper { - List> executeQuery(@Param("sql") String sql); - - List> executeQuery2(@Param("sql") String sql); -} diff --git a/database/mysql/mysql3/src/main/java/cn/lastwhisper/v3/mapper/AppMapper.xml b/database/mysql/mysql3/src/main/java/cn/lastwhisper/v3/mapper/AppMapper.xml deleted file mode 100644 index 9d44a2df..00000000 --- a/database/mysql/mysql3/src/main/java/cn/lastwhisper/v3/mapper/AppMapper.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/database/mysql/mysql3/src/main/java/cn/lastwhisper/v3/test/Main.java b/database/mysql/mysql3/src/main/java/cn/lastwhisper/v3/test/Main.java deleted file mode 100644 index 380471e7..00000000 --- a/database/mysql/mysql3/src/main/java/cn/lastwhisper/v3/test/Main.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.lastwhisper.v3.test; - -import cn.lastwhisper.v3.mapper.AppMapper; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.util.Calendar; - -/** - * 水平分表 - * @author lastwhisper - */ -public class Main { - - public static void main(String[] args) { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); - AppMapper mapper = context.getBean(AppMapper.class); - - String currYear = "2016"; - //String sql = "insert into t_archievement_" + currYear + "(name) values('second')"; - String sql = "select * from t_archievement_" + currYear; - System.out.println(mapper.executeQuery(sql));; - - context.close(); - } - -} diff --git a/database/mysql/mysql3/src/main/resources/applicationContext.xml b/database/mysql/mysql3/src/main/resources/applicationContext.xml deleted file mode 100644 index c5aaa79d..00000000 --- a/database/mysql/mysql3/src/main/resources/applicationContext.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/database/mysql/mysql3/src/main/resources/db.properties b/database/mysql/mysql3/src/main/resources/db.properties deleted file mode 100644 index b5f8c2fc..00000000 --- a/database/mysql/mysql3/src/main/resources/db.properties +++ /dev/null @@ -1,4 +0,0 @@ -jdbc.driver=com.mysql.jdbc.Driver -jdbc.url=jdbc:mysql://192.168.108.100:3306/mytest -jdbc.username=root -jdbc.password=root \ No newline at end of file diff --git a/database/mysql/mysql3/src/main/resources/log4j.properties b/database/mysql/mysql3/src/main/resources/log4j.properties deleted file mode 100644 index ef7157ce..00000000 --- a/database/mysql/mysql3/src/main/resources/log4j.properties +++ /dev/null @@ -1,11 +0,0 @@ -# Global logging configuration\uff0c\u5efa\u8bae\u5f00\u53d1\u73af\u5883\u4e2d\u8981\u7528debug -log4j.rootLogger=DEBUG, stdout -# Console output... -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n -[java] view plain copy -log4j.rootLogger = ${log.level},Console,default,allfile -log4j.logger.com.ibatis=debug -log4j.logger.java.sql=debug -log4j.logger.com.sf.egmas.dcn.web.mapper=debug \ No newline at end of file diff --git a/database/mysql/mysql3/src/main/resources/sqlMapConfig.xml b/database/mysql/mysql3/src/main/resources/sqlMapConfig.xml deleted file mode 100644 index 8418d1a2..00000000 --- a/database/mysql/mysql3/src/main/resources/sqlMapConfig.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - diff --git a/database/mysql/pom.xml b/database/mysql/pom.xml deleted file mode 100644 index 9cb40bd9..00000000 --- a/database/mysql/pom.xml +++ /dev/null @@ -1,152 +0,0 @@ - - - 4.0.0 - - cn.lastwhisper - mysql - pom - 1.0-SNAPSHOT - - mysql2 - mysql1 - - - - 4.2.5.RELEASE - 1.0.23 - 4.12 - 3.2.8 - - - - - - org.springframework - spring-core - ${spring.version} - - - org.springframework - spring-aop - ${spring.version} - - - org.springframework - spring-web - ${spring.version} - - - org.springframework - spring-webmvc - ${spring.version} - - - org.springframework - spring-jdbc - ${spring.version} - - - org.springframework - spring-tx - ${spring.version} - - - - - org.aspectj - aspectjrt - 1.8.0 - - - org.aspectj - aspectjweaver - 1.8.0 - - - - - - org.mybatis - mybatis - ${mybatis.version} - - - - mysql - mysql-connector-java - 5.1.26 - - - - com.alibaba - druid - ${druid.version} - - - - - org.mybatis - mybatis-spring - 1.2.3 - - - - - junit - junit - ${junit.version} - - - - - - - src/main/java - - **/*.properties - **/*.xml - - false - - - src/main/resources - - **/*.properties - **/*.xml - - false - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.8 - 1.8 - UTF-8 - - - - org.apache.maven.plugins - maven-war-plugin - 2.6 - - false - - - - - org.apache.maven.plugins - maven-surefire-plugin - - true - - - - - - \ No newline at end of file diff --git a/database/redis/pom.xml b/database/redis/pom.xml deleted file mode 100644 index deb4a90f..00000000 --- a/database/redis/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - 4.0.0 - - cn.lastwhisper - redis - 1.0-SNAPSHOT - - - - - com.redislabs - jrebloom - 1.0.1 - - - - com.alibaba - fastjson - 1.2.56 - - - - com.google.guava - guava - 27.0.1-jre - - - - - redis.clients - jedis - 2.9.0 - - - - junit - junit - 4.12 - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.7.0 - - 1.8 - 1.8 - - - - - \ No newline at end of file diff --git a/database/redis/reademe b/database/redis/reademe deleted file mode 100644 index 63308e8f..00000000 --- a/database/redis/reademe +++ /dev/null @@ -1,18 +0,0 @@ -redis学习时的代码笔记 -asynqueue 异步队列 -basic 基础数据结构操作 -cluster Java集群操作 -dlock redis分布式锁 -hyperloglog 统计 -bloomfilter 布隆过滤器 -partition hash节点迁移率 -pipeline 流水线指令 -publishersubscriber 发布订阅 -sentinel 哨兵 -transaction 事务 - - - - - - diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/basic/BasicOperation.java b/database/redis/src/main/java/cn/lastwhisper/redis/basic/BasicOperation.java deleted file mode 100644 index 81dac8bc..00000000 --- a/database/redis/src/main/java/cn/lastwhisper/redis/basic/BasicOperation.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.lastwhisper.redis.basic; - -/** - * Redis基础数据结构的操作 - * @author lastwhisper - * @date 2019/11/23 - */ -public class BasicOperation { - - - -} diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/dlock/LockTest.java b/database/redis/src/main/java/cn/lastwhisper/redis/dlock/LockTest.java deleted file mode 100644 index adcde4d8..00000000 --- a/database/redis/src/main/java/cn/lastwhisper/redis/dlock/LockTest.java +++ /dev/null @@ -1,76 +0,0 @@ -package cn.lastwhisper.redis.dlock; - -import redis.clients.jedis.Jedis; - -/** - * 分布式锁上锁正确实例与错误实例 - * https://wudashan.cn/2017/10/23/Redis-Distributed-Lock-Implement/ - * @author lastwhisper - */ -public class LockTest { - - private static final String LOCK_SUCCESS = "OK"; - private static final String SET_IF_NOT_EXIST = "NX"; - private static final String SET_WITH_EXPIRE_TIME = "PX"; - - /** - * 尝试获取分布式锁 - * @param jedis Redis客户端 - * @param lockKey 锁 - * @param requestId 请求标识 - * @param expireTime 超期时间 - * @return 是否获取成功 - */ - public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) { - String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); - if (LOCK_SUCCESS.equals(result)) { - return true; - } - return false; - - } - - /** - * 尝试获取分布式锁 - * @param jedis Redis客户端 - * @param lockKey 锁 - * @param requestId 请求标识 - * @param expireTime 超期时间 - */ - public static void wrongGetLock1(Jedis jedis, String lockKey, String requestId, int expireTime) { - - Long result = jedis.setnx(lockKey, requestId); - if (result == 1) { - // 若在这里程序突然崩溃,则无法设置过期时间,将发生死锁 - jedis.expire(lockKey, expireTime); - } - - } - - - public static boolean wrongGetLock2(Jedis jedis, String lockKey, int expireTime) { - - long expires = System.currentTimeMillis() + expireTime; - String expiresStr = String.valueOf(expires); - - // 如果当前锁不存在,返回加锁成功 - if (jedis.setnx(lockKey, expiresStr) == 1) { - return true; - } - - // 如果锁存在,获取锁的过期时间 - String currentValueStr = jedis.get(lockKey); - if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) { - // 锁已过期,获取上一个锁的过期时间,并设置现在锁的过期时间 - String oldValueStr = jedis.getSet(lockKey, expiresStr); - if (oldValueStr != null && oldValueStr.equals(currentValueStr)) { - // 考虑多线程并发的情况,只有一个线程的设置值和当前值相同,它才有权利加锁 - return true; - } - } - - // 其他情况,一律返回加锁失败 - return false; - - } -} diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/dlock/UnLockTest.java b/database/redis/src/main/java/cn/lastwhisper/redis/dlock/UnLockTest.java deleted file mode 100644 index 3bb5e1b3..00000000 --- a/database/redis/src/main/java/cn/lastwhisper/redis/dlock/UnLockTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.lastwhisper.redis.dlock; - -import redis.clients.jedis.Jedis; - -import java.util.Collections; - -/** - * 分布式锁解锁正确实例与错误实例 - * @author lastwhisper - */ -public class UnLockTest { - private static final Long RELEASE_SUCCESS = 1L; - - /** - * lua脚本释放分布式锁 - * @param jedis Redis客户端 - * @param lockKey 锁 - * @param requestId 请求标识 - * @return 是否释放成功 - */ - public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) { - // 首先获取锁对应的value值,检查是否与requestId相等,如果相等则删除锁(解锁) - String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; - Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); - - if (RELEASE_SUCCESS.equals(result)) { - return true; - } - return false; - - } - - /** - * 直接使用jedis.del()方法删除锁,这种不先判断锁的拥有者而直接解锁的方式, - * 会导致任何客户端都可以随时进行解锁,即使这把锁不是它的。 - */ - public static void wrongReleaseLock1(Jedis jedis, String lockKey) { - jedis.del(lockKey); - } - - /** - * 无法保证原子性 - */ - public static void wrongReleaseLock2(Jedis jedis, String lockKey, String requestId) { - // 判断加锁与解锁是不是同一个客户端 - if (requestId.equals(jedis.get(lockKey))) { - // 若在此时,这把锁突然不是这个客户端的,则会误解锁 - jedis.del(lockKey); - } - - } - -} - diff --git a/distributed/gateway/README.md b/distributed/gateway/README.md new file mode 100644 index 00000000..1c55bcb3 --- /dev/null +++ b/distributed/gateway/README.md @@ -0,0 +1,14 @@ +gateway单独使用 +https://blog.csdn.net/jiongyan6966/article/details/84633632 + +service-product 8081 +http://localhost:8081/method + +service-order-load1 8082 +service-order-load2 8083 +http://localhost:8082/method +http://localhost:8083/method + +zuul-gateway 9000 +http://localhost:9000/shop-api/product/method +http://localhost:9000/shop-api/order/method \ No newline at end of file diff --git a/distributed/gateway/service-order-load1/pom.xml b/distributed/gateway/service-order-load1/pom.xml new file mode 100644 index 00000000..15367fc2 --- /dev/null +++ b/distributed/gateway/service-order-load1/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.2.6.RELEASE + + + cn.lastwhisper + service-order-load1 + 0.0.1-SNAPSHOT + service-a + Demo project for Spring Boot + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/distributed/gateway/service-order-load1/src/main/java/cn/lastwhisper/service/ServiceB1Application.java b/distributed/gateway/service-order-load1/src/main/java/cn/lastwhisper/service/ServiceB1Application.java new file mode 100644 index 00000000..f896ce24 --- /dev/null +++ b/distributed/gateway/service-order-load1/src/main/java/cn/lastwhisper/service/ServiceB1Application.java @@ -0,0 +1,25 @@ +package cn.lastwhisper.service; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +@RestController +@SpringBootApplication +public class ServiceB1Application { + + public static void main(String[] args) { + SpringApplication.run(ServiceB1Application.class, args); + } + + @RequestMapping("/method") + public Map methodA(){ + HashMap hashMap = new HashMap<>(); + hashMap.put("service","order 1"); + return hashMap; + } +} diff --git a/distributed/gateway/service-order-load1/src/main/resources/application.yml b/distributed/gateway/service-order-load1/src/main/resources/application.yml new file mode 100644 index 00000000..08841319 --- /dev/null +++ b/distributed/gateway/service-order-load1/src/main/resources/application.yml @@ -0,0 +1,2 @@ +server: + port: 8082 \ No newline at end of file diff --git a/distributed/gateway/service-order-load1/src/test/java/cn/lastwhisper/servicea/ServiceAApplicationTests.java b/distributed/gateway/service-order-load1/src/test/java/cn/lastwhisper/servicea/ServiceAApplicationTests.java new file mode 100644 index 00000000..e1c1731c --- /dev/null +++ b/distributed/gateway/service-order-load1/src/test/java/cn/lastwhisper/servicea/ServiceAApplicationTests.java @@ -0,0 +1,13 @@ +package cn.lastwhisper.service; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ServiceAApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/distributed/gateway/service-order-load2/pom.xml b/distributed/gateway/service-order-load2/pom.xml new file mode 100644 index 00000000..8a53509f --- /dev/null +++ b/distributed/gateway/service-order-load2/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.2.6.RELEASE + + + cn.lastwhisper + service-order-load2 + 0.0.1-SNAPSHOT + service-a + Demo project for Spring Boot + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/distributed/gateway/service-order-load2/src/main/java/cn/lastwhisper/service/ServiceB2Application.java b/distributed/gateway/service-order-load2/src/main/java/cn/lastwhisper/service/ServiceB2Application.java new file mode 100644 index 00000000..62c2618f --- /dev/null +++ b/distributed/gateway/service-order-load2/src/main/java/cn/lastwhisper/service/ServiceB2Application.java @@ -0,0 +1,25 @@ +package cn.lastwhisper.service; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +@RestController +@SpringBootApplication +public class ServiceB2Application { + + public static void main(String[] args) { + SpringApplication.run(ServiceB2Application.class, args); + } + + @RequestMapping("/method") + public Map methodA(){ + HashMap hashMap = new HashMap<>(); + hashMap.put("service","order 2"); + return hashMap; + } +} diff --git a/distributed/gateway/service-order-load2/src/main/resources/application.yml b/distributed/gateway/service-order-load2/src/main/resources/application.yml new file mode 100644 index 00000000..9899989d --- /dev/null +++ b/distributed/gateway/service-order-load2/src/main/resources/application.yml @@ -0,0 +1,2 @@ +server: + port: 8083 \ No newline at end of file diff --git a/distributed/gateway/service-order-load2/src/test/java/cn/lastwhisper/servicea/ServiceAApplicationTests.java b/distributed/gateway/service-order-load2/src/test/java/cn/lastwhisper/servicea/ServiceAApplicationTests.java new file mode 100644 index 00000000..e1c1731c --- /dev/null +++ b/distributed/gateway/service-order-load2/src/test/java/cn/lastwhisper/servicea/ServiceAApplicationTests.java @@ -0,0 +1,13 @@ +package cn.lastwhisper.service; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ServiceAApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/distributed/gateway/service-product/pom.xml b/distributed/gateway/service-product/pom.xml new file mode 100644 index 00000000..f1d0b245 --- /dev/null +++ b/distributed/gateway/service-product/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.2.6.RELEASE + + + cn.lastwhisper + service-product + 0.0.1-SNAPSHOT + service-a + Demo project for Spring Boot + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/distributed/gateway/service-product/src/main/java/cn/lastwhisper/service/ServiceAApplication.java b/distributed/gateway/service-product/src/main/java/cn/lastwhisper/service/ServiceAApplication.java new file mode 100644 index 00000000..9af2565f --- /dev/null +++ b/distributed/gateway/service-product/src/main/java/cn/lastwhisper/service/ServiceAApplication.java @@ -0,0 +1,26 @@ +package cn.lastwhisper.service; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +@RestController +@SpringBootApplication +public class ServiceAApplication { + + public static void main(String[] args) { + SpringApplication.run(ServiceAApplication.class, args); + } + + @RequestMapping("/method") + public Map methodA(){ + HashMap hashMap = new HashMap<>(); + hashMap.put("service","product"); + return hashMap; + } + +} diff --git a/distributed/gateway/service-product/src/main/resources/application.yml b/distributed/gateway/service-product/src/main/resources/application.yml new file mode 100644 index 00000000..54b155ff --- /dev/null +++ b/distributed/gateway/service-product/src/main/resources/application.yml @@ -0,0 +1,2 @@ +server: + port: 8081 \ No newline at end of file diff --git a/distributed/gateway/service-product/src/test/java/cn/lastwhisper/service/ServiceAApplicationTests.java b/distributed/gateway/service-product/src/test/java/cn/lastwhisper/service/ServiceAApplicationTests.java new file mode 100644 index 00000000..e1c1731c --- /dev/null +++ b/distributed/gateway/service-product/src/test/java/cn/lastwhisper/service/ServiceAApplicationTests.java @@ -0,0 +1,13 @@ +package cn.lastwhisper.service; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ServiceAApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/distributed/gateway/zuul-gateway/pom.xml b/distributed/gateway/zuul-gateway/pom.xml new file mode 100644 index 00000000..900c1c21 --- /dev/null +++ b/distributed/gateway/zuul-gateway/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.2.6.RELEASE + + + cn.lastwhisper + zuul-gateway + 0.0.1-SNAPSHOT + zuul-gateway + gateway + + + 1.8 + Hoxton.SR3 + + + + + org.springframework.cloud + spring-cloud-starter-netflix-zuul + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/distributed/gateway/zuul-gateway/src/main/java/cn/lastwhisper/zuul/ZuulGatewayApplication.java b/distributed/gateway/zuul-gateway/src/main/java/cn/lastwhisper/zuul/ZuulGatewayApplication.java new file mode 100644 index 00000000..7998f028 --- /dev/null +++ b/distributed/gateway/zuul-gateway/src/main/java/cn/lastwhisper/zuul/ZuulGatewayApplication.java @@ -0,0 +1,15 @@ +package cn.lastwhisper.zuul; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.zuul.EnableZuulProxy; + +@EnableZuulProxy +@SpringBootApplication +public class ZuulGatewayApplication { + + public static void main(String[] args) { + SpringApplication.run(ZuulGatewayApplication.class, args); + } + +} diff --git a/distributed/gateway/zuul-gateway/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/distributed/gateway/zuul-gateway/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 00000000..31cf7253 --- /dev/null +++ b/distributed/gateway/zuul-gateway/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,8 @@ +{ + "properties": [ + { + "name": "api-2.ribbon.listOfServers", + "type": "java.lang.String", + "description": "Description for api-2.ribbon.listOfServers." + } +] } \ No newline at end of file diff --git a/distributed/gateway/zuul-gateway/src/main/resources/application.yml b/distributed/gateway/zuul-gateway/src/main/resources/application.yml new file mode 100644 index 00000000..ccb268ee --- /dev/null +++ b/distributed/gateway/zuul-gateway/src/main/resources/application.yml @@ -0,0 +1,16 @@ +server: + port: 9000 +zuul: + routes: + product: + path: /shop-api/product/** + url: http://localhost:8081/ + order: + path: /shop-api/order/** +# url: http://localhost:8083/ +order: + ribbon: + listOfServers: http://localhost:8082,http://localhost:8083 +ribbon: + eureka: + enabled: false diff --git a/distributed/gateway/zuul-gateway/src/test/java/cn/lastwhisper/zuul/ZuulGatewayApplicationTests.java b/distributed/gateway/zuul-gateway/src/test/java/cn/lastwhisper/zuul/ZuulGatewayApplicationTests.java new file mode 100644 index 00000000..511fa9a9 --- /dev/null +++ b/distributed/gateway/zuul-gateway/src/test/java/cn/lastwhisper/zuul/ZuulGatewayApplicationTests.java @@ -0,0 +1,13 @@ +package cn.lastwhisper.zuul; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ZuulGatewayApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/springboot-aop/principle/src/main/resources/application.properties b/distributed/gray/README.md similarity index 100% rename from springboot-aop/principle/src/main/resources/application.properties rename to distributed/gray/README.md diff --git a/distributed/gray/pom.xml b/distributed/gray/pom.xml new file mode 100644 index 00000000..f25dbc3e --- /dev/null +++ b/distributed/gray/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + cn.cunchang + gray + 1.0-SNAPSHOT + + + 8 + 8 + + + + + org.springframework.boot + spring-boot-starter-web + 2.2.4.RELEASE + + + + org.redisson + redisson-spring-boot-starter + 3.12.3 + + + + org.projectlombok + lombok + 1.18.22 + + + + com.alibaba + fastjson + 1.2.80 + + + + com.google.guava + guava + 30.1.1-jre + + + + org.apache.commons + commons-lang3 + 3.10 + + + + org.apache.commons + commons-collections4 + 4.2 + + + \ No newline at end of file diff --git a/distributed/gray/src/main/java/cn/cunchang/Application.java b/distributed/gray/src/main/java/cn/cunchang/Application.java new file mode 100644 index 00000000..69748ef6 --- /dev/null +++ b/distributed/gray/src/main/java/cn/cunchang/Application.java @@ -0,0 +1,14 @@ +package cn.cunchang; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; + +@SpringBootApplication() +@EnableConfigurationProperties +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/distributed/gray/src/main/java/cn/cunchang/v1/Constant.java b/distributed/gray/src/main/java/cn/cunchang/v1/Constant.java new file mode 100644 index 00000000..375343dd --- /dev/null +++ b/distributed/gray/src/main/java/cn/cunchang/v1/Constant.java @@ -0,0 +1,30 @@ +package cn.cunchang.v1; + +/** + * + */ +public interface Constant { + + + /** + * 灰度 + */ + String GRAY = "gray"; + + + /** + * 正常 + */ + String NORMAL = "normal"; + + /** + * 灰度数量 + */ + String GRAY_NUMBER = "grayNumber"; + + + /** + * 正常请求数量 + */ + String NORMAL_NUMBER = "normalNumber"; +} diff --git a/distributed/gray/src/main/java/cn/cunchang/v1/GrayHelper.java b/distributed/gray/src/main/java/cn/cunchang/v1/GrayHelper.java new file mode 100644 index 00000000..b71ebf68 --- /dev/null +++ b/distributed/gray/src/main/java/cn/cunchang/v1/GrayHelper.java @@ -0,0 +1,155 @@ +package cn.cunchang.v1; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.CollectionUtils; + +import java.util.HashMap; +import java.util.Map; + +/** + * + */ +@Slf4j(topic = "gray") +public class GrayHelper { + + /** + * 灰度权重规则key + */ + public final static String GRAY_RULE_STR_KEY = "gray_rule_str_key"; + + /** + * 灰度权重map + */ + private static Map groupMap = new HashMap(); + + + private Map grayRuleCache; + + + /** + * 灰度是否开启 + */ + private static boolean grayOpen = false; + + + /** + * 灰度开启的情况下是否全部走灰度 + */ + private static boolean allRequestGray = false; + + + /** + * 加载灰度权重规则 + * 配置格式: + * {"requestConfig":[{"id":1,"grayNumber":100,"normarlNumber":9900},{"id":2,"grayNumber":1000,"normarlNumber":9000}],"allRequestGray":true,"grayOpen":true} + */ + public void loadRule(){ + + try { + String grayRule = grayRuleCache.get(GRAY_RULE_STR_KEY); + + if(StringUtils.isBlank(grayRule)){ + log.error("gray_rule_str is null"); + return; + } + JSONObject jsonObject = JSONObject.parseObject(grayRule); + //是否开启灰度 + boolean go = jsonObject.getBoolean("grayOpen"); + + grayOpen = go; + + //灰度开启后是否全部走灰度 + boolean arg = jsonObject.getBoolean("allRequestGray"); + + allRequestGray = arg; + + JSONArray jsonArray = jsonObject.getJSONArray("requestConfig"); + if(CollectionUtils.isEmpty(jsonArray)){ + log.warn("requestConfig is empty"); + return; + } + for (Object o : jsonArray) { + JSONObject j = (JSONObject)o; + Integer id = j.getInteger("id"); + WeightCategory grayWeightCategory = new WeightCategory(Constant.GRAY,j.getInteger("grayNumber")); + WeightCategory normalWeightCategory = new WeightCategory(Constant.NORMAL,j.getInteger("normarlNumber")); + InterfaceWeightGroup interfaceWeightGroup = new InterfaceWeightGroup(id,grayWeightCategory,normalWeightCategory); + groupMap.put(id,interfaceWeightGroup); + } + log.info("loadRule finish,groupMap:{}",JSONObject.toJSONString(groupMap)); + + + }catch (Exception e){ + log.error("load loadRule error",e); + } + + } + + /** + * 是否命中灰度 + * @param requestConfigId + * @return + */ + public boolean isGray(Integer requestConfigId){ + try { + if(!grayOpen){ + log.info("grayOpen is false"); + return false; + } + if(requestConfigId == null){ + return false; + } + + InterfaceWeightGroup interfaceWeightGroup = groupMap.get(requestConfigId); + //找不到配置,则返回false + if(interfaceWeightGroup == null){ + return false; + } + return interfaceWeightGroup.accessGray(); + }catch (Exception e){ + log.error("error to isGray",e); + return false; + } + + } + + public static void main(String[] args) { + + JSONArray jsonArray = new JSONArray(); + for (int i =0; i < 3 ;i ++) { + JSONObject requestConfig1 = new JSONObject(); + requestConfig1.put("id",i +1); + requestConfig1.put("grayNumber",100); + requestConfig1.put("normalNumber",9900); + jsonArray.add(requestConfig1); + } + + JSONObject jsonObject = new JSONObject(); + jsonObject.put("requestConfigList",jsonArray); + + System.out.println(jsonArray); + + + + //JSONArray jsonArray = JSONObject.parseArray(rBucket.get()); + if(CollectionUtils.isEmpty(jsonArray)){ + log.warn("requestConfig is empty"); + return; + } + for (Object o : jsonArray) { + JSONObject j = (JSONObject)o; + Integer id = j.getInteger("id"); + WeightCategory grayWeightCategory = new WeightCategory(Constant.GRAY,j.getInteger(Constant.GRAY_NUMBER)); + WeightCategory normalWeightCategory = new WeightCategory(Constant.NORMAL,j.getInteger(Constant.NORMAL_NUMBER)); + InterfaceWeightGroup interfaceWeightGroup = new InterfaceWeightGroup(id,grayWeightCategory,normalWeightCategory); + groupMap.put(id,interfaceWeightGroup); + } + log.info("loadRule finish,groupMap={}",JSONObject.toJSONString(groupMap)); + } + + + +} diff --git a/distributed/gray/src/main/java/cn/cunchang/v1/InterfaceWeightGroup.java b/distributed/gray/src/main/java/cn/cunchang/v1/InterfaceWeightGroup.java new file mode 100644 index 00000000..e8734362 --- /dev/null +++ b/distributed/gray/src/main/java/cn/cunchang/v1/InterfaceWeightGroup.java @@ -0,0 +1,153 @@ +package cn.cunchang.v1; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +/** + * + */ +@Slf4j(topic = "gray") +public class InterfaceWeightGroup { + + + /** + * 权重配置ID + */ + private Integer id; + + + /** + * 灰度权重对象 + */ + private WeightCategory grayWeightCategory = null; + + /** + * 正常请求权重对象 + */ + private WeightCategory normalWeightCategory = null; + + /** + * 灰度请求进来次数 + */ + private int grayRequestAccessNumber = 0; + + + /** + * 权重请求列表 + */ + private List categoryList=new ArrayList<>(); + + /** + * 初始化 + */ + private void init(){ + + categoryList.add(grayWeightCategory); + categoryList.add(normalWeightCategory); + + } + + + + public InterfaceWeightGroup(Integer id,WeightCategory grayWeightCategory,WeightCategory normalWeightCategory){ + this.id = id; + this.grayWeightCategory = grayWeightCategory; + this.normalWeightCategory = normalWeightCategory; + //添加权重到list + init(); + } + + /** + * 此次是否是灰度 + * @return + */ + public boolean accessGray(){ + + String categoryName = getWeight(categoryList); + + if(Constant.GRAY.equals(categoryName)){ + grayRequestAccessNumber ++; + log.info("id={},grayRequestAccessNumber={}",id,grayRequestAccessNumber); + return true; + } + + return false; + + } + + /** + * 权重获取方法 + * @param categorys + * @return + */ + public String getWeight(List categorys) { + + if(CollectionUtils.isEmpty(categorys)){ + return Constant.NORMAL; + } + + Integer weightSum = 0; + String result=null; + for (WeightCategory wc : categorys) { + weightSum += wc.getWeight(); + } + + if (weightSum <= 0) { + log.error("Error: weightSum=" + weightSum.toString()); + return result; + } + Random random = new Random(); + Integer n = random.nextInt(weightSum); // n in [0, weightSum) + Integer m = 0; + for (WeightCategory wc : categorys) { + if (m <= n && n < m + wc.getWeight()) { + result=wc.getCategory(); + break; + } + m += wc.getWeight(); + } + + return result; + } + + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public WeightCategory getGrayWeightCategory() { + return grayWeightCategory; + } + + public void setGrayWeightCategory(WeightCategory grayWeightCategory) { + this.grayWeightCategory = grayWeightCategory; + } + + public WeightCategory getNormalWeightCategory() { + return normalWeightCategory; + } + + public void setNormalWeightCategory(WeightCategory normalWeightCategory) { + this.normalWeightCategory = normalWeightCategory; + } + + public int getGrayRequestAccessNumber() { + return grayRequestAccessNumber; + } + + public void setGrayRequestAccessNumber(int grayRequestAccessNumber) { + this.grayRequestAccessNumber = grayRequestAccessNumber; + } + + + + +} diff --git a/distributed/gray/src/main/java/cn/cunchang/v1/WeightCategory.java b/distributed/gray/src/main/java/cn/cunchang/v1/WeightCategory.java new file mode 100644 index 00000000..bb0c0a4b --- /dev/null +++ b/distributed/gray/src/main/java/cn/cunchang/v1/WeightCategory.java @@ -0,0 +1,36 @@ +package cn.cunchang.v1; + +/** + * 权重分类 + * + */ +public class WeightCategory { + + //类别 + private String category; + //权重值 + private int weight; + + public WeightCategory(String category, int weight) { + this.category = category; + this.weight = weight; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public int getWeight() { + return weight; + } + + public void setWeight(int weight) { + this.weight = weight; + + } + +} diff --git a/distributed/gray/src/main/java/cn/cunchang/v1/WeightRandom.java b/distributed/gray/src/main/java/cn/cunchang/v1/WeightRandom.java new file mode 100644 index 00000000..02f1ba8c --- /dev/null +++ b/distributed/gray/src/main/java/cn/cunchang/v1/WeightRandom.java @@ -0,0 +1,103 @@ +package cn.cunchang.v1; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import javafx.util.Pair; +import lombok.extern.slf4j.Slf4j; + +import java.util.*; + +@Slf4j +public class WeightRandom { + + /** + * 以权重为key + */ + private TreeMap weightMap = new TreeMap<>(); + + public WeightRandom(List> list) { + Preconditions.checkNotNull(list, "list can NOT be null!"); + for (Pair pair : list) { + // 权重值需大于0 + Preconditions.checkArgument(pair.getValue().doubleValue() > 0, String.format("非法权重值:pair=%s", pair)); + + double lastWeight = this.weightMap.size() == 0 ? 0 : this.weightMap.lastKey(); + + //权重累加值作为map的key + this.weightMap.put(pair.getValue().doubleValue() + lastWeight, pair.getKey()); + } + } + + public K random() { + // 在权重累加值范围内生成随机值 + double randomWeight = this.weightMap.lastKey() * Math.random(); + // 取key权重值大于随机值的节点 + SortedMap tailMap = this.weightMap.tailMap(randomWeight, false); + // 再取第一个节点 + return this.weightMap.get(tailMap.firstKey()); + } + + public static void main(String[] args) { + + List> list; + + WeightRandom random; + + list = Lists.newArrayList(); + list.add(new Pair<>("Gray", 1)); + list.add(new Pair<>("Normal", 9)); + + random = new WeightRandom<>(list); + + Map countMap = Maps.newHashMap(); + for (int i = 0; i < 10000; i++) { + String randomKey = random.random(); + countMap.put(randomKey, countMap.getOrDefault(randomKey, 0) + 1); + } + + for (Pair pair : list) { + log.debug("{}:{}", pair.getKey(), countMap.get(pair.getKey())); + } + } + + +// public static void main(String[] args) { +// List> pairs = new ArrayList<>(); +// pairs.add(new Pair<>("a", 1D)); +// pairs.add(new Pair<>("b", 1D)); +// pairs.add(new Pair<>("c", 1D)); +// pairs.add(new Pair<>("d", 1D)); +// pairs.add(new Pair<>("e", 1D)); +// pairs.add(new Pair<>("f", 6D)); +// WeightRandom weightRandom = new WeightRandom<>(pairs); +// int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0; +// for (int i = 0; i < 110000; i++) { +// String key = weightRandom.random(); +// if ("a".equals(key)) { +// a++; +// } +// if ("b".equals(key)) { +// b++; +// } +// if ("c".equals(key)) { +// c++; +// } +// if ("d".equals(key)) { +// d++; +// } +// if ("e".equals(key)) { +// e++; +// } +// if ("f".equals(key)) { +// f++; +// } +// } +// System.out.println(a);// 9994 +// System.out.println(b);// 10035 +// System.out.println(c);// 10119 +// System.out.println(d);// 9950 +// System.out.println(e);// 10088 +// System.out.println(f);// 59814 +// } +} \ No newline at end of file diff --git a/distributed/gray/src/main/java/cn/cunchang/v1/WeightTest.java b/distributed/gray/src/main/java/cn/cunchang/v1/WeightTest.java new file mode 100644 index 00000000..716dea1d --- /dev/null +++ b/distributed/gray/src/main/java/cn/cunchang/v1/WeightTest.java @@ -0,0 +1,74 @@ +package cn.cunchang.v1; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +/** + * + */ +public class WeightTest { + + public static void main(String[] args) throws Exception{ + + //测试数据 + List categoryList=new ArrayList<>(); + WeightCategory weightCategory1=new WeightCategory("一等奖",100); + WeightCategory weightCategory2=new WeightCategory("二等奖",900); + categoryList.add(weightCategory1); + categoryList.add(weightCategory2); + + String result= ""; + int a1=0,a2=0; + for (int i=0;i<1000;i++){ + if(i%50 ==0){ + System.out.println("sleep "); + Thread.currentThread().sleep(5000L); + } + result = getWeight(categoryList); + System.out.println(i+" 开奖结果: "+result); + if(result.equals("一等奖")){ + a1++; + } + else if(result.equals("二等奖")){ + a2++; + } + } + + System.out.println("一等奖共出现 "+a1); + System.out.println("二等奖共出现 "+a2); + + + } + + /** + * 权重获取方法 + * @param categorys + * @return + */ + public static String getWeight(List categorys) { + Integer weightSum = 0; + String result=null; + for (WeightCategory wc : categorys) { + weightSum += wc.getWeight(); + } + + if (weightSum <= 0) { + System.err.println("Error: weightSum=" + weightSum.toString()); + return result; + } + Random random = new Random(); + Integer n = random.nextInt(weightSum); // n in [0, weightSum) + Integer m = 0; + for (WeightCategory wc : categorys) { + if (m <= n && n < m + wc.getWeight()) { + result=wc.getCategory(); + break; + } + m += wc.getWeight(); + } + return result; + } + + +} diff --git a/distributed/gray/src/main/java/cn/cunchang/v2/Constant.java b/distributed/gray/src/main/java/cn/cunchang/v2/Constant.java new file mode 100644 index 00000000..a325b9d2 --- /dev/null +++ b/distributed/gray/src/main/java/cn/cunchang/v2/Constant.java @@ -0,0 +1,31 @@ +package cn.cunchang.v2; + +/** + * Created by qiumu on 2020/10/10. + */ +public interface Constant { + + + /** + * 灰度 + */ + String GRAY = "gray"; + + + /** + * 正常 + */ + String NORMAL = "normal"; + + + /** + * 灰度数量 + */ + String GRAY_NUMBER = "grayNumber"; + + + /** + * 正常请求数量 + */ + String NORMAL_NUMBER = "normalNumber"; +} diff --git a/distributed/gray/src/main/java/cn/cunchang/v2/GrayHelper.java b/distributed/gray/src/main/java/cn/cunchang/v2/GrayHelper.java new file mode 100644 index 00000000..68ff11eb --- /dev/null +++ b/distributed/gray/src/main/java/cn/cunchang/v2/GrayHelper.java @@ -0,0 +1,310 @@ +package cn.cunchang.v2; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; +import org.redisson.api.RBucket; +import org.redisson.api.RedissonClient; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by qiumu on 2020/10/10. + */ +@Slf4j(topic = "grayLog") +@Service("grayHelper") +public class GrayHelper { + + /** + * 灰度权重规则key + */ + public final static String GRAY_RULE_STR_KEY = "gray_rule_str_key"; + + + /** + * 灰度开关key + */ + public final static String GRAY_OPEN_KEY = "gray_open"; + + + /** + * 灰度权重规则key + */ + public final static String ALL_REQUEST_GRAY_KEY = "all_request_gray"; + + + /** + * 灰度用户ID列表 + */ + public final static String GRAY_USER_ID_LIST = "grayUserIdList"; + + /** + * 请求配置列表 + */ + public final static String REQUEST_CONFIG_LIST = "requestConfigList"; + + /** + * 灰度权重map + */ + private static Map groupMap = new HashMap(); + + + /** + * 白名单用户ID列表 + */ + private static List userIdList = new ArrayList(); + + @Resource + private RedissonClient redissonClient; + + /** + * 设置灰度是否开启 + * @param grayOpen + */ + public void setGrayOpen(String grayOpen){ + + try { + RBucket rBucket = redissonClient.getBucket(GRAY_OPEN_KEY); + rBucket.set(Boolean.valueOf(grayOpen)); + }catch (Exception e){ + log.error("error to setGrayOpen",e); + } + } + + /** + * 设置灰度是否开启 + * @param allRequestGray + */ + public void setAllRequestGray(String allRequestGray){ + + try { + RBucket rBucket = redissonClient.getBucket(ALL_REQUEST_GRAY_KEY); + rBucket.set(Boolean.valueOf(allRequestGray)); + }catch (Exception e){ + log.error("error to setAllRequestGray",e); + } + } + + /** + * 获取是否开启灰度 + * @return + */ + public Boolean getGrayOpen(){ + + try { + RBucket rBucket = redissonClient.getBucket(GRAY_OPEN_KEY); + if(rBucket == null || rBucket.get()==null){ + return false; + } + return rBucket.get(); + }catch (Exception e){ + log.error("error to getGrayOpen",e); + } + return false; + } + + + /** + * 获取是否全部请求走灰度 + * @return + */ + public Boolean getAllRequestGray(){ + + try { + RBucket rBucket = redissonClient.getBucket(ALL_REQUEST_GRAY_KEY); + if(rBucket == null || rBucket.get()==null){ + return false; + } + return rBucket.get(); + }catch (Exception e){ + log.error("error to getAllRequestGray",e); + } + return false; + } + + + + + /** + * 加载灰度权重规则,grayUserIdList为白名单,白名单不为空,则优先走白名单策略,否则走接口权重策略。requestConfigList为接口灰度权重访问策略。 + * 配置格式: + * {"grayUserIdList":[12323,12323,2323,23244],"requestConfigList":[{"normalNumber":80,"id":1,"grayNumber":20},{"normalNumber":80,"id":2,"grayNumber":20},{"normalNumber":80,"id":3,"grayNumber":20}]} + */ + /** + * 启动后自动加载 + * @return + */ + @PostConstruct + public synchronized boolean loadRule(){ + + try { + RBucket rBucket = redissonClient.getBucket(GRAY_RULE_STR_KEY); + + if(rBucket == null || StringUtils.isBlank(rBucket.get())){ + log.error("gray_rule_str is null"); + return false; + } + //灰度策略json字符串 + String config = rBucket.get(); + log.info("config={}",config); + JSONObject jsonObject = JSONObject.parseObject(config); + + //设置白名单 + JSONArray grayUserArrayList = jsonObject.getJSONArray(GRAY_USER_ID_LIST); + + //先清空在重新添加 + userIdList.clear(); + //不为空则重新添加 + if(!CollectionUtils.isEmpty(grayUserArrayList)){ + + for (Object userId : grayUserArrayList){ + userIdList.add((Integer)userId); + } + } + + + //设置groupMap + JSONArray jsonArray = jsonObject.getJSONArray(REQUEST_CONFIG_LIST); + if(CollectionUtils.isEmpty(jsonArray)){ + log.warn("requestConfig is empty"); + return false; + } + for (Object o : jsonArray) { + JSONObject j = (JSONObject)o; + Integer id = j.getInteger("id"); + WeightCategory grayWeightCategory = new WeightCategory(Constant.GRAY,j.getInteger(Constant.GRAY_NUMBER)); + WeightCategory normalWeightCategory = new WeightCategory(Constant.NORMAL,j.getInteger(Constant.NORMAL_NUMBER)); + InterfaceWeightGroup interfaceWeightGroup = new InterfaceWeightGroup(id,grayWeightCategory,normalWeightCategory); + groupMap.put(id,interfaceWeightGroup); + } + log.info("loadRule finish,userIdList={}",JSONObject.toJSONString(userIdList)); + log.info("loadRule finish,groupMap={}",JSONObject.toJSONString(groupMap)); + + + }catch (Exception e){ + log.error("load loadRule error",e); + return false; + } + + return true; + } + + /** + * 是否命中灰度 + * @param requestConfigId + * @return + */ + public boolean isGray(Integer requestConfigId){ + try { + //如果灰度关闭则返回false + if(!getGrayOpen()){ + log.info("grayOpen is false"); + return false; + } + //如果灰度打开,并且所有请求都走灰度则返回true + if(getAllRequestGray()){ + log.info("access gray interface,requestConfigId={}",requestConfigId); + return true; + } + if(requestConfigId == null){ + return false; + } + + if(MapUtils.isEmpty(groupMap)){ + loadRule(); + } + + InterfaceWeightGroup interfaceWeightGroup = groupMap.get(requestConfigId); + //找不到配置,则返回false + if(interfaceWeightGroup == null){ + return false; + } + return interfaceWeightGroup.accessGray(); + }catch (Exception e){ + log.error("error to isGray",e); + return false; + } + + } + + /** + * 是否命中灰度 + * @param requestConfigId 接口配置ID + * @param userId 用户ID + * @return + */ + public boolean isGray(Integer requestConfigId,Integer userId){ + try { + //如果灰度关闭则返回false + if(!getGrayOpen()){ + log.info("grayOpen is false"); + return false; + } + //如果灰度打开,并且所有请求都走灰度则返回true + if(getAllRequestGray()){ + log.info("access gray interface,requestConfigId={}",requestConfigId); + return true; + } + + if(requestConfigId == null){ + return false; + } + + //如果用户白名单策略不为空,则优先走白名单判断 + if(!CollectionUtils.isEmpty(userIdList)){ + if(userIdList.contains(userId)){ + log.info("access gray interface,requestConfigId={},userId={}",requestConfigId,userId); + return true; + } + return false; + } + + if(MapUtils.isEmpty(groupMap)){ + loadRule(); + } + + InterfaceWeightGroup interfaceWeightGroup = groupMap.get(requestConfigId); + //找不到配置,则返回false + if(interfaceWeightGroup == null){ + return false; + } + return interfaceWeightGroup.accessGray(); + }catch (Exception e){ + log.error("error to isGray",e); + return false; + } + + } + + public static void main(String[] args){ + JSONArray jsonArray = new JSONArray(); + + JSONObject requestConfig1 = new JSONObject(); + requestConfig1.put("id",1); + requestConfig1.put("grayNumber",100); + requestConfig1.put("normalNumber",9900); + + JSONObject requestConfig2 = new JSONObject(); + requestConfig2.put("id",2); + requestConfig2.put("grayNumber",1000); + requestConfig2.put("normalNumber",9000); + + jsonArray.add(requestConfig1); + jsonArray.add(requestConfig2); + + + System.out.println(jsonArray); + } + + + +} diff --git a/distributed/gray/src/main/java/cn/cunchang/v2/InterfaceWeightGroup.java b/distributed/gray/src/main/java/cn/cunchang/v2/InterfaceWeightGroup.java new file mode 100644 index 00000000..a630ba51 --- /dev/null +++ b/distributed/gray/src/main/java/cn/cunchang/v2/InterfaceWeightGroup.java @@ -0,0 +1,152 @@ +package cn.cunchang.v2; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Created by qiumu on 2020/10/10. + */ +@Slf4j(topic = "grayLog") +public class InterfaceWeightGroup { + + + + /** + * 权重配置ID + */ + private Integer id; + + + /** + * 灰度权重对象 + */ + private WeightCategory grayWeightCategory = null; + + /** + * 正常请求权重对象 + */ + private WeightCategory normalWeightCategory = null; + + /** + * 灰度请求进来次数 + */ + private AtomicInteger grayRequestAccessNumber = new AtomicInteger(0); + + /** + * 灰度请求进来次数 + */ + private AtomicInteger normalRequestAccessNumber = new AtomicInteger(0);; + + + /** + * 权重请求列表 + */ + private List categoryList=new ArrayList<>(); + + /** + * 初始化 + */ + private void init(){ + + categoryList.add(grayWeightCategory); + categoryList.add(normalWeightCategory); + + } + + + + public InterfaceWeightGroup(Integer id,WeightCategory grayWeightCategory,WeightCategory normalWeightCategory){ + this.id = id; + this.grayWeightCategory = grayWeightCategory; + this.normalWeightCategory = normalWeightCategory; + //添加权重到list + init(); + } + + /** + * 此次是否是灰度 + * @return + */ + public boolean accessGray(){ + + String categoryName = getWeight(categoryList); + + if(Constant.GRAY.equals(categoryName)){ + int grayNumber = grayRequestAccessNumber.incrementAndGet(); + log.info("id={},grayRequestAccessNumber={}",id,grayNumber); + return true; + } + + int normalNumber = normalRequestAccessNumber.incrementAndGet(); + log.info("id={},normalRequestAccessNumber={}",id,normalNumber); + + return false; + + } + + /** + * 权重获取方法 + * @param categorys + * @return + */ + public String getWeight(List categorys) { + + if(CollectionUtils.isEmpty(categorys)){ + return Constant.NORMAL; + } + + Integer weightSum = 0; + String result=null; + for (WeightCategory wc : categorys) { + weightSum += wc.getWeight(); + } + + if (weightSum <= 0) { + log.error("Error: weightSum=" + weightSum.toString()); + return result; + } + Random random = new Random(); + Integer n = random.nextInt(weightSum); // n in [0, weightSum) + Integer m = 0; + for (WeightCategory wc : categorys) { + if (m <= n && n < m + wc.getWeight()) { + result=wc.getCategory(); + break; + } + m += wc.getWeight(); + } + + return result; + } + + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public WeightCategory getGrayWeightCategory() { + return grayWeightCategory; + } + + public void setGrayWeightCategory(WeightCategory grayWeightCategory) { + this.grayWeightCategory = grayWeightCategory; + } + + public WeightCategory getNormalWeightCategory() { + return normalWeightCategory; + } + + public void setNormalWeightCategory(WeightCategory normalWeightCategory) { + this.normalWeightCategory = normalWeightCategory; + } + +} diff --git a/distributed/gray/src/main/java/cn/cunchang/v2/UrlListEnum.java b/distributed/gray/src/main/java/cn/cunchang/v2/UrlListEnum.java new file mode 100644 index 00000000..b82fc015 --- /dev/null +++ b/distributed/gray/src/main/java/cn/cunchang/v2/UrlListEnum.java @@ -0,0 +1,150 @@ +package cn.cunchang.v2; + +/** + * 付款计划、付款申请单、提现申请单leo迁移的接口列表 + * Created by qiumu on 2020/10/28. + */ +public enum UrlListEnum { + + PC进场费管理_付款计划_1(1,"leo/1.0/payPlan/list"), + + PC合同详情_付款计划_2(2,"leo/1.0/payPlan/detail"), + + PC合同详情_付款计划_新增付款计划_3(3,"leo/1.0/payPlan/add"), + + PC合同详情_付款计划_新增其他费用付款计划_4(4,"leo/1.0/other/fee/payPlan/add"), + + PC合同详情_付款计划_新增押金付款计划_5(5,"leo/1.0/deposit/plan/create"), + + PC合同详情_付款计划_删除_6(6,"leo/1.0/payPlan/delete"), + + PC合同详情_付款计划_发起请款_查询付款计划_7(7,"leo/1.0/payPlanLine/detail"), + + 瓯柑那边调用_根据付款申请单号获取付款计划税前金额_8(8,"leo/1.0/payPlan/getByApplyNo"), + + 付款成功后lvy回调leo更新付款计划为付款成功_9(9,"leo/1.0/payApply/pay/callback"), + + 移动端付款申请单列表_10(10,"leo/search/payApply"), + + PC合同_付款计划_发起请款_提交_check_11(11,"leo/1.0/payPlan/check"), + + PC合同_付款计划_发起请款_提交_12(12,"leo/1.0/payPlan/edit"), + + 付款申请单列表_查询条件subjectTypeList_13(13,"leo/1.0/scm/invoice/subjectType/list"), + + 付款申请单列表List_14(14,"leo/1.0/payApply/list"), + + 付款申请单列表sum_15(15,"leo/1.0/payApply/sumAmount"), + + 直营付款申请单获取审批人_16(16,"leo/1.0/approval/task/checker/payment/apply"), + + KA付款申请单获取审批人_17(17,"leo/1.0/approval/task/checker/ka/payment/apply"), + + KA付款申请单获取审批人2_18(18,"leo/1.0/approval/task/checker/payment/apply/ka"), + + 付款申请单回调_19(19,"leo/1.0/payApply/check/result"), + + 付款申请单撤回_20(20,"leo/1.0/payPlan/recall"), + + PC付款申请单_发票核销_21(21,"leo/1.0/payApply/invoice/use"), + + PC付款申请单_切换票款顺序_22(22,"leo/1.0/payApply/invoice/updateMethod"), + + PC付款申请单_审批详情1_23(23,"leo/1.0/approval/purchasePlan/getProcessDetail"), + + PC付款申请单_审批详情2_24(24,"leo/1.0/payApply/check/detail"), + + PC付款申请单_申请详情_25(25,"leo/1.0/payApply/detail"), + + 提现申请回调_26(26,"leo/1.0/approval/callback/merchant/withDraw/add"), + + 商户提现流程审批流程获取任务节点的审批人接口_27(27,"leo/1.0/approval/task/checker/merchant/withDraw/add"), + + 移动端提现申请列表_28(28,"/leo/search/withdrawals"), + + PC端_财务管理_提现申请_提现申请列表List_29(29,"leo/1.0/merchant/withDraw/queryWithdrawList"), + + PC端_财务管理_提现申请_提现申请列表Sum_30(30,"leo/1.0/merchant/withDraw/sumAmount"), + + PC端_财务管理_提现申请_提现申请列表查询条件1_31(31,"leo/1.0/h5/merchant/withDraw/clientStatusList"), + + PC端_财务管理_提现申请_提现申请列表查询条件2_32(32,"leo/1.0/h5/merchant/withDraw/statusList"), + + PC端_财务管理_提现申请_提现申请列表_审核_通过_拒绝_冻结_33(33,"leo/1.0/merchant/withDraw/financialOperationCheck"), + + PC端_财务管理_提现申请_提现申请列表_审批详情_34(34,"leo/1.0/approval/purchasePlan/getProcessDetail"), + + PC端_财务管理_提现申请_提现申请列表_审核_35(35,"leo/1.0/merchant/withDraw/getWithdrawalDetail"), + + PC端_财务管理_提现申请_提现申请列表_发票核对_查询发票_36(36,"leo/1.0/merchant/withDraw/getInvoiceInfo"), + + PC端_财务管理_提现申请_提现申请列表_发票核对_通过_不通过_37(37,"leo/1.0/merchant/withDraw/invoiceCheck"), + + 移动端_审批中心_提现修改发票_38(38,"leo/1.0/merchant/withDraw/modifyInvoiceInfo"), + + PC端_财务管理_提现申请_先款后票白名单维护_39(39,"leo/1.0/withdrawals/whitelist/list"), + + PC端_财务管理_提现申请_先款后票白名单维护_新增_40(40,"leo/1.0/withdrawals/whitelist/batch"), + + PC端_财务管理_提现申请_先款后票白名单维护_作废_41(41,"leo/1.0/withdrawals/whitelist/{mainBizId}"), + + PC端_财务管理_提现申请_先款后票白名单维护_生效_作废_42(42,"leo/1.0/withdrawals/whitelist/enable/{mainBizId}"), + + PC端_财务管理_提现申请_先款后票白名单维护_导出_43(43,"leo/1.0/withdrawals/whitelist/export"), + + 提现申请_导出_44(44,"leo/1.0/h5/merchant/withDraw/export"), + + lvy账单任务创建AccountFreezeTask_45(45,"leo/1.0/merchant/withDraw/recall/byLvy"), + + 提现批量审核_查询_46(46,"leo/1.0/h5/merchant/withDraw/batch/getTaskInfo"), + + 提现批量审核_下一步47(47,"leo/1.0/h5/merchant/withDraw/batch/getAuditDetailList"), + + 批量处理审批任务48(48,"leo/1.0/h5/merchant/withDraw/batchHandleApprovalTask"), + + BD审核任务_49(49,"/leo/1.0/merchant/withDraw/addBdCheckOperatorRecord"), + + 获取提现发票信息_50(50,"/leo/1.0/merchant/withdrawal/invoice"), + + 获取批量审批提现单列表_51(51,"/leo/1.0/merchant/withDraw/batch/getList"), + + 获取批量审批提现单列表总金额_52(52,"/leo/1.0/merchant/withDraw/batch/sumAmount"), + + 批量审核提交_53(53,"/leo/1.0/merchant/withDraw/batch/submit"), + + 提现先款后票_发票核销_54(54,"/leo/1.0/withdrawals/invoice/deduct"), + + ; + + + + + /** + * 接口ID + */ + private Integer id ; + + + /** + * + */ + private String url; + + + UrlListEnum(Integer id,String url){ + this.id = id; + this.url = url; + } + + + public Integer getId() { + return id; + } + + public String getUrl() { + return url; + } + + + +} diff --git a/distributed/gray/src/main/java/cn/cunchang/v2/WeightCategory.java b/distributed/gray/src/main/java/cn/cunchang/v2/WeightCategory.java new file mode 100644 index 00000000..4c730a23 --- /dev/null +++ b/distributed/gray/src/main/java/cn/cunchang/v2/WeightCategory.java @@ -0,0 +1,36 @@ +package cn.cunchang.v2; + +/** + * 权重分类 + * Created by qiumu on 2020/10/10. + */ +public class WeightCategory { + + //类别 + private String category; + //权重值 + private int weight; + + public WeightCategory(String category, int weight) { + this.category = category; + this.weight = weight; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public int getWeight() { + return weight; + } + + public void setWeight(int weight) { + this.weight = weight; + + } + +} diff --git a/distributed/gray/src/main/java/cn/cunchang/v2/WeightTest.java b/distributed/gray/src/main/java/cn/cunchang/v2/WeightTest.java new file mode 100644 index 00000000..6213f151 --- /dev/null +++ b/distributed/gray/src/main/java/cn/cunchang/v2/WeightTest.java @@ -0,0 +1,70 @@ +package cn.cunchang.v2; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +/** + * Created by qiumu on 2020/10/10. + */ +public class WeightTest { + + public static void main(String[] args){ + + //测试数据 + List categoryList=new ArrayList<>(); + WeightCategory weightCategory1=new WeightCategory("一等奖",1000); + WeightCategory weightCategory2=new WeightCategory("二等奖",9000); + categoryList.add(weightCategory1); + categoryList.add(weightCategory2); + + String result= ""; + int a1=0,a2=0; + for (int i=0;i<10000;i++){ + result = getWeight(categoryList); + System.out.println(i+" 开奖结果: "+result); + if(result.equals("一等奖")){ + a1++; + } + else if(result.equals("二等奖")){ + a2++; + } + } + + System.out.println("一等奖共出现 "+a1); + System.out.println("二等奖共出现 "+a2); + + + } + + /** + * 权重获取方法 + * @param categorys + * @return + */ + public static String getWeight(List categorys) { + Integer weightSum = 0; + String result=null; + for (WeightCategory wc : categorys) { + weightSum += wc.getWeight(); + } + + if (weightSum <= 0) { + System.err.println("Error: weightSum=" + weightSum.toString()); + return result; + } + Random random = new Random(); + Integer n = random.nextInt(weightSum); // n in [0, weightSum) + Integer m = 0; + for (WeightCategory wc : categorys) { + if (m <= n && n < m + wc.getWeight()) { + result=wc.getCategory(); + break; + } + m += wc.getWeight(); + } + return result; + } + + +} diff --git a/distributed/gray/src/main/java/cn/cunchang/v2/web/GrayConfigController.java b/distributed/gray/src/main/java/cn/cunchang/v2/web/GrayConfigController.java new file mode 100644 index 00000000..18a2ab3d --- /dev/null +++ b/distributed/gray/src/main/java/cn/cunchang/v2/web/GrayConfigController.java @@ -0,0 +1,148 @@ +package cn.cunchang.v2.web; + +import cn.cunchang.v2.GrayHelper; +import cn.cunchang.v2.web.req.RequestConfigParam; +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import org.redisson.api.RBucket; +import org.redisson.api.RedissonClient; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.concurrent.TimeUnit; + +/** + * Created by qiumu on 2020/10/11. + */ + +@Controller +@Slf4j(topic = "grayLog") +public class GrayConfigController { + + @Resource + private GrayHelper grayHelper; + + @Resource + private RedissonClient redissonClient; + + /** + * 第一步:每台机器都进行设置灰度策略配置并加载 + * @param config + * @return + */ + @RequestMapping(value = {"/gray/loadRequestConfig"},method = RequestMethod.POST) + @ResponseBody + public String loadRequestConfig(@RequestBody RequestConfigParam config){ + + boolean ok = false; + try { + String json = JSON.toJSONString(config); + RBucket rBucket = redissonClient.getBucket(GrayHelper.GRAY_RULE_STR_KEY); + //保存60天 + rBucket.set(json,60 * 24 * 60 * 60, TimeUnit.SECONDS); + + ok = grayHelper.loadRule(); + }catch (Exception e){ + log.error(e.getMessage(),e); + return "fail"; + } + if(ok){ + return "ok"; + } + return "fail"; + + } + + /** + * 第一步:设置灰度策略配置并加载 + * @param grayOpen + * @return + */ + @RequestMapping(value = {"/gray/setGrayOpen"}) + @ResponseBody + public String setGrayOpen(@RequestParam("grayOpen") String grayOpen){ + + try { + grayHelper.setGrayOpen(grayOpen); + }catch (Exception e){ + log.error(e.getMessage(),e); + return "fail"; + } + return "ok"; + } + + /** + * 第二步:设置是否都走灰度请求 + * @param allRequestGray + * @return + */ + @RequestMapping(value = {"/gray/setAllRequestGray"}) + @ResponseBody + public String setAllRequestGray(@RequestParam("allRequestGray") String allRequestGray){ + + try { + grayHelper.setAllRequestGray(allRequestGray); + }catch (Exception e){ + log.error(e.getMessage(),e); + return "fail"; + } + return "ok"; + } + + /** + * 获取请求配置 + * @return + */ + @RequestMapping(value = {"/gray/getRequestConfig"}) + @ResponseBody + public String getRequestConfig(){ + + try { + RBucket rBucket = redissonClient.getBucket(GrayHelper.GRAY_RULE_STR_KEY); + if(rBucket == null || rBucket.get() == null){ + return "empty"; + } + return rBucket.get(); + }catch (Exception e){ + log.error(e.getMessage(),e); + return "fail"; + } + + } + + /** + * 查询灰度开关 + * @return + */ + @RequestMapping(value = {"/gray/getGrayOpen"}) + @ResponseBody + public Boolean getGrayOpen(){ + + try { + return grayHelper.getGrayOpen(); + }catch (Exception e){ + log.error(e.getMessage(),e); + return false; + } + } + + /** + * + * @return + */ + @RequestMapping(value = {"/gray/getAllRequestGray"}) + @ResponseBody + public Boolean getAllRequestGray(){ + + try { + return grayHelper.getAllRequestGray(); + }catch (Exception e){ + log.error(e.getMessage(),e); + return false; + } + } + + + +} diff --git a/distributed/gray/src/main/java/cn/cunchang/v2/web/req/RequestConfig.java b/distributed/gray/src/main/java/cn/cunchang/v2/web/req/RequestConfig.java new file mode 100644 index 00000000..b2a5b92b --- /dev/null +++ b/distributed/gray/src/main/java/cn/cunchang/v2/web/req/RequestConfig.java @@ -0,0 +1,22 @@ +package cn.cunchang.v2.web.req; + +import lombok.Data; + +/** + * Created by qiumu on 2020/10/11. + */ +@Data +public class RequestConfig { + + + /** + * 接口ID + */ + private Integer id; + + private Integer grayNumber; + + private Integer normalNumber; + + +} diff --git a/distributed/gray/src/main/java/cn/cunchang/v2/web/req/RequestConfigParam.java b/distributed/gray/src/main/java/cn/cunchang/v2/web/req/RequestConfigParam.java new file mode 100644 index 00000000..5006f22f --- /dev/null +++ b/distributed/gray/src/main/java/cn/cunchang/v2/web/req/RequestConfigParam.java @@ -0,0 +1,25 @@ +package cn.cunchang.v2.web.req; + +import lombok.Data; + +import java.util.List; + +/** + * Created by qiumu on 2020/10/11. + */ +@Data +public class RequestConfigParam { + + + /** + * 白名单userID + */ + private List grayUserIdList; + + + /** + * 配置列表 + */ + private List requestConfigList; + +} diff --git a/distributed/gray/src/main/resources/application.yml b/distributed/gray/src/main/resources/application.yml new file mode 100644 index 00000000..1cb00593 --- /dev/null +++ b/distributed/gray/src/main/resources/application.yml @@ -0,0 +1,12 @@ +# common spring boot settings + +spring.redis.database= +spring.redis.host=127.0.0.1 +spring.redis.port=6397 +spring.redis.password= +spring.redis.ssl= +spring.redis.timeout= +spring.redis.cluster.nodes= +spring.redis.sentinel.master= +spring.redis.sentinel.nodes= + diff --git a/distributed/lock/flow1/Thread Group100.jmx b/distributed/lock/flow1/Thread Group100.jmx new file mode 100644 index 00000000..1ebff925 --- /dev/null +++ b/distributed/lock/flow1/Thread Group100.jmx @@ -0,0 +1,51 @@ + + + + + + false + true + false + + + + + + + + continue + + false + 1 + + 100 + 1 + false + + + true + + + + + + + http://localhost/ + + + + http://localhost/buy_goods + GET + true + false + true + false + + + + + + + + + diff --git a/distributed/lock/flow1/pom.xml b/distributed/lock/flow1/pom.xml new file mode 100644 index 00000000..f1340bcb --- /dev/null +++ b/distributed/lock/flow1/pom.xml @@ -0,0 +1,97 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.4.0 + + + cn.cunchang + flow1 + 0.0.1-SNAPSHOT + flow1 + Demo project for redis distributed lock + + + 1.8 + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.apache.commons + commons-pool2 + + + + redis.clients + jedis + 3.1.0 + + + + + org.springframework.boot + spring-boot-starter-aop + + + + org.redisson + redisson + 3.13.6 + + + + org.projectlombok + lombok + true + + + + junit + junit + 4.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/distributed/lock/flow1/src/main/java/cn/cunchang/Application1.java b/distributed/lock/flow1/src/main/java/cn/cunchang/Application1.java new file mode 100644 index 00000000..4b963062 --- /dev/null +++ b/distributed/lock/flow1/src/main/java/cn/cunchang/Application1.java @@ -0,0 +1,14 @@ +package cn.cunchang; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; + +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) +public class Application1 { + + public static void main(String[] args) { + SpringApplication.run(Application1.class, args); + } + +} diff --git a/distributed/lock/flow1/src/main/java/cn/cunchang/config/RedisConfig.java b/distributed/lock/flow1/src/main/java/cn/cunchang/config/RedisConfig.java new file mode 100644 index 00000000..2225fde2 --- /dev/null +++ b/distributed/lock/flow1/src/main/java/cn/cunchang/config/RedisConfig.java @@ -0,0 +1,42 @@ + +package cn.cunchang.config; + +import org.redisson.Redisson; +import org.redisson.api.RedissonClient; +import org.redisson.client.codec.Codec; +import org.redisson.config.Config; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.io.Serializable; + +@Configuration +public class RedisConfig { + + /*** 保证不是序列化后的乱码配置 */ + @Bean + public RedisTemplate redisTemplate(LettuceConnectionFactory connectionFactory) { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + redisTemplate.setConnectionFactory(connectionFactory); + return redisTemplate; + } + + @Bean + public RedissonClient redisson() { + Config config = new Config(); + config.useSingleServer().setAddress("redis://127.0.0.1:6379").setDatabase(0); + try { + config.setCodec((Codec) Class.forName("org.redisson.codec.JsonJacksonCodec").newInstance()); + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { + e.printStackTrace(); + } + return Redisson.create(config); + } +} + diff --git a/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController1.java b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController1.java new file mode 100644 index 00000000..e26a1669 --- /dev/null +++ b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController1.java @@ -0,0 +1,37 @@ +package cn.cunchang.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + + +//@RestController +public class GoodController1 { + @Autowired + private StringRedisTemplate stringRedisTemplate; + @Value("${server.port}") + private String serverPort; + + /** + * + * 产生的问题:单机无锁,非原子操作 + * @return + */ + @GetMapping("/buy_goods") + public String buyGoods() { + String result = stringRedisTemplate.opsForValue().get("goods:001"); + int goodsNumber = result == null ? 0 : Integer.parseInt(result); + if (goodsNumber > 0) { + int realNumber = goodsNumber - 1; + stringRedisTemplate.opsForValue().set("goods:001", realNumber + ""); + System.out.println(" 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort); + return " 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort; + } else { + System.out.println(" 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort); + } + return " 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort; + } +} + diff --git a/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController2.java b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController2.java new file mode 100644 index 00000000..70fb08d5 --- /dev/null +++ b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController2.java @@ -0,0 +1,39 @@ +package cn.cunchang.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + + +//@RestController +public class GoodController2 { + @Autowired + private StringRedisTemplate stringRedisTemplate; + @Value("${server.port}") + private String serverPort; + + /** + * 解决了1的问题 + * 产生的问题:集群有锁,非原子操作 + * @return + */ + @GetMapping("/buy_goods") + public String buyGoods() { + synchronized (this) { + String result = stringRedisTemplate.opsForValue().get("goods:001"); + int goodsNumber = result == null ? 0 : Integer.parseInt(result); + if (goodsNumber > 0) { + int realNumber = goodsNumber - 1; + stringRedisTemplate.opsForValue().set("goods:001", realNumber + ""); + System.out.println(" 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort); + return " 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort; + } else { + System.out.println(" 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort); + } + return " 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort; + } + } +} + diff --git a/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController3.java b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController3.java new file mode 100644 index 00000000..702e55f1 --- /dev/null +++ b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController3.java @@ -0,0 +1,52 @@ +package cn.cunchang.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.UUID; + + +//@RestController +public class GoodController3 { + @Autowired + private StringRedisTemplate stringRedisTemplate; + @Value("${server.port}") + private String serverPort; + + private String LOCK_KEY = "seckillLock"; + + /** + * 解决了2的问题 + * 产生的问题:集群有分布式锁,设置锁后宕机,死锁 + * @return + */ + @GetMapping("/buy_goods") + public String buyGoods() { + + try { + String lockValue = UUID.randomUUID().toString(); + //NX + Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(LOCK_KEY, lockValue); + if (!flag) { + return "抢锁失败!!!请再次尝试"; + } + String result = stringRedisTemplate.opsForValue().get("goods:001"); + int goodsNumber = result == null ? 0 : Integer.parseInt(result); + if (goodsNumber > 0) { + int realNumber = goodsNumber - 1; + stringRedisTemplate.opsForValue().set("goods:001", realNumber + ""); + System.out.println(" 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort); + return " 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort; + } else { + System.out.println(" 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort); + } + return " 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort; + } finally { + stringRedisTemplate.delete(LOCK_KEY); + } + } +} + diff --git a/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController4.java b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController4.java new file mode 100644 index 00000000..d5e3de10 --- /dev/null +++ b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController4.java @@ -0,0 +1,54 @@ +package cn.cunchang.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + + +//@RestController +public class GoodController4 { + @Autowired + private StringRedisTemplate stringRedisTemplate; + @Value("${server.port}") + private String serverPort; + + private String LOCK_KEY = "seckillLock"; + + /** + * 解决了3的问题 + * 产生的问题:加锁+过期,非原子操作 + * @return + */ + @GetMapping("/buy_goods") + public String buyGoods() { + + try { + String lockValue = UUID.randomUUID().toString(); + //NX + Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(LOCK_KEY, lockValue); + stringRedisTemplate.expire(LOCK_KEY,10L, TimeUnit.SECONDS); + if (!flag) { + return "抢锁失败!!!请再次尝试"; + } + String result = stringRedisTemplate.opsForValue().get("goods:001"); + int goodsNumber = result == null ? 0 : Integer.parseInt(result); + if (goodsNumber > 0) { + int realNumber = goodsNumber - 1; + stringRedisTemplate.opsForValue().set("goods:001", realNumber + ""); + System.out.println(" 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort); + return " 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort; + } else { + System.out.println(" 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort); + } + return " 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort; + } finally { + stringRedisTemplate.delete(LOCK_KEY); + } + } +} + diff --git a/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController5.java b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController5.java new file mode 100644 index 00000000..79a9f19f --- /dev/null +++ b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController5.java @@ -0,0 +1,56 @@ +package cn.cunchang.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + + +//@RestController +public class GoodController5 { + @Autowired + private StringRedisTemplate stringRedisTemplate; + @Value("${server.port}") + private String serverPort; + + private String LOCK_KEY = "seckillLock"; + + /** + * 解决了4的问题

+ * 产生的问题:加锁解锁可能不是一个客户端 + * A抢到锁后锁10秒过期,A业务执行了11秒(正常5~8秒突发情况),锁在第10秒过期后, + * B抢到锁,B业务执行了1秒,A释放锁,此时其实是把B拿到的锁释放了,B还在执行业务代码 + * C抢到锁,B与C分布式锁的代码其实是在并行执行 + * @return + */ + @GetMapping("/buy_goods") + public String buyGoods() { + + try { + String lockValue = UUID.randomUUID().toString(); + //NX+time + Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(LOCK_KEY, lockValue, 10L, TimeUnit.SECONDS); + if (!flag) { + return "抢锁失败!!!请再次尝试"; + } + String result = stringRedisTemplate.opsForValue().get("goods:001"); + int goodsNumber = result == null ? 0 : Integer.parseInt(result); + if (goodsNumber > 0) { + int realNumber = goodsNumber - 1; + stringRedisTemplate.opsForValue().set("goods:001", realNumber + ""); + System.out.println(" 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort); + return " 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort; + } else { + System.out.println(" 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort); + } + return " 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort; + } finally { + stringRedisTemplate.delete(LOCK_KEY); + } + } +} + diff --git a/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController6.java b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController6.java new file mode 100644 index 00000000..68ca8cd0 --- /dev/null +++ b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController6.java @@ -0,0 +1,56 @@ +package cn.cunchang.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.web.bind.annotation.GetMapping; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + + +//@RestController +public class GoodController6 { + @Autowired + private StringRedisTemplate stringRedisTemplate; + @Value("${server.port}") + private String serverPort; + + private String LOCK_KEY = "seckillLock"; + + /** + * 解决了5的问题

+ * + * 产生的问题:判断是不是同一个客户端,不是原子操作,会导致死锁 + * + * @return + */ + @GetMapping("/buy_goods") + public String buyGoods() { + String lockValue = UUID.randomUUID().toString(); + try { + //NX+time + Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(LOCK_KEY, lockValue, 10L, TimeUnit.SECONDS); + if (!flag) { + return "抢锁失败!!!请再次尝试"; + } + String result = stringRedisTemplate.opsForValue().get("goods:001"); + int goodsNumber = result == null ? 0 : Integer.parseInt(result); + if (goodsNumber > 0) { + int realNumber = goodsNumber - 1; + stringRedisTemplate.opsForValue().set("goods:001", realNumber + ""); + System.out.println(" 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort); + return " 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort; + } else { + System.out.println(" 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort); + } + return " 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort; + } finally { + String nowLockValue = stringRedisTemplate.opsForValue().get(LOCK_KEY); + if (nowLockValue != null && nowLockValue.equals(lockValue)) { + stringRedisTemplate.delete(LOCK_KEY); + } + } + } +} + diff --git a/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController7_1.java b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController7_1.java new file mode 100644 index 00000000..a9b15388 --- /dev/null +++ b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController7_1.java @@ -0,0 +1,82 @@ +package cn.cunchang.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.core.script.DefaultRedisScript; +import org.springframework.web.bind.annotation.GetMapping; + +import javax.annotation.PostConstruct; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + + +//@RestController +public class GoodController7_1 { + @Autowired + private StringRedisTemplate stringRedisTemplate; + @Value("${server.port}") + private String serverPort; + + private String LOCK_KEY = "seckillLock"; + + private String DEL_SCRIPT = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" + + "then\n" + + " return redis.call(\"del\",KEYS[1])\n" + + "else\n" + + " return 0\n" + + "end"; + + private DefaultRedisScript getRedisScript; + + @PostConstruct + public void init() { + getRedisScript = new DefaultRedisScript<>(); + getRedisScript.setResultType(List.class); + // 加载lua文本 + getRedisScript.setScriptText(DEL_SCRIPT); + // 加载lua文件 +// getRedisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("lua/DelLockScript.lua"))); + } + + /** + * 解决了6的问题

+ * - lua

+ * - 事务 + *

+ * 产生的问题:续租 + * + * @return + */ + @GetMapping("/buy_goods") + public String buyGoods() { + String lockValue = UUID.randomUUID().toString(); + try { + //NX+time + Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(LOCK_KEY, lockValue, 10L, TimeUnit.SECONDS); + if (!flag) { + return "抢锁失败!!!请再次尝试"; + } + String result = stringRedisTemplate.opsForValue().get("goods:001"); + int goodsNumber = result == null ? 0 : Integer.parseInt(result); + if (goodsNumber > 0) { + int realNumber = goodsNumber - 1; + stringRedisTemplate.opsForValue().set("goods:001", realNumber + ""); + System.out.println(" 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort); + return " 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort; + } else { + System.out.println(" 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort); + } + return " 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort; + } finally { + List keys = new ArrayList<>(); + keys.add(LOCK_KEY); + List args = new ArrayList<>(); + args.add(lockValue); + stringRedisTemplate.execute(getRedisScript, keys, args); + } + } +} + diff --git a/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController7_2.java b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController7_2.java new file mode 100644 index 00000000..5af00008 --- /dev/null +++ b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController7_2.java @@ -0,0 +1,72 @@ +package cn.cunchang.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.web.bind.annotation.GetMapping; + +import java.util.List; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + + +//@RestController +public class GoodController7_2 { + @Autowired + private StringRedisTemplate stringRedisTemplate; + @Value("${server.port}") + private String serverPort; + + private String LOCK_KEY = "seckillLock"; + + /** + * 解决了6的问题

+ * - lua

+ * - 事务 + *

+ * 产生的问题:续租 + * + * @return + */ + @GetMapping("/buy_goods") + public String buyGoods() { + String lockValue = UUID.randomUUID().toString(); + try { + //NX+time + Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(LOCK_KEY, lockValue, 10L, TimeUnit.SECONDS); + if (!flag) { + return "抢锁失败!!!请再次尝试"; + } + String result = stringRedisTemplate.opsForValue().get("goods:001"); + int goodsNumber = result == null ? 0 : Integer.parseInt(result); + if (goodsNumber > 0) { + int realNumber = goodsNumber - 1; + stringRedisTemplate.opsForValue().set("goods:001", realNumber + ""); + System.out.println(" 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort); + return " 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort; + } else { + System.out.println(" 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort); + } + return " 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort; + } finally { + while (true) { + stringRedisTemplate.watch(LOCK_KEY); // 加事务,乐观锁 + if (lockValue.equalsIgnoreCase(stringRedisTemplate.opsForValue().get(LOCK_KEY))) { + stringRedisTemplate.setEnableTransactionSupport(true); + stringRedisTemplate.multi(); + // 开始事务 + stringRedisTemplate.delete(LOCK_KEY); + List list = stringRedisTemplate.exec(); + if (list == null) { + // 如果等于 null ,就是没有删掉,删除失败,再回去 while 循环那再重新执行删除 + continue; + } + } + // 如果删除成功,释放监控器,并且 breank 跳出当前循环 + stringRedisTemplate.unwatch(); + break; + } + } + } +} + diff --git a/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController8.java b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController8.java new file mode 100644 index 00000000..424d16f0 --- /dev/null +++ b/distributed/lock/flow1/src/main/java/cn/cunchang/controller/GoodController8.java @@ -0,0 +1,57 @@ +package cn.cunchang.controller; + +import org.redisson.api.RBucket; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + + +@RestController +public class GoodController8 { + @Value("${server.port}") + private String serverPort; + + private String LOCK_KEY = "seckillLock"; + + @Autowired + private RedissonClient redisson; + + /** + * 解决了7的问题

+ * - watch dog + *

+ * 产生的问题: + * + * @return + */ + @GetMapping("/buy_goods") + public String buyGoods() { + RLock rLock = redisson.getLock(LOCK_KEY); + try { + rLock.lock(); + + RBucket bucket = redisson.getBucket("goods:001"); + Integer result = bucket.get(); + + int goodsNumber = result == null ? 0 : result; + if (goodsNumber > 0) { + int realNumber = goodsNumber - 1; + bucket.set(realNumber); + System.out.println(" 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort); + return " 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort; + } else { + System.out.println(" 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort); + } + return " 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort; + } finally { + // 极端情况下会出现问题 + if (rLock.isLocked() && rLock.isHeldByCurrentThread()) { + rLock.unlock(); + } + } + } +} + diff --git a/distributed/lock/flow1/src/main/resources/application.properties b/distributed/lock/flow1/src/main/resources/application.properties new file mode 100644 index 00000000..f9964fd0 --- /dev/null +++ b/distributed/lock/flow1/src/main/resources/application.properties @@ -0,0 +1,12 @@ +server.port=1111 +spring.redis.database=0 +spring.redis.host=localhost +#连接池最大连接数(使用负值表示没有限制)默认8 +spring.redis.port=6379 +#连接池最大阻塞等待时间(使用负值表示没有限制)默认-1 +spring.redis.lettuce.pool.max-active=8 +#连接池中的最大空闲连接默认8 +spring.redis.lettuce.pool.max-wait=-1 +#连接池中的最小空闲连接默认0 +spring.redis.lettuce.pool.max-idle=8 +spring.redis.lettuce.pool.min-idle=0 \ No newline at end of file diff --git a/distributed/lock/flow1/src/main/resources/lua/DelLockScript.lua b/distributed/lock/flow1/src/main/resources/lua/DelLockScript.lua new file mode 100644 index 00000000..7b3fdb1e --- /dev/null +++ b/distributed/lock/flow1/src/main/resources/lua/DelLockScript.lua @@ -0,0 +1,6 @@ +if redis.call("get",KEYS[1]) == ARGV[1] +then + return redis.call("del",KEYS[1]) +else + return 0 +end \ No newline at end of file diff --git a/distributed/lock/flow1/src/test/java/cn/cunchang/Application1Tests.java b/distributed/lock/flow1/src/test/java/cn/cunchang/Application1Tests.java new file mode 100644 index 00000000..992218a4 --- /dev/null +++ b/distributed/lock/flow1/src/test/java/cn/cunchang/Application1Tests.java @@ -0,0 +1,13 @@ +package cn.cunchang; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class Application1Tests { + + @Test + void contextLoads() { + } + +} diff --git a/distributed/lock/flow2/pom.xml b/distributed/lock/flow2/pom.xml new file mode 100644 index 00000000..5ebdfc0f --- /dev/null +++ b/distributed/lock/flow2/pom.xml @@ -0,0 +1,98 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.4.0 + + + cn.cunchang + flow2 + 0.0.1-SNAPSHOT + flow2 + Demo project for redis distributed lock + + + 1.8 + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.apache.commons + commons-pool2 + + + + + redis.clients + jedis + 3.1.0 + + + + + org.springframework.boot + spring-boot-starter-aop + + + + org.redisson + redisson + 3.13.6 + + + + org.projectlombok + lombok + true + + + + junit + junit + 4.12 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/distributed/lock/flow2/src/main/java/cn/cunchang/Application2.java b/distributed/lock/flow2/src/main/java/cn/cunchang/Application2.java new file mode 100644 index 00000000..40274927 --- /dev/null +++ b/distributed/lock/flow2/src/main/java/cn/cunchang/Application2.java @@ -0,0 +1,14 @@ +package cn.cunchang; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; + +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) +public class Application2 { + + public static void main(String[] args) { + SpringApplication.run(Application2.class, args); + } + +} diff --git a/distributed/lock/flow2/src/main/java/cn/cunchang/config/RedisConfig.java b/distributed/lock/flow2/src/main/java/cn/cunchang/config/RedisConfig.java new file mode 100644 index 00000000..2eeefe5e --- /dev/null +++ b/distributed/lock/flow2/src/main/java/cn/cunchang/config/RedisConfig.java @@ -0,0 +1,42 @@ + +package cn.cunchang.config; + +import org.redisson.Redisson; +import org.redisson.api.RedissonClient; +import org.redisson.client.codec.Codec; +import org.redisson.config.Config; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.io.Serializable; + +@Configuration +public class RedisConfig { + + /*** 保证不是序列化后的乱码配置 */ + @Bean + public RedisTemplate redisTemplate(LettuceConnectionFactory connectionFactory) { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + redisTemplate.setConnectionFactory(connectionFactory); + return redisTemplate; + } + + @Bean + public RedissonClient redisson() { + Config config = new Config(); + config.useSingleServer().setAddress("redis://127.0.0.1:6379").setDatabase(0);; + try { + config.setCodec((Codec) Class.forName("org.redisson.codec.JsonJacksonCodec").newInstance()); + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { + e.printStackTrace(); + } + return Redisson.create(config); + } +} + diff --git a/distributed/lock/flow2/src/main/java/cn/cunchang/controller/GoodController.java b/distributed/lock/flow2/src/main/java/cn/cunchang/controller/GoodController.java new file mode 100644 index 00000000..28b586da --- /dev/null +++ b/distributed/lock/flow2/src/main/java/cn/cunchang/controller/GoodController.java @@ -0,0 +1,34 @@ +package cn.cunchang.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + + +//@RestController +public class GoodController { + @Autowired + private StringRedisTemplate stringRedisTemplate; + @Value("${server.port}") + private String serverPort; + + @GetMapping("/buy_goods") + public String buyGoods() { + synchronized (this) { + String result = stringRedisTemplate.opsForValue().get("goods:001"); + int goodsNumber = result == null ? 0 : Integer.parseInt(result); + if (goodsNumber > 0) { + int realNumber = goodsNumber - 1; + stringRedisTemplate.opsForValue().set("goods:001", realNumber + ""); + System.out.println(" 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort); + return " 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort; + } else { + System.out.println(" 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort); + } + return " 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort; + } + } +} + diff --git a/distributed/lock/flow2/src/main/java/cn/cunchang/controller/GoodController8.java b/distributed/lock/flow2/src/main/java/cn/cunchang/controller/GoodController8.java new file mode 100644 index 00000000..424d16f0 --- /dev/null +++ b/distributed/lock/flow2/src/main/java/cn/cunchang/controller/GoodController8.java @@ -0,0 +1,57 @@ +package cn.cunchang.controller; + +import org.redisson.api.RBucket; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + + +@RestController +public class GoodController8 { + @Value("${server.port}") + private String serverPort; + + private String LOCK_KEY = "seckillLock"; + + @Autowired + private RedissonClient redisson; + + /** + * 解决了7的问题

+ * - watch dog + *

+ * 产生的问题: + * + * @return + */ + @GetMapping("/buy_goods") + public String buyGoods() { + RLock rLock = redisson.getLock(LOCK_KEY); + try { + rLock.lock(); + + RBucket bucket = redisson.getBucket("goods:001"); + Integer result = bucket.get(); + + int goodsNumber = result == null ? 0 : result; + if (goodsNumber > 0) { + int realNumber = goodsNumber - 1; + bucket.set(realNumber); + System.out.println(" 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort); + return " 你已经成功秒杀商品,此时还剩余: " + realNumber + " 件 " + " \t 服务器端口 : " + serverPort; + } else { + System.out.println(" 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort); + } + return " 商品已经售罄 / 活动结束 / 调用超时,欢迎下次光临 " + " \t 服务器端口 : " + serverPort; + } finally { + // 极端情况下会出现问题 + if (rLock.isLocked() && rLock.isHeldByCurrentThread()) { + rLock.unlock(); + } + } + } +} + diff --git a/distributed/lock/flow2/src/main/resources/application.properties b/distributed/lock/flow2/src/main/resources/application.properties new file mode 100644 index 00000000..03d037e6 --- /dev/null +++ b/distributed/lock/flow2/src/main/resources/application.properties @@ -0,0 +1,12 @@ +server.port=2222 +spring.redis.database=0 +spring.redis.host=localhost +#连接池最大连接数(使用负值表示没有限制)默认8 +spring.redis.port=6379 +#连接池最大阻塞等待时间(使用负值表示没有限制)默认-1 +spring.redis.lettuce.pool.max-active=8 +#连接池中的最大空闲连接默认8 +spring.redis.lettuce.pool.max-wait=-1 +#连接池中的最小空闲连接默认0 +spring.redis.lettuce.pool.max-idle=8 +spring.redis.lettuce.pool.min-idle=0 \ No newline at end of file diff --git a/distributed/lock/flow2/src/test/java/cn/cunchang/Application2Tests.java b/distributed/lock/flow2/src/test/java/cn/cunchang/Application2Tests.java new file mode 100644 index 00000000..59265d64 --- /dev/null +++ b/distributed/lock/flow2/src/test/java/cn/cunchang/Application2Tests.java @@ -0,0 +1,13 @@ +package cn.cunchang; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class Application2Tests { + + @Test + void contextLoads() { + } + +} diff --git a/distributed/lock/jedis/README.md b/distributed/lock/jedis/README.md new file mode 100644 index 00000000..156c1efe --- /dev/null +++ b/distributed/lock/jedis/README.md @@ -0,0 +1,30 @@ + +# redis学习时的代码笔记 + +## asynqueue 异步队列 + +## basic 基础数据结构操作 + +## cluster Java集群操作 + +## dlock redis分布式锁 + +## hyperloglog 统计 + +## bloomfilter 布隆过滤器 + +## partition hash节点迁移率 + +## pipeline 流水线指令 + +## publishersubscriber 发布订阅 + +## sentinel 哨兵 + +## transaction 事务 + + + + + + diff --git a/distributed/lock/jedis/pom.xml b/distributed/lock/jedis/pom.xml new file mode 100644 index 00000000..a97af966 --- /dev/null +++ b/distributed/lock/jedis/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + cn.lastwhisper + jedis + 1.0-SNAPSHOT + jedis + + + + + + com.redislabs + jrebloom + 1.0.1 + + + + com.alibaba + fastjson + 1.2.56 + + + + com.google.guava + guava + 27.0.1-jre + + + + + redis.clients + jedis + 2.9.0 + + + + junit + junit + 4.12 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.7.0 + + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/distributed/lock/jedis/src/main/java/cn/cunchang/JedisUtil.java b/distributed/lock/jedis/src/main/java/cn/cunchang/JedisUtil.java new file mode 100644 index 00000000..216ed3f2 --- /dev/null +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/JedisUtil.java @@ -0,0 +1,15 @@ +package cn.cunchang; + +import cn.cunchang.common.Const; +import redis.clients.jedis.Jedis; + +public class JedisUtil { + + public static Jedis getJedis() { + // 默认db0,可以设置 + Jedis jedis = new Jedis(Const.IP, Const.PORT); +// jedis.select(1); + return jedis; + } + +} diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/asynqueue/RedisDelayingQueue.java b/distributed/lock/jedis/src/main/java/cn/cunchang/asynqueue/RedisDelayingQueue.java similarity index 96% rename from database/redis/src/main/java/cn/lastwhisper/redis/asynqueue/RedisDelayingQueue.java rename to distributed/lock/jedis/src/main/java/cn/cunchang/asynqueue/RedisDelayingQueue.java index 3ac51dfa..e9ca8024 100644 --- a/database/redis/src/main/java/cn/lastwhisper/redis/asynqueue/RedisDelayingQueue.java +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/asynqueue/RedisDelayingQueue.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.redis.asynqueue; +package cn.cunchang.asynqueue; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; @@ -10,7 +10,7 @@ /** * 延时队列的实现 - * @author lastwhisper + * @author cunchang */ public class RedisDelayingQueue { @@ -68,6 +68,7 @@ public static void main(String[] args) { RedisDelayingQueue queue = new RedisDelayingQueue(jedis, "q-demo"); Thread producer = new Thread() { + @Override public void run() { for (int i = 0; i < 10; i++) { queue.delay("codehole" + i); @@ -77,6 +78,7 @@ public void run() { }; Thread consumer = new Thread() { + @Override public void run() { queue.loop(); } diff --git a/distributed/lock/jedis/src/main/java/cn/cunchang/basic/BasicOperation.java b/distributed/lock/jedis/src/main/java/cn/cunchang/basic/BasicOperation.java new file mode 100644 index 00000000..d207c9fd --- /dev/null +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/basic/BasicOperation.java @@ -0,0 +1,12 @@ +package cn.cunchang.basic; + +/** + * Redis基础数据结构的操作 + * @author cunchang + * @date 2019/11/23 + */ +public class BasicOperation { + + + +} diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/basic/StringOper.java b/distributed/lock/jedis/src/main/java/cn/cunchang/basic/StringOper.java similarity index 84% rename from database/redis/src/main/java/cn/lastwhisper/redis/basic/StringOper.java rename to distributed/lock/jedis/src/main/java/cn/cunchang/basic/StringOper.java index 5ff185ce..3beefdbd 100644 --- a/database/redis/src/main/java/cn/lastwhisper/redis/basic/StringOper.java +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/basic/StringOper.java @@ -1,10 +1,10 @@ -package cn.lastwhisper.redis.basic; +package cn.cunchang.basic; import redis.clients.jedis.Jedis; /** * string数据结构的操作 - * @author lastwhisper + * @author cunchang * @date 2019/11/24 */ public class StringOper { diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/bloomfilter/BloomTest.java b/distributed/lock/jedis/src/main/java/cn/cunchang/bloomfilter/BloomTest.java similarity index 94% rename from database/redis/src/main/java/cn/lastwhisper/redis/bloomfilter/BloomTest.java rename to distributed/lock/jedis/src/main/java/cn/cunchang/bloomfilter/BloomTest.java index 6692b993..442a9b29 100644 --- a/database/redis/src/main/java/cn/lastwhisper/redis/bloomfilter/BloomTest.java +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/bloomfilter/BloomTest.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.redis.bloomfilter; +package cn.cunchang.bloomfilter; import io.rebloom.client.Client; import org.junit.Test; @@ -7,7 +7,7 @@ /** * 布隆过滤器测试 - * @author lastwhisper + * @author cunchang */ public class BloomTest { diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/bloomfilter/BloomTest2.java b/distributed/lock/jedis/src/main/java/cn/cunchang/bloomfilter/BloomTest2.java similarity index 96% rename from database/redis/src/main/java/cn/lastwhisper/redis/bloomfilter/BloomTest2.java rename to distributed/lock/jedis/src/main/java/cn/cunchang/bloomfilter/BloomTest2.java index b40954eb..813dcae2 100644 --- a/database/redis/src/main/java/cn/lastwhisper/redis/bloomfilter/BloomTest2.java +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/bloomfilter/BloomTest2.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.redis.bloomfilter; +package cn.cunchang.bloomfilter; import io.rebloom.client.Client; @@ -8,7 +8,7 @@ /** * 测试bloomfilter的误判率 - * @author lastwhisper + * @author cunchang */ public class BloomTest2 { diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/bloomfilter/BloomTest3.java b/distributed/lock/jedis/src/main/java/cn/cunchang/bloomfilter/BloomTest3.java similarity index 96% rename from database/redis/src/main/java/cn/lastwhisper/redis/bloomfilter/BloomTest3.java rename to distributed/lock/jedis/src/main/java/cn/cunchang/bloomfilter/BloomTest3.java index cb69ca2b..3b3f78b3 100644 --- a/database/redis/src/main/java/cn/lastwhisper/redis/bloomfilter/BloomTest3.java +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/bloomfilter/BloomTest3.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.redis.bloomfilter; +package cn.cunchang.bloomfilter; import io.rebloom.client.Client; @@ -7,7 +7,7 @@ import java.util.concurrent.ThreadLocalRandom; /** - * @author lastwhisper + * @author cunchang */ public class BloomTest3 { private String chars; diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/bloomfilter/GuavaBloom.java b/distributed/lock/jedis/src/main/java/cn/cunchang/bloomfilter/GuavaBloom.java similarity index 91% rename from database/redis/src/main/java/cn/lastwhisper/redis/bloomfilter/GuavaBloom.java rename to distributed/lock/jedis/src/main/java/cn/cunchang/bloomfilter/GuavaBloom.java index 8eb2ac28..e663a39f 100644 --- a/database/redis/src/main/java/cn/lastwhisper/redis/bloomfilter/GuavaBloom.java +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/bloomfilter/GuavaBloom.java @@ -1,11 +1,11 @@ -package cn.lastwhisper.redis.bloomfilter; +package cn.cunchang.bloomfilter; import com.google.common.hash.BloomFilter; import com.google.common.hash.Funnel; import com.google.common.hash.Funnels; /** - * @author lastwhisper + * @author cunchang */ public class GuavaBloom { public static void main(String[] args) { diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/cluster/ClusterTest.java b/distributed/lock/jedis/src/main/java/cn/cunchang/cluster/ClusterTest.java similarity index 95% rename from database/redis/src/main/java/cn/lastwhisper/redis/cluster/ClusterTest.java rename to distributed/lock/jedis/src/main/java/cn/cunchang/cluster/ClusterTest.java index 8db76db0..0b12060d 100644 --- a/database/redis/src/main/java/cn/lastwhisper/redis/cluster/ClusterTest.java +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/cluster/ClusterTest.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.redis.cluster; +package cn.cunchang.cluster; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.JedisCluster; @@ -12,7 +12,7 @@ /** * 集群测试 - * @author lastwhisper + * @author cunchang */ public class ClusterTest { diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/cluster/JedisClusterFactory.java b/distributed/lock/jedis/src/main/java/cn/cunchang/cluster/JedisClusterFactory.java similarity index 96% rename from database/redis/src/main/java/cn/lastwhisper/redis/cluster/JedisClusterFactory.java rename to distributed/lock/jedis/src/main/java/cn/cunchang/cluster/JedisClusterFactory.java index 681410ea..f85de56a 100644 --- a/database/redis/src/main/java/cn/lastwhisper/redis/cluster/JedisClusterFactory.java +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/cluster/JedisClusterFactory.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.redis.cluster; +package cn.cunchang.cluster; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.JedisCluster; @@ -38,7 +38,7 @@ public void init() { } - public void destory() { + public void destroy() { if (jedisCluster != null) { try { jedisCluster.close(); diff --git a/distributed/lock/jedis/src/main/java/cn/cunchang/common/Const.java b/distributed/lock/jedis/src/main/java/cn/cunchang/common/Const.java new file mode 100644 index 00000000..4cfa486d --- /dev/null +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/common/Const.java @@ -0,0 +1,13 @@ +package cn.cunchang.common; + +/** + * + * @author cunchang + * @date 2020/4/20 + */ +public interface Const { + + String IP = "127.0.0.1"; + Integer PORT = 6379; + +} diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/hyperloglog/PfTest.java b/distributed/lock/jedis/src/main/java/cn/cunchang/hyperloglog/PfTest.java similarity index 81% rename from database/redis/src/main/java/cn/lastwhisper/redis/hyperloglog/PfTest.java rename to distributed/lock/jedis/src/main/java/cn/cunchang/hyperloglog/PfTest.java index 87e66c52..ece304a0 100644 --- a/database/redis/src/main/java/cn/lastwhisper/redis/hyperloglog/PfTest.java +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/hyperloglog/PfTest.java @@ -1,10 +1,11 @@ -package cn.lastwhisper.redis.hyperloglog; +package cn.cunchang.hyperloglog; +import cn.cunchang.common.Const; import org.junit.Test; import redis.clients.jedis.Jedis; /** - * @author lastwhisper + * @author cunchang */ public class PfTest { @@ -13,7 +14,7 @@ public class PfTest { */ @Test public void test1() { - Jedis jedis = new Jedis("192.168.108.129", 6379); + Jedis jedis = new Jedis(Const.IP, Const.PORT); for (int i = 0; i < 1000; i++) { jedis.pfadd("uv", "user" + i); // 出现误差 @@ -31,7 +32,7 @@ public void test1() { */ @Test public void test2() { - Jedis jedis = new Jedis("192.168.108.129", 6379); + Jedis jedis = new Jedis(Const.IP, Const.PORT); for (int i = 0; i < 10000; i++) { jedis.pfadd("uv", "user" + i); } diff --git a/distributed/lock/jedis/src/main/java/cn/cunchang/lock/LockDome.java b/distributed/lock/jedis/src/main/java/cn/cunchang/lock/LockDome.java new file mode 100644 index 00000000..970127be --- /dev/null +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/lock/LockDome.java @@ -0,0 +1,238 @@ +package cn.cunchang.lock; + + +import redis.clients.jedis.Jedis; +import redis.clients.jedis.Transaction; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +/** + * 分布式锁 + * + * @author cunchang + */ +public class LockDome { + + + /** + * 问题:死锁 + * 解决:需要设置过期时间,自动释放锁 + * + * @param jedis Redis客户端 + * @param lockKey set指令的key + */ + public static void wrongLock1(Jedis jedis, String lockKey) { + Long result = jedis.setnx(lockKey, "lockValue"); + // 1 0 + if (result == 0L) { + throw new RuntimeException("操作太频繁,等一分钟在操作"); + } + try { + // wrong: 若在程序死循环,无法释放锁,将发生死锁 + // do something + } finally { + jedis.del(lockKey); + jedis.close(); + } + } + + /** + * 处理wrongLock1的问题 + *

+ * 问题:非原子操作,死锁 + * 解决: + * - 原生set + * - lua + * - 事务 + * + * @param jedis Redis客户端 + * @param lockKey set指令的key + * @param expireTime 超期时间 + */ + public static void wrongLock2(Jedis jedis, String lockKey, int expireTime) { + Long result = jedis.setnx(lockKey, "lockValue"); + // 1 0 + if (result == 0L) { + throw new RuntimeException("操作太频繁,等一分钟在操作"); + } + try { + // wrong: setnx+expire非原子操作(若程序在这里突然所属进程崩溃、机器宕机等,无法释放锁,将发生死锁) + jedis.expire(lockKey, expireTime); + // do something + } finally { + jedis.del(lockKey); + jedis.close(); + } + } + + //设置锁的lua脚本 + static String SETNX_EXPIRE_SCRIPT = "if redis.call('setnx', KEYS[1], KEYS[2]) == 1 then\n" + + "return redis.call('expire', KEYS[1], KEYS[3]);\n" + + "end\n" + + "return nil;"; + + static String RELEASE_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then\n" + + " return redis.call('del', KEYS[1]);\n" + + " else return 0 end"; + + static String SETNX_EXPIRE_SCRIPT2 = + "if redis.call('setnx', KEYS[1], KEYS[2]) == 1 then return redis.call('expire', KEYS[1], KEYS[3]); end return nil;"; + + static String RELEASE_SCRIPT2 = + "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]); else return 0 end"; + + + /** + * 问题:锁错误释放 + * 解决:value设置随机数,获取lockkey对应的value,判断一下value是否相等 + * + * @param jedis Redis客户端 + * @param lockKey set指令的key + * @param expireTime 超期时间 + */ + public static void wrongLock3_1(Jedis jedis, String lockKey, int expireTime) { + Object result = jedis.set(lockKey, "lockValue", "NX", "EX", expireTime); + // OK null + if (Objects.isNull(result)) { + throw new RuntimeException("操作太频繁,等一分钟在操作"); + } + try { + // do something + // wrong : + // do something 执行超过锁过期时间,锁过期释放 + // do something 执行完毕后,del key,导致锁错误释放 + } finally { + jedis.del(lockKey); + jedis.close(); + } + } + + /** + * 问题:锁错误释放 + * 解决:value设置随机数,获取lockkey对应的value,判断一下value是否相等 + * + * @param jedis Redis客户端 + * @param lockKey set指令的key + * @param expireTime 超期时间 + */ + public static void wrongLock3_2(Jedis jedis, String lockKey, int expireTime) { + String SETNX_EXPIRE_SCRIPT = "if redis.call('setnx', KEYS[1], KEYS[2]) == 1 then\n" + + "return redis.call('expire', KEYS[1], KEYS[3]);\n" + + "end\n" + + "return nil;"; + + Object result = jedis.eval(SETNX_EXPIRE_SCRIPT, 3, lockKey, "lockValue", Integer.toString(expireTime)); + // 1 null + if (Objects.isNull(result)) { + throw new RuntimeException("操作太频繁,等一分钟在操作"); + } + try { + // do something + // wrong : + // do something 执行超过锁过期时间,锁过期释放 + // do something 执行完毕后,del key,导致锁错误释放 + } finally { + jedis.del(lockKey); + jedis.close(); + } + } + + /** + * 问题:client1超时后锁过期释放,client2获取锁后,client1执行完成,将client2的锁释放,导致锁错误释放 + * 解决:value设置随机数 + * + * @param jedis Redis客户端 + * @param lockKey set指令的key + * @param expireTime 超期时间 + */ + public static void wrongLock4(Jedis jedis, String lockKey, int expireTime) { + String randomId = UUID.randomUUID().toString(); + Object result = jedis.set(lockKey, randomId, "NX", "EX", expireTime); + // OK null + if (Objects.isNull(result)) { + throw new RuntimeException("操作太频繁,等一分钟在操作"); + } + try { + // do something + } finally { + // 判断加锁与解锁是不是同一个客户端,防止误解锁 + if (randomId.equals(jedis.get(lockKey))) { + // wrong :无法保证原子性 + jedis.del(lockKey); + } + jedis.close(); + } + } + + /** + * 问题:equals和del不是原子操作 + * 解决: + * - lua + * - 事务 + * + * @param jedis Redis客户端 + * @param lockKey set指令的key + * @param expireTime 超期时间 + */ + public static void lock5_1(Jedis jedis, String lockKey, int expireTime) { + String randomId = UUID.randomUUID().toString(); + Object result = jedis.set(lockKey, randomId, "NX", "EX", expireTime); + // OK null + if (Objects.isNull(result)) { + throw new RuntimeException("操作太频繁,等一分钟在操作"); + } + try { + // do something + } finally { + // 判断加锁与解锁是不是同一个客户端,防止误解锁 + jedis.eval(RELEASE_SCRIPT, Collections.singletonList(lockKey), Collections.singletonList(randomId)); + jedis.close(); + } + } + + /** + * 问题:equals和del不是原子操作 + * 解决: + * - lua + * - 事务 + * + * @param jedis Redis客户端 + * @param lockKey set指令的key + * @param expireTime 超期时间 + */ + public static void lock5_2(Jedis jedis, String lockKey, int expireTime) { + String randomId = UUID.randomUUID().toString(); + Object result = jedis.set(lockKey, randomId, "NX", "EX", expireTime); + // OK null + if (Objects.isNull(result)) { + throw new RuntimeException("操作太频繁,等一分钟在操作"); + } + try { + // do something + } finally { + // 判断加锁与解锁是不是同一个客户端,防止误解锁 + // 通过watch+事务,实现乐观锁,尝试删除key;删除失败说明自己的锁已经过期 + while (true) { + // watch监控key + jedis.watch(lockKey); + String redisLockValue = jedis.get(lockKey); + if (randomId.equals(redisLockValue)) { + Transaction tx = jedis.multi(); + tx.del(lockKey); + // 事务发现watch的key对应value发生变化,del会执行失败,就不会释放别人的锁了 + List execResult = tx.exec(); + if (execResult == null) { + continue; + } + } + jedis.unwatch(); + break; + } + jedis.close(); + } + } + +} \ No newline at end of file diff --git a/distributed/lock/jedis/src/main/java/cn/cunchang/lock/RedisWithReentrantLock.java b/distributed/lock/jedis/src/main/java/cn/cunchang/lock/RedisWithReentrantLock.java new file mode 100644 index 00000000..619ef64a --- /dev/null +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/lock/RedisWithReentrantLock.java @@ -0,0 +1,81 @@ +package cn.cunchang.lock; + +import cn.cunchang.JedisUtil; +import redis.clients.jedis.Jedis; +import java.util.HashMap; +import java.util.Map; + +//redis可重入锁,java实现 +public class RedisWithReentrantLock { + /* + *ThreadLocal是一个关于创建线程局部变量的类。 + *通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。 + * 而使用ThreadLocal创建的变量只能被当前线程访问,其他线程则无法访问和修改。 + */ + private ThreadLocal> lockers = new ThreadLocal<>(); + + private Jedis jedis; + + public RedisWithReentrantLock(Jedis jedis) { + this.jedis = jedis; + } + + private boolean _lock(String key){ + //使用 set ket value ex number nx 指令上锁(“给萝卜占个坑”) + return jedis.set(key , "","nx" , "ex" ,5L) != null; + } + + private void _unlock(String key){ + jedis.del(key); + } + + private Map currentLockers(){ + Map refs = lockers.get(); + if (refs != null){ + return refs; + } + lockers.set(new HashMap<>()); + return lockers.get(); + } + + public boolean lock(String key ){ + Map refs = currentLockers(); + Integer refCnt = refs.get(key); + if (refCnt != null){ //如果加过锁 + refs.put(key , refCnt + 1); //那就在threadlocal再加一把锁 + return true; + } + boolean ok = this._lock(key); //这里是没加过锁,那就进行加锁 + if (!ok){ + return false; //加锁不成功,返回false + } + refs.put(key , 1 ); //加锁成功,则在threalocal里面加上加锁信息 + return true; + } + + public boolean unlock(String key){ + Map refs = currentLockers(); + Integer refCnt = refs.get(key); + if (refCnt == null){ //如果没有加锁的对象,那就不需要解锁 + return false; + } + refCnt -= 1; //如果有加锁的对象,那就去掉一层锁 + if (refCnt > 0 ){ + refs.put(key , refCnt); //更新threadlocal对象信息 + }else { //如果刚才减锁的对象只有一层锁,减一之后就没有锁了,那么就把threalocal里面的对象移除 + refs.remove(key); + this._unlock(key); + } + return true; + } + + public static void main(String[] args) { + Jedis jedis = JedisUtil.getJedis(); + RedisWithReentrantLock redis = new RedisWithReentrantLock(jedis); + System.out.println(redis.lock("codehole")); + System.out.println(redis.lock("codehole")); + System.out.println(redis.unlock("codehole")); + System.out.println(redis.unlock("codehole")); + } +} + diff --git a/distributed/lock/jedis/src/main/java/cn/cunchang/lock/real/Client.java b/distributed/lock/jedis/src/main/java/cn/cunchang/lock/real/Client.java new file mode 100644 index 00000000..9f5b324c --- /dev/null +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/lock/real/Client.java @@ -0,0 +1,23 @@ +package cn.cunchang.lock.real; + +import cn.cunchang.JedisUtil; + +/** + * @author cunchang + */ +public class Client { + + public static void main(String[] args) { + // 校验参数或者干了什么 + LockUtil.wrongLock3_2(JedisUtil.getJedis(),"stock_lock_key",100, new CodeBlock() { + @Override + public void operatingSharedResource() { + // 查库存 + // 库存-1 + // 更新库存 + } + }); + // 封装结果或者干了什么 + } + +} diff --git a/distributed/lock/jedis/src/main/java/cn/cunchang/lock/real/CodeBlock.java b/distributed/lock/jedis/src/main/java/cn/cunchang/lock/real/CodeBlock.java new file mode 100644 index 00000000..0cd4a235 --- /dev/null +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/lock/real/CodeBlock.java @@ -0,0 +1,15 @@ +package cn.cunchang.lock.real; + +/** + * 代码块 + * + * @author cunchang + */ +public interface CodeBlock { + + /** + * 操作共享资源 + */ + void operatingSharedResource(); + +} diff --git a/distributed/lock/jedis/src/main/java/cn/cunchang/lock/real/LockUtil.java b/distributed/lock/jedis/src/main/java/cn/cunchang/lock/real/LockUtil.java new file mode 100644 index 00000000..bdc3629d --- /dev/null +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/lock/real/LockUtil.java @@ -0,0 +1,128 @@ +package cn.cunchang.lock.real; + +import redis.clients.jedis.Jedis; + +import java.util.Objects; + +public class LockUtil { + + + /** + * 问题:死锁 + * 解决:需要设置过期时间,自动释放锁 + * + * @param jedis Redis客户端 + * @param lockKey set指令的key + * @param codeBlock 代码块 + */ + public static void wrongLock1(Jedis jedis, String lockKey, CodeBlock codeBlock) { + Long result = jedis.setnx(lockKey, "lockValue"); + if (result == 0L) { + throw new RuntimeException("操作太频繁,等一分钟在操作"); + } + try { + codeBlock.operatingSharedResource(); + } finally { + jedis.del(lockKey); + jedis.close(); + } + } + + /** + * 处理wrongLock1的问题 + *

+ * 问题:非原子操作,死锁 + * 解决: + * - 原生set + * - lua + * - 事务 + * + * @param jedis Redis客户端 + * @param lockKey set指令的key + * @param expireTime 超期时间 + */ + public static void wrongLock2(Jedis jedis, String lockKey, int expireTime, CodeBlock codeBlock) { + Long result = jedis.setnx(lockKey, "lockValue"); + if (result == 0L) { + throw new RuntimeException("操作太频繁,等一分钟在操作"); + } + try { + // wrong: setnx+expire非原子操作(若程序在这里突然所属进程崩溃、机器宕机等,无法释放锁,将发生死锁) + jedis.expire(lockKey, expireTime); + codeBlock.operatingSharedResource(); + } finally { + jedis.del(lockKey); + jedis.close(); + } + } + + //设置锁的lua脚本 + static String SETNX_EXPIRE_SCRIPT = "if redis.call('setnx', KEYS[1], KEYS[2]) == 1 then\n" + + "return redis.call('expire', KEYS[1], KEYS[3]);\n" + + "end\n" + + "return nil;"; + + static String RELEASE_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then\n" + + " return redis.call('del', KEYS[1]);\n" + + " else return 0 end"; + + static String SETNX_EXPIRE_SCRIPT2 = + "if redis.call('setnx', KEYS[1], KEYS[2]) == 1 then return redis.call('expire', KEYS[1], KEYS[3]); end return nil;"; + + static String RELEASE_SCRIPT2 = + "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]); else return 0 end"; + + + /** + * 问题:锁错误释放 + * 解决:value设置随机数,获取lockkey对应的value,判断一下value是否相等 + * + * @param jedis Redis客户端 + * @param lockKey set指令的key + * @param expireTime 超期时间 秒 + */ + public static void wrongLock3_1(Jedis jedis, String lockKey, int expireTime, CodeBlock codeBlock) { + Object result = jedis.set(lockKey, "lockValue", "NX", "EX", expireTime); + + if (Objects.isNull(result)) { + throw new RuntimeException("操作太频繁,等一分钟在操作"); + } + try { + // do something + // wrong : + // do something 执行超过锁过期时间,锁过期释放 + // do something 执行完毕后,del key,导致锁错误释放 + codeBlock.operatingSharedResource(); + } finally { + jedis.del(lockKey); + jedis.close(); + } + } + + /** + * 问题:锁错误释放 + * 解决:value设置随机数,获取lockkey对应的value,判断一下value是否相等 + * + * @param jedis Redis客户端 + * @param lockKey set指令的key + * @param expireTime 超期时间 + */ + public static void wrongLock3_2(Jedis jedis, String lockKey, int expireTime, CodeBlock codeBlock) { + Object result = jedis.eval(SETNX_EXPIRE_SCRIPT, 3, lockKey, "lockValue", Integer.toString(expireTime)); + + if (Objects.isNull(result)) { + throw new RuntimeException("操作太频繁,等一分钟在操作"); + } + try { + // do something + // wrong : + // do something 执行超过锁过期时间,锁过期释放 + // do something 执行完毕后,del key,导致锁错误释放 + codeBlock.operatingSharedResource(); + } finally { + jedis.del(lockKey); + jedis.close(); + } + } + +} diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/partition/PartitionTest.java b/distributed/lock/jedis/src/main/java/cn/cunchang/partition/PartitionTest.java similarity index 98% rename from database/redis/src/main/java/cn/lastwhisper/redis/partition/PartitionTest.java rename to distributed/lock/jedis/src/main/java/cn/cunchang/partition/PartitionTest.java index cb80e748..e9e304f9 100644 --- a/database/redis/src/main/java/cn/lastwhisper/redis/partition/PartitionTest.java +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/partition/PartitionTest.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.redis.partition; +package cn.cunchang.partition; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -7,7 +7,7 @@ /** * hash分区 迁移率 - * @author lastwhisper + * @author cunchang */ public class PartitionTest { private final static Object value = new Object(); diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/pipeline/PipelineTest.java b/distributed/lock/jedis/src/main/java/cn/cunchang/pipeline/PipelineTest.java similarity index 95% rename from database/redis/src/main/java/cn/lastwhisper/redis/pipeline/PipelineTest.java rename to distributed/lock/jedis/src/main/java/cn/cunchang/pipeline/PipelineTest.java index fd6cd57a..33515f51 100644 --- a/database/redis/src/main/java/cn/lastwhisper/redis/pipeline/PipelineTest.java +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/pipeline/PipelineTest.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.redis.pipeline; +package cn.cunchang.pipeline; import org.junit.Test; import redis.clients.jedis.Jedis; @@ -6,7 +6,7 @@ /** * 流水线 - * @author lastwhisper + * @author cunchang */ public class PipelineTest { //没有使用pipieline的情况下 diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/publishersubscriber/PublisherTest.java b/distributed/lock/jedis/src/main/java/cn/cunchang/publishersubscriber/PublisherTest.java similarity index 82% rename from database/redis/src/main/java/cn/lastwhisper/redis/publishersubscriber/PublisherTest.java rename to distributed/lock/jedis/src/main/java/cn/cunchang/publishersubscriber/PublisherTest.java index c25f9321..97812bfc 100644 --- a/database/redis/src/main/java/cn/lastwhisper/redis/publishersubscriber/PublisherTest.java +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/publishersubscriber/PublisherTest.java @@ -1,10 +1,10 @@ -package cn.lastwhisper.redis.publishersubscriber; +package cn.cunchang.publishersubscriber; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPubSub; /** - * @author lastwhisper + * @author cunchang */ public class PublisherTest { //发布 diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/publishersubscriber/SubscriberTest.java b/distributed/lock/jedis/src/main/java/cn/cunchang/publishersubscriber/SubscriberTest.java similarity index 87% rename from database/redis/src/main/java/cn/lastwhisper/redis/publishersubscriber/SubscriberTest.java rename to distributed/lock/jedis/src/main/java/cn/cunchang/publishersubscriber/SubscriberTest.java index b76632ab..41dc69ce 100644 --- a/database/redis/src/main/java/cn/lastwhisper/redis/publishersubscriber/SubscriberTest.java +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/publishersubscriber/SubscriberTest.java @@ -1,10 +1,10 @@ -package cn.lastwhisper.redis.publishersubscriber; +package cn.cunchang.publishersubscriber; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPubSub; /** - * @author lastwhisper + * @author cunchang */ public class SubscriberTest { //订阅 diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/sentinel/SentinelTest.java b/distributed/lock/jedis/src/main/java/cn/cunchang/sentinel/SentinelTest.java similarity index 96% rename from database/redis/src/main/java/cn/lastwhisper/redis/sentinel/SentinelTest.java rename to distributed/lock/jedis/src/main/java/cn/cunchang/sentinel/SentinelTest.java index f4dd2131..c0efbcb9 100644 --- a/database/redis/src/main/java/cn/lastwhisper/redis/sentinel/SentinelTest.java +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/sentinel/SentinelTest.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.redis.sentinel; +package cn.cunchang.sentinel; import org.junit.Before; import org.junit.Test; @@ -12,7 +12,7 @@ import java.util.concurrent.TimeUnit; /** - * @author lastwhisper + * @author cunchang */ public class SentinelTest { private JedisSentinelPool sentinelPool; diff --git a/database/redis/src/main/java/cn/lastwhisper/redis/transaction/TransactionTest.java b/distributed/lock/jedis/src/main/java/cn/cunchang/transaction/TransactionTest.java similarity index 79% rename from database/redis/src/main/java/cn/lastwhisper/redis/transaction/TransactionTest.java rename to distributed/lock/jedis/src/main/java/cn/cunchang/transaction/TransactionTest.java index 8eb3fde8..f3a5f6ed 100644 --- a/database/redis/src/main/java/cn/lastwhisper/redis/transaction/TransactionTest.java +++ b/distributed/lock/jedis/src/main/java/cn/cunchang/transaction/TransactionTest.java @@ -1,5 +1,6 @@ -package cn.lastwhisper.redis.transaction; +package cn.cunchang.transaction; +import cn.cunchang.JedisUtil; import redis.clients.jedis.Jedis; import redis.clients.jedis.Transaction; @@ -7,13 +8,14 @@ /** * redis事务测试 - * @author lastwhisper + * @author cunchang */ public class TransactionTest { + public static void main(String[] args) { - Jedis jedis = new Jedis("192.168.108.131", 7000); + Jedis jedis = JedisUtil.getJedis(); String userId = "abc"; - String key = keyFor(userId); + String key = buildKey(userId); jedis.setnx(key, String.valueOf(5)); // setnx 做初始化 System.out.println(doubleAccount(jedis, userId)); jedis.close(); @@ -23,7 +25,7 @@ public static void main(String[] args) { * */ public static int doubleAccount(Jedis jedis, String userId) { - String key = keyFor(userId); + String key = buildKey(userId); while (true) { jedis.watch(key); int value = Integer.parseInt(jedis.get(key)); @@ -38,7 +40,7 @@ public static int doubleAccount(Jedis jedis, String userId) { return Integer.parseInt(jedis.get(key)); // 重新获取余额 } - public static String keyFor(String userId) { + public static String buildKey(String userId) { return String.format("account_{}", userId); } } diff --git a/distributed/lock/jedis/src/main/resources/Setnx_Expire_Srcipt.lua b/distributed/lock/jedis/src/main/resources/Setnx_Expire_Srcipt.lua new file mode 100644 index 00000000..d6dbab39 --- /dev/null +++ b/distributed/lock/jedis/src/main/resources/Setnx_Expire_Srcipt.lua @@ -0,0 +1,4 @@ +if redis.call('setnx', KEYS[1], KEYS[2]) == 1 + then return redis.call('expire', KEYS[1], KEYS[3]); +end + return nil; \ No newline at end of file diff --git a/distributed/lock/redisson/pom.xml b/distributed/lock/redisson/pom.xml new file mode 100644 index 00000000..19f53d6e --- /dev/null +++ b/distributed/lock/redisson/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + cn.cunchang + redisson + 1.0-SNAPSHOT + redisson + + + + + + org.redisson + redisson + 3.13.0 + + + + org.slf4j + slf4j-simple + 1.7.25 + + + + com.alibaba + fastjson + 1.2.56 + + + + junit + junit + 4.12 + + + + \ No newline at end of file diff --git a/distributed/lock/redisson/src/main/java/cn/cunchang/RedissonUtil.java b/distributed/lock/redisson/src/main/java/cn/cunchang/RedissonUtil.java new file mode 100644 index 00000000..f8e66a8a --- /dev/null +++ b/distributed/lock/redisson/src/main/java/cn/cunchang/RedissonUtil.java @@ -0,0 +1,37 @@ +package cn.cunchang; + +import org.redisson.Redisson; +import org.redisson.api.RedissonClient; +import org.redisson.client.codec.Codec; +import org.redisson.config.Config; + +public class RedissonUtil { + + public static RedissonClient getRedissonClient() { + Config config = new Config(); + try { + config.setCodec((Codec) Class.forName("org.redisson.codec.JsonJacksonCodec").newInstance()); + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { + e.printStackTrace(); + } + config.useSingleServer().setAddress("redis://127.0.0.1:6379"); + + RedissonClient redisson = Redisson.create(config); + return redisson; + } + + public static RedissonClient getRedissonClient(long watchDogTime) { + Config config = new Config(); + config.setLockWatchdogTimeout(watchDogTime); +// try { +// config.setCodec((Codec) Class.forName("org.redisson.codec.JsonJacksonCodec").newInstance()); +// } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { +// e.printStackTrace(); +// } + config.useSingleServer().setAddress("redis://127.0.0.1:6379"); + + RedissonClient redisson = Redisson.create(config); + return redisson; + } + +} diff --git a/distributed/lock/redisson/src/main/java/cn/cunchang/lock/DemoMain.java b/distributed/lock/redisson/src/main/java/cn/cunchang/lock/DemoMain.java new file mode 100644 index 00000000..6e1ff5b9 --- /dev/null +++ b/distributed/lock/redisson/src/main/java/cn/cunchang/lock/DemoMain.java @@ -0,0 +1,103 @@ +package cn.cunchang.lock; + +import cn.cunchang.RedissonUtil; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; + +import java.util.concurrent.CountDownLatch; + +public class DemoMain { + + private volatile static boolean flag = false; + + public static void main(String[] args) throws Exception { + + RedissonClient redisson = RedissonUtil.getRedissonClient(); + + CountDownLatch countDownLatch = new CountDownLatch(3); + + Thread thread1 = new Thread(new Runnable() { + @Override + public void run() { + RLock lock = redisson.getLock("myLock"); + try { + lock.lock(); + System.out.println("t1 lock!!!+id:" + Thread.currentThread().getId()); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + while (flag) { + int i = 1; + } + System.out.println("t1 debug!!!+id:" + Thread.currentThread().getId()); + } finally { + lock.unlock(); + countDownLatch.countDown(); + } + } + }); + + Thread thread2 = new Thread(new Runnable() { + @Override + public void run() { + RLock lock = redisson.getLock("myLock"); + try { + lock.lock(); + System.out.println("t2 lock!!!+id:" + Thread.currentThread().getId()); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + while (flag) { + int i = 1; + } + System.out.println("t2 debug!!!+id:" + Thread.currentThread().getId()); + } finally { + lock.unlock(); + countDownLatch.countDown(); + } + } + }); + + Thread thread3 = new Thread(new Runnable() { + @Override + public void run() { + RLock lock = redisson.getLock("myLock"); + try { + lock.lock(); + System.out.println("t2 lock!!!+id:" + Thread.currentThread().getId()); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + while (flag) { + int i = 1; + } + System.out.println("t2 debug!!!+id:" + Thread.currentThread().getId()); + } finally { + lock.unlock(); + countDownLatch.countDown(); + } + } + }); + + + thread1.start(); + thread2.start(); + thread3.start(); + + countDownLatch.await(); + redisson.shutdown(); + } + +} \ No newline at end of file diff --git a/distributed/lock/redisson/src/main/java/cn/cunchang/lock/LockDemo.java b/distributed/lock/redisson/src/main/java/cn/cunchang/lock/LockDemo.java new file mode 100644 index 00000000..b15f969d --- /dev/null +++ b/distributed/lock/redisson/src/main/java/cn/cunchang/lock/LockDemo.java @@ -0,0 +1,46 @@ +package cn.cunchang.lock; + +import cn.cunchang.RedissonUtil; +import org.redisson.api.RBucket; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; + +public class LockDemo { + + static long doSomethingTime = 20; + /** + * + * 每隔 leaseRenewalTime/3 就会进行续租,每次续租 leaseRenewalTime 毫秒 + */ + static long leaseRenewalTime = 9 * 1000; + + /** + * lock一直获取锁,直到能获取 + * + */ + public static void main(String[] args) { + RedissonClient redisson = RedissonUtil.getRedissonClient(leaseRenewalTime); + RLock lock = redisson.getLock("myLock"); + RBucket rBucket = redisson.getBucket("myLock"); + try { + lock.lock(); + long ttl = rBucket.remainTimeToLive(); + System.out.println("lock | lockkey:myLock,ttl:" + ttl); + for (int i = 1; i <= doSomethingTime; i++) { + Thread.sleep(995L); + ttl = rBucket.remainTimeToLive(); + System.out.println("do something " + i + " 秒 | lockkey:myLock,ttl:" + ttl); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (lock.isHeldByCurrentThread() && lock.isLocked()) { + lock.unlock(); + long ttl = rBucket.remainTimeToLive(); + System.out.println("unlock lockkey:myLock,ttl:" + ttl); + } + redisson.shutdown(); + } + } + +} diff --git a/distributed/lock/redisson/src/main/java/cn/cunchang/lock/MultiLockDemo.java b/distributed/lock/redisson/src/main/java/cn/cunchang/lock/MultiLockDemo.java new file mode 100644 index 00000000..85ef4c83 --- /dev/null +++ b/distributed/lock/redisson/src/main/java/cn/cunchang/lock/MultiLockDemo.java @@ -0,0 +1,53 @@ +package cn.cunchang.lock; + +import cn.cunchang.RedissonUtil; +import org.redisson.RedissonMultiLock; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; + +public class MultiLockDemo { + + static long doSomethingTime = 20; + + static long watchDogTime = 10 * 1000; + + /** + * 不设置过期时间有watch dog续租 + * + * @param args + */ + public static void main(String[] args) { + RedissonClient redissonInstance1 = RedissonUtil.getRedissonClient(watchDogTime); + RedissonClient redissonInstance2 = RedissonUtil.getRedissonClient(watchDogTime); + RedissonClient redissonInstance3 = RedissonUtil.getRedissonClient(watchDogTime); + + RLock lock1 = redissonInstance1.getLock("lock1"); + RLock lock2 = redissonInstance2.getLock("lock2"); + RLock lock3 = redissonInstance3.getLock("lock3"); + + RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3); + try { + // 同时加锁:lock1 lock2 lock3 + // 所有的锁都上锁成功才算成功。 + lock.lock(); +// rLock.lock(10, TimeUnit.SECONDS); + System.out.println("lock -->lock1 lock2 lock3"); + for (int i = 1; i <= doSomethingTime; i++) { + Thread.sleep(1000L); + System.out.println("do something " + i + " 秒..."); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + // lock.isHeldByCurrentThread() =》java.lang.UnsupportedOperationException + // lock.isLocked() =》java.lang.UnsupportedOperationException + System.out.println("unlock -->lock1 lock2 lock3"); + lock.unlock(); + redissonInstance1.shutdown(); + redissonInstance2.shutdown(); + redissonInstance3.shutdown(); + } + + } + +} diff --git a/distributed/lock/redisson/src/main/java/cn/cunchang/lock/RedLockDemo.java b/distributed/lock/redisson/src/main/java/cn/cunchang/lock/RedLockDemo.java new file mode 100644 index 00000000..57a592ca --- /dev/null +++ b/distributed/lock/redisson/src/main/java/cn/cunchang/lock/RedLockDemo.java @@ -0,0 +1,95 @@ +package cn.cunchang.lock; + +import cn.cunchang.RedissonUtil; +import org.redisson.RedissonRedLock; +import org.redisson.api.RBucket; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; + +public class RedLockDemo { + + static long doSomethingTime = 10; + + static long watchDogTime = 9 * 1000; + + /** + * 不设置过期时间有watch dog续租 + * + * @param args + */ + public static void main(String[] args) { + // 5个完全互相独立,不存在主从复制或者其他集群协调机制的 Redis 实例 + RedissonClient redissonInstance1 = RedissonUtil.getRedissonClient(watchDogTime); + RedissonClient redissonInstance2 = RedissonUtil.getRedissonClient(watchDogTime); + RedissonClient redissonInstance3 = RedissonUtil.getRedissonClient(watchDogTime); + RedissonClient redissonInstance4 = RedissonUtil.getRedissonClient(watchDogTime); + RedissonClient redissonInstance5 = RedissonUtil.getRedissonClient(watchDogTime); + + RLock lock1 = redissonInstance1.getLock("lock1"); + RLock lock2 = redissonInstance2.getLock("lock2"); + RLock lock3 = redissonInstance3.getLock("lock3"); + RLock lock4 = redissonInstance4.getLock("lock4"); + RLock lock5 = redissonInstance5.getLock("lock5"); + + RBucket rBucket1 = redissonInstance1.getBucket("lock1"); + RBucket rBucket2 = redissonInstance1.getBucket("lock2"); + RBucket rBucket3 = redissonInstance1.getBucket("lock3"); + RBucket rBucket4 = redissonInstance1.getBucket("lock4"); + RBucket rBucket5 = redissonInstance1.getBucket("lock5"); + + RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3, lock4, lock5); + try { + // 同时加锁:lock1, lock2, lock3, lock4, lock5 + // 红锁在(N/2 +1)个节点上加锁成功就算成功。 + System.out.println("pre lock -->" + + "\tlock1,ttl:" + rBucket1.remainTimeToLive() + + "\tlock2,ttl:" + rBucket2.remainTimeToLive() + + "\tlock3,ttl:" + rBucket3.remainTimeToLive() + + "\tlock4,ttl:" + rBucket4.remainTimeToLive() + + "\tlock5,ttl:" + rBucket5.remainTimeToLive() + ); + boolean falg = lock.tryLock(); + if (!falg) { + System.out.println("lock fail"); + return; + } + System.out.println("lock success -->" + + "\tlock1,ttl:" + rBucket1.remainTimeToLive() + + "\tlock2,ttl:" + rBucket2.remainTimeToLive() + + "\tlock3,ttl:" + rBucket3.remainTimeToLive() + + "\tlock4,ttl:" + rBucket4.remainTimeToLive() + + "\tlock5,ttl:" + rBucket5.remainTimeToLive() + ); + for (int i = 1; i <= doSomethingTime; i++) { + Thread.sleep(995L); + System.out.println("do something " + i + " 秒 | " + + "\tlock1,ttl:" + rBucket1.remainTimeToLive() + + "\tlock2,ttl:" + rBucket2.remainTimeToLive() + + "\tlock3,ttl:" + rBucket3.remainTimeToLive() + + "\tlock4,ttl:" + rBucket4.remainTimeToLive() + + "\tlock5,ttl:" + rBucket5.remainTimeToLive() + ); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + // lock.isHeldByCurrentThread() =》java.lang.UnsupportedOperationException + // lock.isLocked() =》java.lang.UnsupportedOperationException + System.out.println("unlock -->" + + "\tlock1,ttl:" + rBucket1.remainTimeToLive() + + "\tlock2,ttl:" + rBucket2.remainTimeToLive() + + "\tlock3,ttl:" + rBucket3.remainTimeToLive() + + "\tlock4,ttl:" + rBucket4.remainTimeToLive() + + "\tlock5,ttl:" + rBucket5.remainTimeToLive() + ); + lock.unlock(); + redissonInstance1.shutdown(); + redissonInstance2.shutdown(); + redissonInstance3.shutdown(); + redissonInstance4.shutdown(); + redissonInstance5.shutdown(); + } + } + + +} diff --git a/distributed/lock/redisson/src/main/java/cn/cunchang/lock/TryLockDemo.java b/distributed/lock/redisson/src/main/java/cn/cunchang/lock/TryLockDemo.java new file mode 100644 index 00000000..a6a86fa7 --- /dev/null +++ b/distributed/lock/redisson/src/main/java/cn/cunchang/lock/TryLockDemo.java @@ -0,0 +1,56 @@ +package cn.cunchang.lock; + +import cn.cunchang.RedissonUtil; +import org.redisson.api.RBucket; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; + +import java.util.concurrent.TimeUnit; + +public class TryLockDemo { + + static long doSomethingTime = 300L; + // 锁租约时间 + static long leaseTime = 10L; + + /** + * tryLock 尝试获取锁 + */ + public static void main(String[] args) { + RedissonClient redisson = RedissonUtil.getRedissonClient(); + RLock lock = redisson.getLock("myLock"); + RBucket rBucket = redisson.getBucket("myLock"); + try { + boolean lockFlag = false; + // 无租锁时间,锁会自动续租 + lockFlag = lock.tryLock(); + // 等待0秒,租10秒,锁不会自动续租 +// lockFlag = lock.tryLock(0L, leaseTime, TimeUnit.SECONDS); + if (lockFlag) { + long ttl = rBucket.remainTimeToLive(); + System.out.println("lock | lockkey:myLock,ttl:" + ttl); + for (int i = 1; i <= doSomethingTime; i++) { + Thread.sleep(995L); + ttl = rBucket.remainTimeToLive(); + System.out.println("do something " + i + " 秒 | lockkey:myLock,ttl:" + ttl); + } + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (lock.isHeldByCurrentThread() && lock.isLocked()) { + lock.unlock(); + long ttl = rBucket.remainTimeToLive(); + System.out.println("unlock lockkey:myLock,ttl:" + ttl); + } + redisson.shutdown(); + } +// try { +// Thread.sleep(10000000000L); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } + } + +} diff --git a/distributed/lock/redisson/src/main/java/cn/cunchang/lock/test/ThreadGcTest.java b/distributed/lock/redisson/src/main/java/cn/cunchang/lock/test/ThreadGcTest.java new file mode 100644 index 00000000..10973cd9 --- /dev/null +++ b/distributed/lock/redisson/src/main/java/cn/cunchang/lock/test/ThreadGcTest.java @@ -0,0 +1,60 @@ +package cn.cunchang.lock.test; + +import cn.cunchang.RedissonUtil; +import org.redisson.api.RBucket; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; + +public class ThreadGcTest { + + /** + * 线程不释放锁,线程被回收后,看门狗不续约 + */ + public static void main(String[] args) { + stackSegement(); + + try { + // 等待stackSegement()执行完成 + Thread.sleep(5000L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + // 回收 new Thread + System.gc(); + System.out.println("回收 new Thread!!!"); + + + try { + Thread.sleep(10000000000L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + private static void stackSegement() { + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + RedissonClient redisson = RedissonUtil.getRedissonClient(); + RLock lock = redisson.getLock("myLock"); + try { + boolean lockFlag; + // 无租锁时间,锁会自动续租 + lockFlag = lock.tryLock(); + if (lockFlag) { + System.out.println("拿到锁"); + } else { + System.out.println("没拿到锁"); + } + + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println("new thread() run方法执行完毕!!!"); + } + }); + thread.start(); + } + +} diff --git a/distributed/mq/rocketmq/rocketmq-api/README.md b/distributed/mq/rocketmq/rocketmq-api/README.md new file mode 100644 index 00000000..31ada97b --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/README.md @@ -0,0 +1,30 @@ + +- quickstart 快速入门,生产者发送消息到 broker,broker push 消息到消费者 +- product.sync 生产者发送同步消息 +- product.async 生产者发送异步消息 +- product.oneway 生产者发送单向消息 +- consumer.pull consumer pull broker +- consumer.push broker push consumer +- consumer.broadcast 消费者广播模式消费 +- consumer.retry 消费者重试消息 +- ordermsg 生产者发送有序消息 + - 消息消费时能按照发送的顺序来消费。例如:一个订单产生了三条消息分别是订单创建、订单付款、订单完成。消费时要按照这个顺序消费才能有意义 +- schedulemsg 生产者发送延时消息 + - 消息消费时能按照发送时设置的延长的时间来消费。例如:电商里,提交了一个订单就可以发送一个延时消息,1h后去检查这个订单的状态,如果还是未付款就取消订单释放库存。 + - rocketmq 的延时消息只能按照18个 level 进行延时,不能指定时间 +- batch 发送批量消息 +- filter broker 端进行的消息过滤 +- transaction 事务消息 + - 事务消息共有三种状态,提交状态、回滚状态、中间状态 + - TransactionStatus.CommitTransaction: 提交事务,它允许消费者消费此消息。 + - TransactionStatus.RollbackTransaction: 回滚事务,它代表该消息将被删除,不允许被消费。 + - TransactionStatus.Unknown: 中间状态,它代表需要检查消息队列来确定状态。 + - + + + + + + + + diff --git a/distributed/mq/rocketmq/rocketmq-api/pom.xml b/distributed/mq/rocketmq/rocketmq-api/pom.xml index 831a5181..aaa9b299 100644 --- a/distributed/mq/rocketmq/rocketmq-api/pom.xml +++ b/distributed/mq/rocketmq/rocketmq-api/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - cn.lastwhisper + cn.cunchang rocketmq-api 1.0-SNAPSHOT diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/batch/Consumer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/batch/Consumer.java new file mode 100644 index 00000000..cbf01c43 --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/batch/Consumer.java @@ -0,0 +1,58 @@ +package cn.cunchang.batch; + +import cn.cunchang.contants.Const; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.remoting.common.RemotingHelper; + +import java.util.List; + +public class Consumer { + + public static void main(String[] args) throws MQClientException { + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(); + + //指定NameServer地址,多个地址以 ; 隔开 + consumer.setNamesrvAddr(Const.NAMESRV_ADDR_SINGLE); + + //CONSUME_FROM_LAST_OFFSET 默认策略,从该队列最尾开始消费,跳过历史消息 + //CONSUME_FROM_FIRST_OFFSET 从队列最开始开始消费,即历史消息(还储存在broker的)全部消费一遍 + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); + consumer.setConsumerGroup("test_quick_consumer_name"); + + //设置consumer所订阅的Topic和Tag,*代表全部的Tag + consumer.subscribe("BatchTest", "*"); + + consumer.registerMessageListener(new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + System.out.printf("\npull 到 %d 条消息",msgs.size()); + for (MessageExt msg : msgs) { + try { + String topic = msg.getTopic(); + String tags = msg.getTags(); + String keys = msg.getKeys(); + + String msgBody = new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET); + System.err.println("消费消息--- topic: " + topic + ",tags: " + tags + ", keys: " + keys + ",body: " + msgBody); + } catch (Exception e) { + e.printStackTrace(); + // broke消息重发 + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + } + } + //消费成功 + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + + consumer.start(); + System.err.println("consumer start..."); + + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/batch/ListSplitter.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/batch/ListSplitter.java new file mode 100644 index 00000000..d7377d3f --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/batch/ListSplitter.java @@ -0,0 +1,75 @@ +package cn.cunchang.batch; + +import org.apache.rocketmq.common.message.Message; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +public class ListSplitter implements Iterator> { + private final int SIZE_LIMIT = 1024 * 1024 *4; + private final List messages; + private int currIndex; + + public ListSplitter(List messages) { + this.messages = messages; + } + + @Override + public boolean hasNext() { + return currIndex < messages.size(); + } + + @Override + public List next() { + // 获取开始切割的消息索引(消息字节小于4MB的消息索引) + int startIndex = getStartIndex(); + // 切割结束位置 + int nextIndex = startIndex; + // 临时存放切割出的消息列表的总字节数 + int totalSize = 0; + // 切割消息列表,从起始位置切割,直到切割出的消息列表的总字节数超过4MB为止 + for (; nextIndex < messages.size() ; nextIndex++) { + // 计算遍历的消息的字节并累加,当超过4MB时退出循环,记录nextIndex;用于切分list + Message message = messages.get(nextIndex); + int tmpSize = calcMessageSize(message); + if (tmpSize + totalSize > SIZE_LIMIT){ + break; + }else { + totalSize += tmpSize; + } + } + List subList = this.messages.subList(startIndex, nextIndex); + // 存放切割结束位置 + currIndex = nextIndex; + return subList; + } + + /** + * 计算开始切割的位置,切割的对象是消息列表,最小粒度就是一个消息对象(一条消息的字节大于4MB不会对该消息对象进行切割) + * 获取起始切割位置就是找到单条消息字节小于4MB的消息索引。对大于4MB的消息跳过。 + */ + private int getStartIndex(){ + // 计算开始索引的消息的字节数 + Message currMessage = messages.get(currIndex); + int tmpSize = calcMessageSize(currMessage); + // 下一个开始位置的消息的字节数不能大于4MB + while (tmpSize > SIZE_LIMIT) { + currIndex ++; + Message message = messages.get(currIndex); + tmpSize = calcMessageSize(message); + } + return currIndex; + } + + private int calcMessageSize(Message message){ + int tmpSize = message.getTopic().length() + message.getBody().length; + Map properties = message.getProperties(); + for (Map.Entry entry : properties.entrySet()) { + tmpSize += entry.getKey().length() + entry.getValue().length(); + } + // 增加日志的开销20字节 + tmpSize = tmpSize+20; + return tmpSize; + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/batch/SimpleBatchProducer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/batch/SimpleBatchProducer.java new file mode 100644 index 00000000..372f6368 --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/batch/SimpleBatchProducer.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cunchang.batch; + +import java.util.ArrayList; +import java.util.List; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.common.message.Message; + +public class SimpleBatchProducer { + + public static void main(String[] args) throws Exception { + DefaultMQProducer producer = new DefaultMQProducer("BatchProducerGroupName"); + producer.setNamesrvAddr("127.0.0.1:9876"); + producer.start(); + + //If you just send messages of no more than 1MiB at a time, it is easy to use batch + //Messages of the same batch should have: same topic, same waitStoreMsgOK and no schedule support + String topic = "BatchTest"; + List messages = new ArrayList<>(); + messages.add(new Message(topic, "Tag", "OrderID001", "Hello world 0".getBytes())); + messages.add(new Message(topic, "Tag", "OrderID002", "Hello world 1".getBytes())); + messages.add(new Message(topic, "Tag", "OrderID003", "Hello world 2".getBytes())); + + producer.send(messages); + System.err.println("SimpleBatchProducer 批量消息发送成功"); + producer.shutdown(); + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/batch/SplitBatchProducer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/batch/SplitBatchProducer.java new file mode 100644 index 00000000..df2e3f7f --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/batch/SplitBatchProducer.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cunchang.batch; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.common.message.Message; + +public class SplitBatchProducer { + + public static void main(String[] args) throws Exception { + DefaultMQProducer producer = new DefaultMQProducer("BatchProducerGroupName"); + producer.setNamesrvAddr("127.0.0.1:9876"); + producer.start(); + + //large batch + String topic = "BatchTest"; + List messages = new ArrayList<>(100 * 1000); + for (int i = 0; i < 100 * 1000; i++) { + messages.add(new Message(topic, "Tag", "OrderID" + i, ("Hello world " + i).getBytes())); + } + + //split the large batch into small ones: + ListSplitter splitter = new ListSplitter(messages); + while (splitter.hasNext()) { + List listItem = splitter.next(); + producer.send(listItem); + } + System.err.println("SplitBatchProducer 批量消息发送成功"); + producer.shutdown(); + } + +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/broadcast/BroadCastConsumer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/broadcast/BroadCastConsumer.java new file mode 100644 index 00000000..2fcb7c74 --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/broadcast/BroadCastConsumer.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cunchang.consumer.broadcast; + +import java.util.List; + +import cn.cunchang.contants.Const; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; + +public class BroadCastConsumer { + + public static void main(String[] args) throws InterruptedException, MQClientException { + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_1"); + consumer.setNamesrvAddr(Const.NAMESRV_ADDR_SINGLE); + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); + // 广播模式消费消息 + consumer.setMessageModel(MessageModel.BROADCASTING); + consumer.subscribe("TopicTest", "TagA || TagC || TagD"); + + consumer.registerMessageListener(new MessageListenerConcurrently() { + + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, + ConsumeConcurrentlyContext context) { + System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + + consumer.start(); + System.out.printf("Broadcast Consumer Started.%n"); + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/pull/PullConsumer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/pull/PullConsumer.java new file mode 100644 index 00000000..41f7a61f --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/pull/PullConsumer.java @@ -0,0 +1,62 @@ +package cn.cunchang.consumer.pull; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import org.apache.rocketmq.client.consumer.DefaultMQPullConsumer; +import org.apache.rocketmq.client.consumer.PullResult; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.message.MessageQueue; + +public class PullConsumer { + private static final Map OFFSE_TABLE = new HashMap(); + + public static void main(String[] args) throws MQClientException { + DefaultMQPullConsumer consumer = new DefaultMQPullConsumer("please_rename_unique_group_name_5"); + + consumer.start(); + + Set mqs = consumer.fetchSubscribeMessageQueues("TopicTest1"); + for (MessageQueue mq : mqs) { + System.out.printf("Consume from the queue: %s%n", mq); + SINGLE_MQ: + while (true) { + try { + PullResult pullResult = + consumer.pullBlockIfNotFound(mq, null, getMessageQueueOffset(mq), 32); + System.out.printf("%s%n", pullResult); + putMessageQueueOffset(mq, pullResult.getNextBeginOffset()); + switch (pullResult.getPullStatus()) { + case FOUND: + break; + case NO_MATCHED_MSG: + break; + case NO_NEW_MSG: + break SINGLE_MQ; + case OFFSET_ILLEGAL: + break; + default: + break; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + consumer.shutdown(); + } + + private static long getMessageQueueOffset(MessageQueue mq) { + Long offset = OFFSE_TABLE.get(mq); + if (offset != null) + return offset; + + return 0; + } + + private static void putMessageQueueOffset(MessageQueue mq, long offset) { + OFFSE_TABLE.put(mq, offset); + } + +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/pull/PullScheduleConsumer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/pull/PullScheduleConsumer.java new file mode 100644 index 00000000..207247b5 --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/pull/PullScheduleConsumer.java @@ -0,0 +1,49 @@ +package cn.cunchang.consumer.pull; + +import org.apache.rocketmq.client.consumer.*; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.message.MessageQueue; +import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; + +public class PullScheduleConsumer { + + public static void main(String[] args) throws MQClientException { + final MQPullConsumerScheduleService scheduleService = new MQPullConsumerScheduleService("GroupName1"); + + scheduleService.setMessageModel(MessageModel.CLUSTERING); + scheduleService.registerPullTaskCallback("TopicTest", new PullTaskCallback() { + + @Override + public void doPullTask(MessageQueue mq, PullTaskContext context) { + MQPullConsumer consumer = context.getPullConsumer(); + try { + + long offset = consumer.fetchConsumeOffset(mq, false); + if (offset < 0) + offset = 0; + + PullResult pullResult = consumer.pull(mq, "*", offset, 32); + System.out.printf("%s%n", offset + "\t" + mq + "\t" + pullResult); + switch (pullResult.getPullStatus()) { + case FOUND: + break; + case NO_MATCHED_MSG: + break; + case NO_NEW_MSG: + case OFFSET_ILLEGAL: + break; + default: + break; + } + consumer.updateConsumeOffset(mq, pullResult.getNextBeginOffset()); + + context.setPullNextDelayTimeMillis(100); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + + scheduleService.start(); + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/push/PushConsumer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/push/PushConsumer.java new file mode 100644 index 00000000..4342aa1f --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/push/PushConsumer.java @@ -0,0 +1,31 @@ +package cn.cunchang.consumer.push; + +import java.util.List; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; +import org.apache.rocketmq.common.message.MessageExt; + +public class PushConsumer { + + public static void main(String[] args) throws InterruptedException, MQClientException { + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer_name_push_test"); + consumer.subscribe("push_test_topic", "*"); + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); + //wrong time format 2017_0422_221800 + consumer.setConsumeTimestamp("20170422221800"); + consumer.registerMessageListener(new MessageListenerConcurrently() { + + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + consumer.start(); + System.out.printf("Consumer Started.%n"); + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/retry/Consumer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/retry/Consumer.java new file mode 100644 index 00000000..1a4e2371 --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/retry/Consumer.java @@ -0,0 +1,73 @@ +package cn.cunchang.consumer.retry; + +import cn.cunchang.contants.Const; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.remoting.common.RemotingHelper; + +import java.util.List; + +public class Consumer { + + + public static void main(String[] args) throws MQClientException { + + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(); + //指定NameServer地址,多个地址以 ; 隔开 + consumer.setNamesrvAddr(Const.NAMESRV_ADDR_SINGLE); + //CONSUME_FROM_LAST_OFFSET 默认策略,从该队列最尾开始消费,跳过历史消息 + //CONSUME_FROM_FIRST_OFFSET 从队列最开始开始消费,即历史消息(还储存在broker的)全部消费一遍 + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); + consumer.setConsumerGroup("test_quick_ms_consumer_name"); + //设置consumer所订阅的Topic和Tag,*代表全部的Tag + consumer.subscribe("test_quick_topic", "*"); + + consumer.registerMessageListener(new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + MessageExt me = msgs.get(0); + try { + String topic = me.getTopic(); + String tags = me.getTags(); + String keys = me.getKeys(); + + // 模拟消息消费失败异常 + //if(keys.equals("key1")) { + // System.err.println("消息消费失败.."); + // int a = 1/0; + //} + + String msgBody = new String(me.getBody(), RemotingHelper.DEFAULT_CHARSET); + System.err.println("topic: " + topic + ",tags: " + tags + ", keys: " + keys + ",body: " + msgBody); + } catch (Exception e) { + e.printStackTrace(); + // 消息重发次数 + int recousumeTimes = me.getReconsumeTimes(); + System.err.println("recousumeTimes: " + recousumeTimes); + if(recousumeTimes == 3) { + /* + * 对于broke消息重发到一定次数的时候 + * 记录日志.... + * 做补偿处理 + */ + System.out.println("消息无法消费 msid="+me.getMsgId()); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + + // broke消息重发 + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + } + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + + consumer.start(); + System.err.println("consumer start..."); + + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/retry/Producer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/retry/Producer.java new file mode 100644 index 00000000..1419294b --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/consumer/retry/Producer.java @@ -0,0 +1,34 @@ +package cn.cunchang.consumer.retry; + +import cn.cunchang.contants.Const; +import org.apache.rocketmq.client.exception.MQBrokerException; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.remoting.exception.RemotingException; + +public class Producer { + + public static void main(String[] args) throws MQClientException, RemotingException, MQBrokerException, InterruptedException { + + DefaultMQProducer producer = new DefaultMQProducer("test_quick_ms_consumer_name"); + + producer.setNamesrvAddr(Const.NAMESRV_ADDR_MASTER_SLAVE); + + producer.start(); + + for (int i = 0; i < 1; i++) { + // 1、创建消息 + Message message = new Message("test_quick_topic", // 主题 + "TagA", // 标签 + "key" + i, // 用户自定义的key ,唯一的标识 + ("Hello RocketMQ" + i).getBytes()); // 消息内容实体(byte[]) + // 2、发送消息 + SendResult sr = producer.send(message); + System.err.println("消息发出:" + sr); + } + producer.shutdown(); + + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/contants/Const.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/contants/Const.java new file mode 100644 index 00000000..9e5a0e4e --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/contants/Const.java @@ -0,0 +1,9 @@ +package cn.cunchang.contants; + +public interface Const { + + String NAMESRV_ADDR_SINGLE = "127.0.0.1:9876"; + + String NAMESRV_ADDR_MASTER_SLAVE = "127.0.0.1:9876;192.168.217.102:9876"; + +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/filter/Consumer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/filter/Consumer.java new file mode 100644 index 00000000..6a0e7fec --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/filter/Consumer.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cunchang.filter; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.MixAll; +import org.apache.rocketmq.common.message.MessageExt; + +public class Consumer { + + public static void main(String[] args) throws InterruptedException, MQClientException, IOException { + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupNamecc4"); + + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + File classFile = new File(classLoader.getResource("MessageFilterImpl.java").getFile()); + + String filterCode = MixAll.file2String(classFile); + consumer.subscribe("TopicTest", "org.apache.rocketmq.example.filter.MessageFilterImpl", + filterCode); + + consumer.registerMessageListener(new MessageListenerConcurrently() { + + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, + ConsumeConcurrentlyContext context) { + System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + + consumer.start(); + + System.out.printf("Consumer Started.%n"); + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/filter/Producer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/filter/Producer.java new file mode 100644 index 00000000..fbda03ae --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/filter/Producer.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cunchang.filter; + +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.remoting.common.RemotingHelper; + +public class Producer { + public static void main(String[] args) throws MQClientException, InterruptedException { + DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName"); + producer.start(); + + try { + for (int i = 0; i < 6000000; i++) { + Message msg = new Message("TopicFilter7", + "TagA", + "OrderID001", + "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET)); + + msg.putUserProperty("SequenceId", String.valueOf(i)); + SendResult sendResult = producer.send(msg); + System.out.printf("%s%n", sendResult); + } + } catch (Exception e) { + e.printStackTrace(); + } + producer.shutdown(); + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/filter/SqlConsumer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/filter/SqlConsumer.java new file mode 100644 index 00000000..d3fc6950 --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/filter/SqlConsumer.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cunchang.filter; + +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.MessageSelector; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.message.MessageExt; + +import java.util.List; + +public class SqlConsumer { + + public static void main(String[] args) { + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_4"); + try { + consumer.subscribe("TopicTest", + MessageSelector.bySql("(TAGS is not null and TAGS in ('TagA', 'TagB'))" + + "and (a is not null and a between 0 3)")); + } catch (MQClientException e) { + e.printStackTrace(); + return; + } + + consumer.registerMessageListener(new MessageListenerConcurrently() { + + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, + ConsumeConcurrentlyContext context) { + System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + + try { + consumer.start(); + } catch (MQClientException e) { + e.printStackTrace(); + return; + } + System.out.printf("Consumer Started.%n"); + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/filter/SqlProducer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/filter/SqlProducer.java new file mode 100644 index 00000000..f77308fa --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/filter/SqlProducer.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cunchang.filter; + +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.remoting.common.RemotingHelper; + +public class SqlProducer { + + public static void main(String[] args) { + DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); + try { + producer.start(); + } catch (MQClientException e) { + e.printStackTrace(); + return; + } + + for (int i = 0; i < 10; i++) { + try { + String tag; + int div = i % 3; + if (div == 0) { + tag = "TagA"; + } else if (div == 1) { + tag = "TagB"; + } else { + tag = "TagC"; + } + Message msg = new Message("TopicTest", + tag, + ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) + ); + msg.putUserProperty("a", String.valueOf(i)); + + SendResult sendResult = producer.send(msg); + System.out.printf("%s%n", sendResult); + } catch (Exception e) { + e.printStackTrace(); + try { + Thread.sleep(1000); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + } + } + producer.shutdown(); + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/ordermsg/ConsumerInOrder.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/ordermsg/ConsumerInOrder.java new file mode 100644 index 00000000..86eda770 --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/ordermsg/ConsumerInOrder.java @@ -0,0 +1,56 @@ +package cn.cunchang.ordermsg; + +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; +import org.apache.rocketmq.common.message.MessageExt; + +import java.util.List; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** +* 顺序消息消费,带事务方式(应用可控制Offset什么时候提交) +*/ +public class ConsumerInOrder { + + public static void main(String[] args) throws Exception { + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("test_quick_consumer_name"); + consumer.setNamesrvAddr("127.0.0.1:9876"); + /** + * 设置Consumer第一次启动是从队列头部开始消费还是队列尾部开始消费
+ * 如果非第一次启动,那么按照上次消费的位置继续消费 + */ + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); + + consumer.subscribe("test_quick_topic", "TagA || TagC || TagD"); + + consumer.registerMessageListener(new MessageListenerOrderly() { + + Random random = new Random(); + + @Override + public ConsumeOrderlyStatus consumeMessage(List msgs, ConsumeOrderlyContext context) { + context.setAutoCommit(true); + for (MessageExt msg : msgs) { + // 可以看到每个queue有唯一的consume线程来消费, 订单对每个queue(分区)有序 + System.out.println("consumeThread=" + Thread.currentThread().getName() + "queueId=" + msg.getQueueId() + ", content:" + new String(msg.getBody())); + } + + try { + //模拟业务逻辑处理中... + TimeUnit.SECONDS.sleep(random.nextInt(10)); + } catch (Exception e) { + e.printStackTrace(); + } + return ConsumeOrderlyStatus.SUCCESS; + } + }); + + consumer.start(); + + System.out.println("Consumer Started."); + } +} \ No newline at end of file diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/ordermsg/Producer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/ordermsg/Producer.java new file mode 100644 index 00000000..bf7f9ecf --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/ordermsg/Producer.java @@ -0,0 +1,153 @@ +package cn.cunchang.ordermsg; + +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.MessageQueueSelector; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.common.message.MessageQueue; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class Producer { + /** + * Producer,发送顺序消息 + */ + public static void main(String[] args) throws Exception { + DefaultMQProducer producer = new DefaultMQProducer(); + producer.setProducerGroup("test_quick_consumer_name"); + producer.setNamesrvAddr("127.0.0.1:9876"); + producer.start(); + + String[] tags = new String[]{"TagA", "TagC", "TagD"}; + + // 订单列表 + List orderList = new Producer().buildOrders(); + + Date date = new Date(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String dateStr = sdf.format(date); + for (int i = 0; i < 10; i++) { + // 加个时间前缀 + String body = dateStr + " Hello RocketMQ " + orderList.get(i); + Message msg = new Message("test_quick_topic", tags[i % tags.length], "KEY" + i, body.getBytes()); + + SendResult sendResult = producer.send(msg, new MessageQueueSelector() { + /** + * 发送消息的队列选择器 + * 控制发送的顺序消息只依次发送到同一个queue中,消费的时候只从这个queue上依次拉取,则就保证了顺序 + * @param mqs + * @param msg + * @param arg + * @return + */ + @Override + public MessageQueue select(List mqs, Message msg, Object arg) { + Long id = (Long) arg; //根据订单id选择发送queue + long index = id % mqs.size(); + return mqs.get((int) index); + } + }, orderList.get(i).getOrderId());//订单id + + System.out.println(String.format("SendResult status:%s, queueId:%d, body:%s", + sendResult.getSendStatus(), + sendResult.getMessageQueue().getQueueId(), + body)); + } + + producer.shutdown(); + } + + /** + * 订单的步骤 + */ + private static class OrderStep { + private long orderId; + private String desc; + + public long getOrderId() { + return orderId; + } + + public void setOrderId(long orderId) { + this.orderId = orderId; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + @Override + public String toString() { + return "OrderStep{" + + "orderId=" + orderId + + ", desc='" + desc + '\'' + + '}'; + } + } + + /** + * 生成模拟订单数据 + */ + private List buildOrders() { + List orderList = new ArrayList(); + + OrderStep orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111039L); + orderDemo.setDesc("创建"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111065L); + orderDemo.setDesc("创建"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111039L); + orderDemo.setDesc("付款"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103117235L); + orderDemo.setDesc("创建"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111065L); + orderDemo.setDesc("付款"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103117235L); + orderDemo.setDesc("付款"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111065L); + orderDemo.setDesc("完成"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111039L); + orderDemo.setDesc("推送"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103117235L); + orderDemo.setDesc("完成"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111039L); + orderDemo.setDesc("完成"); + orderList.add(orderDemo); + + return orderList; + } +} \ No newline at end of file diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/producer/PushConsumer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/producer/PushConsumer.java new file mode 100644 index 00000000..fbdf6d06 --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/producer/PushConsumer.java @@ -0,0 +1,59 @@ +package cn.cunchang.producer; + +import cn.cunchang.contants.Const; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.remoting.common.RemotingHelper; + +import java.util.List; + +public class PushConsumer { + + public static void main(String[] args) throws MQClientException { + + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(); + + //指定NameServer地址,多个地址以 ; 隔开 + consumer.setNamesrvAddr(Const.NAMESRV_ADDR_SINGLE); + + //CONSUME_FROM_LAST_OFFSET 默认策略,从该队列最尾开始消费,跳过历史消息 + //CONSUME_FROM_FIRST_OFFSET 从队列最开始开始消费,即历史消息(还储存在broker的)全部消费一遍 + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); + consumer.setConsumerGroup("test_quick_consumer_name"); + + //设置consumer所订阅的Topic和Tag,*代表全部的Tag + consumer.subscribe("test_quick_topic", "*"); + + consumer.registerMessageListener(new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + System.out.printf("\npull 到 %d 条消息",msgs.size()); + for (MessageExt msg : msgs) { + try { + String topic = msg.getTopic(); + String tags = msg.getTags(); + String keys = msg.getKeys(); + + String msgBody = new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET); + System.err.println("消费消息--- topic: " + topic + ",tags: " + tags + ", keys: " + keys + ",body: " + msgBody); + } catch (Exception e) { + e.printStackTrace(); + // broke消息重发 + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + } + } + //消费成功 + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + + consumer.start(); + System.err.println("consumer start..."); + + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/producer/async/AsyncProducer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/producer/async/AsyncProducer.java new file mode 100644 index 00000000..ab4a8395 --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/producer/async/AsyncProducer.java @@ -0,0 +1,57 @@ +package cn.cunchang.producer.async; + +import cn.cunchang.contants.Const; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.SendCallback; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.CountDownLatch2; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.remoting.common.RemotingHelper; + +import java.util.concurrent.TimeUnit; + +public class AsyncProducer { + /** + * 异步消息通常用在对响应时间敏感的业务场景,即发送端不能容忍长时间地等待Broker的响应。 + * @param args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + // 实例化消息生产者Producer + DefaultMQProducer producer = new DefaultMQProducer("test_quick_producer_name"); + // 设置NameServer的地址 + producer.setNamesrvAddr(Const.NAMESRV_ADDR_SINGLE); + // 启动Producer实例 + producer.start(); + producer.setRetryTimesWhenSendAsyncFailed(0); + + int messageCount = 100; + // 根据消息数量实例化倒计时计算器 + final CountDownLatch2 countDownLatch = new CountDownLatch2(messageCount); + for (int i = 0; i < messageCount; i++) { + final int index = i; + // 创建消息,并指定Topic,Tag和消息体 + Message msg = new Message("test_quick_topic", + "TagA", + "OrderID"+index, + "Hello RocketMQ AsyncProducer".getBytes(RemotingHelper.DEFAULT_CHARSET)); + // SendCallback接收异步返回结果的回调 + producer.send(msg, new SendCallback() { + @Override + public void onSuccess(SendResult sendResult) { + System.out.printf("%-10d onSuccess %s %n", index, + sendResult.getMsgId()); + } + @Override + public void onException(Throwable e) { + System.out.printf("%-10d onException %s %n", index, e); + e.printStackTrace(); + } + }); + } + // 等待5s + countDownLatch.await(5, TimeUnit.SECONDS); + // 如果不再发送消息,关闭Producer实例。 + producer.shutdown(); + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/producer/oneway/OnewayProducer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/producer/oneway/OnewayProducer.java new file mode 100644 index 00000000..56e81f1e --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/producer/oneway/OnewayProducer.java @@ -0,0 +1,36 @@ +package cn.cunchang.producer.oneway; + +import cn.cunchang.contants.Const; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.remoting.common.RemotingHelper; + +public class OnewayProducer { + /** + * 这种方式主要用在不特别关心发送结果的场景,例如日志发送。 + * @param args + * @throws Exception + */ + public static void main(String[] args) throws Exception{ + // 实例化消息生产者Producer + DefaultMQProducer producer = new DefaultMQProducer(); + // 设置NameServer的地址 + producer.setNamesrvAddr(Const.NAMESRV_ADDR_SINGLE); + // 生产者的组名 + producer.setProducerGroup("test_quick_producer_name"); + // 启动Producer实例 + producer.start(); + + for (int i = 0; i < 100; i++) { + //Create a message instance, specifying topic, tag and message body. + Message msg = new Message("test_quick_topic" /* Topic */, + "TagA" /* Tag */, + ("Hello RocketMQ OnewayProducer" + + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ + ); + //Call send message to deliver message to one of brokers. + producer.sendOneway(msg); + } + producer.shutdown(); + } +} \ No newline at end of file diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/producer/sync/SyncProducer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/producer/sync/SyncProducer.java new file mode 100644 index 00000000..18314734 --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/producer/sync/SyncProducer.java @@ -0,0 +1,45 @@ +package cn.cunchang.producer.sync; + +import cn.cunchang.contants.Const; +import org.apache.rocketmq.client.exception.MQBrokerException; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.remoting.exception.RemotingException; + +public class SyncProducer { + + /** + * 这种可靠性同步地发送方式使用的比较广泛,比如:重要的消息通知,短信通知。 + * @param args + * @throws MQClientException + * @throws RemotingException + * @throws MQBrokerException + * @throws InterruptedException + */ + public static void main(String[] args) throws MQClientException, RemotingException, MQBrokerException, InterruptedException { + // 实例化消息生产者Producer + DefaultMQProducer producer = new DefaultMQProducer(); + // 设置NameServer的地址 + producer.setNamesrvAddr(Const.NAMESRV_ADDR_SINGLE); + // 生产者的组名 + producer.setProducerGroup("test_quick_producer_name"); + // 启动Producer实例 + producer.start(); + + for (int i = 0; i < 5; i++) { + // 1、创建消息 + Message message = new Message("test_quick_topic", // 主题 + "TagA", // 标签,用于消息过滤 + "key" + i, // 用户自定义的key ,用于唯一的标识 + ("Hello RocketMQ SyncProducer" + i).getBytes()); // 消息内容实体(byte[]) + // 2、发送消息 + SendResult result = producer.send(message); + System.out.println("发送消息--- MsgId:" + result.getMsgId() + ",发送状态:" + result.getSendStatus()); + } + // 如果不再发送消息,关闭Producer实例。 + producer.shutdown(); + + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/quickstart/Consumer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/quickstart/Consumer.java new file mode 100644 index 00000000..361fa8a8 --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/quickstart/Consumer.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cunchang.quickstart; + +import java.util.List; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; +import org.apache.rocketmq.common.message.MessageExt; + +/** + * This example shows how to subscribe and consume messages using providing {@link DefaultMQPushConsumer}. + */ +public class Consumer { + + public static void main(String[] args) throws InterruptedException, MQClientException { + + /* + * Instantiate with specified consumer group name. + */ + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_4"); + + /* + * Specify name server addresses. + *

+ * + * Alternatively, you may specify name server addresses via exporting environmental variable: NAMESRV_ADDR + *

+         * {@code
+         * consumer.setNamesrvAddr("name-server1-ip:9876;name-server2-ip:9876");
+         * }
+         * 
+ */ + + /* + * Specify where to start in case the specified consumer group is a brand new one. + */ + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); + + /* + * Subscribe one more more topics to consume. + */ + consumer.subscribe("TopicTest", "*"); + + /* + * Register callback to execute on arrival of messages fetched from brokers. + */ + consumer.registerMessageListener(new MessageListenerConcurrently() { + + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, + ConsumeConcurrentlyContext context) { + System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + + /* + * Launch the consumer instance. + */ + consumer.start(); + + System.out.printf("Consumer Started.%n"); + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/quickstart/Producer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/quickstart/Producer.java new file mode 100644 index 00000000..e92dc6da --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/quickstart/Producer.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.cunchang.quickstart; + +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.remoting.common.RemotingHelper; + +/** + * This class demonstrates how to send messages to brokers using provided {@link DefaultMQProducer}. + */ +public class Producer { + public static void main(String[] args) throws MQClientException, InterruptedException { + + /* + * Instantiate with a producer group name. + */ + DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); + + /* + * Specify name server addresses. + *

+ * + * Alternatively, you may specify name server addresses via exporting environmental variable: NAMESRV_ADDR + *

+         * {@code
+         * producer.setNamesrvAddr("name-server1-ip:9876;name-server2-ip:9876");
+         * }
+         * 
+ */ + + /* + * Launch the instance. + */ + producer.start(); + + for (int i = 0; i < 1000; i++) { + try { + + /* + * Create a message instance, specifying topic, tag and message body. + */ + Message msg = new Message("TopicTest" /* Topic */, + "TagA" /* Tag */, + ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ + ); + + /* + * Call send message to deliver message to one of brokers. + */ + SendResult sendResult = producer.send(msg); + + System.out.printf("%s%n", sendResult); + } catch (Exception e) { + e.printStackTrace(); + Thread.sleep(1000); + } + } + + /* + * Shut down once the producer instance is not longer in use. + */ + producer.shutdown(); + } +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/schedulemsg/ScheduledMessageConsumer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/schedulemsg/ScheduledMessageConsumer.java new file mode 100644 index 00000000..d8b5be38 --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/schedulemsg/ScheduledMessageConsumer.java @@ -0,0 +1,32 @@ +package cn.cunchang.schedulemsg; + +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.common.message.MessageExt; + +import java.util.List; + +public class ScheduledMessageConsumer { + public static void main(String[] args) throws Exception { + // 实例化消费者 + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ExampleConsumer"); + consumer.setNamesrvAddr("127.0.0.1:9876"); + // 订阅Topics + consumer.subscribe("test_quick_topic", "*"); + // 注册消息监听者 + consumer.registerMessageListener(new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List messages, ConsumeConcurrentlyContext context) { + for (MessageExt message : messages) { + // Print approximate delay time period + System.out.println("Receive message[msgId=" + message.getMsgId() + "] " + (System.currentTimeMillis() - message.getStoreTimestamp()) + "ms later"); + } + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + // 启动消费者 + consumer.start(); + } +} \ No newline at end of file diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/schedulemsg/ScheduledMessageProducer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/schedulemsg/ScheduledMessageProducer.java new file mode 100644 index 00000000..d1fd9b00 --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/schedulemsg/ScheduledMessageProducer.java @@ -0,0 +1,24 @@ +package cn.cunchang.schedulemsg; + +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.common.message.Message; + +public class ScheduledMessageProducer { + public static void main(String[] args) throws Exception { + // 实例化一个生产者来产生延时消息 + DefaultMQProducer producer = new DefaultMQProducer("ExampleProducerGroup"); + producer.setNamesrvAddr("127.0.0.1:9876"); + // 启动生产者 + producer.start(); + int totalMessagesToSend = 100; + for (int i = 0; i < totalMessagesToSend; i++) { + Message message = new Message("test_quick_topic", ("Hello scheduled message " + i).getBytes()); + // 设置延时等级3,这个消息将在10s之后发送(现在只支持固定的几个时间,详看delayTimeLevel) + message.setDelayTimeLevel(3); + // 发送消息 + producer.send(message); + } + // 关闭生产者 + producer.shutdown(); + } +} \ No newline at end of file diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/transaction/Consumer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/transaction/Consumer.java new file mode 100644 index 00000000..e3a3e37c --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/transaction/Consumer.java @@ -0,0 +1,53 @@ +package cn.cunchang.transaction; + +import cn.cunchang.contants.Const; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.remoting.common.RemotingHelper; + +import java.util.List; + +public class Consumer { + + public static void main(String[] args) throws InterruptedException, MQClientException { + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("transaction_producer_name_test"); + consumer.setNamesrvAddr(Const.NAMESRV_ADDR_SINGLE); + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); + consumer.subscribe("transaction_producer_topic_test", "*"); + + consumer.registerMessageListener(new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + aVoid(msgs); + for (MessageExt msg : msgs) { + try { + String topic = msg.getTopic(); + String tags = msg.getTags(); + String keys = msg.getKeys(); + + String msgBody = new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET); + System.err.println("收到事务消息--- topic: " + topic + ",tags: " + tags + ", keys: " + keys + ",body: " + msgBody); + } catch (Exception e) { + e.printStackTrace(); + // broke消息重发 + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + } + } + //消费成功 + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + consumer.start(); + System.out.printf("tx Consumer Started.%n"); + } + + public static synchronized void aVoid(List msgs){ + System.out.printf("\npull 到 %d 条消息",msgs.size()); + } + +} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/transaction/TransactionListenerImpl.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/transaction/TransactionListenerImpl.java new file mode 100644 index 00000000..2ec611c7 --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/transaction/TransactionListenerImpl.java @@ -0,0 +1,53 @@ +package cn.cunchang.transaction; + +import org.apache.commons.lang3.StringUtils; +import org.apache.rocketmq.client.producer.LocalTransactionState; +import org.apache.rocketmq.client.producer.TransactionListener; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.common.message.MessageExt; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +public class TransactionListenerImpl implements TransactionListener { + + /** + * 执行本地事务 + * + * @param msg + * @param arg 回调参数 + * @return + */ + @Override + public LocalTransactionState executeLocalTransaction(Message msg, Object arg) { + System.err.println("TransactionListenerImpl executeLocalTransaction 异步执行本地事务 msg:" + msg + " arg:" + arg); + String tags = msg.getTags(); + if(StringUtils.contains(tags,"TagA")){ + // 事务提交 + return LocalTransactionState.COMMIT_MESSAGE; + }else if(StringUtils.contains(tags,"TagB")){ + return LocalTransactionState.ROLLBACK_MESSAGE; + }else{ + return LocalTransactionState.UNKNOW; + } + } + + /** + * 本地事务执行返回LocalTransactionState.UNKNOW时进行回查事务状态 + * + * @param msg + * @return + */ + @Override + public LocalTransactionState checkLocalTransaction(MessageExt msg) { + System.err.println("TransactionListenerImpl checkLocalTransaction 回调消息检查 msg:" + msg); + String tags = msg.getTags(); + if(StringUtils.contains(tags,"TagC")){ + return LocalTransactionState.COMMIT_MESSAGE; + }else if(StringUtils.contains(tags,"TagD")){ + return LocalTransactionState.ROLLBACK_MESSAGE; + }else{ + return LocalTransactionState.UNKNOW; + } + } +} \ No newline at end of file diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/transaction/TransactionProducer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/transaction/TransactionProducer.java new file mode 100644 index 00000000..d1ae9952 --- /dev/null +++ b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/cunchang/transaction/TransactionProducer.java @@ -0,0 +1,47 @@ +package cn.cunchang.transaction; + +import cn.cunchang.contants.Const; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.client.producer.TransactionListener; +import org.apache.rocketmq.client.producer.TransactionMQProducer; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.remoting.common.RemotingHelper; + +import java.io.UnsupportedEncodingException; +import java.util.concurrent.*; + +public class TransactionProducer { + public static void main(String[] args) throws MQClientException, InterruptedException { + TransactionListener transactionListener = new TransactionListenerImpl(); + TransactionMQProducer producer = new TransactionMQProducer("transaction_producer_name_test"); + ExecutorService executorService = new ThreadPoolExecutor(2, 5, 100, TimeUnit.SECONDS, new ArrayBlockingQueue(2000), new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread thread = new Thread(r); + thread.setName("client-transaction-msg-check-thread"); + return thread; + } + }); + producer.setNamesrvAddr(Const.NAMESRV_ADDR_SINGLE); + producer.setExecutorService(executorService); + producer.setTransactionListener(transactionListener); + producer.start(); + String[] tags = new String[]{"TagA", "TagB", "TagC", "TagD", "TagE"}; + for (int i = 0; i < 10; i++) { + try { + Message msg = new Message("transaction_producer_topic_test", tags[i % tags.length], "KEY" + i, + ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET)); + SendResult sendResult = producer.sendMessageInTransaction(msg, "我是回调参数,可能会用到"); + System.out.printf("%s%n", sendResult); + Thread.sleep(10); + } catch (MQClientException | UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + for (int i = 0; i < 100000; i++) { + Thread.sleep(1000); + } + producer.shutdown(); + } +} \ No newline at end of file diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/contants/Const.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/contants/Const.java deleted file mode 100644 index ba69b40b..00000000 --- a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/contants/Const.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.lastwhisper.rocketmq.contants; - -public interface Const { - - String NAMESRV_ADDR_SINGLE = "192.168.217.101:9876"; - - String NAMESRV_ADDR_MASTER_SLAVE = "192.168.217.101:9876;192.168.217.102:9876"; - -} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/async/Consumer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/async/Consumer.java deleted file mode 100644 index 2cf6abdc..00000000 --- a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/async/Consumer.java +++ /dev/null @@ -1,66 +0,0 @@ -package cn.lastwhisper.rocketmq.quickstart.async; - -import cn.lastwhisper.rocketmq.contants.Const; -import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; -import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; -import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; -import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; -import org.apache.rocketmq.client.exception.MQClientException; -import org.apache.rocketmq.common.consumer.ConsumeFromWhere; -import org.apache.rocketmq.common.message.MessageExt; -import org.apache.rocketmq.remoting.common.RemotingHelper; - -import java.util.List; - -public class Consumer { - - - public static void main(String[] args) throws MQClientException { - - DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("test_async_producer_name"); - - consumer.setNamesrvAddr(Const.NAMESRV_ADDR_SINGLE); - - consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); - - consumer.subscribe("test_quick_topic", "*"); - - consumer.registerMessageListener(new MessageListenerConcurrently() { - - @Override - public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { - MessageExt me = msgs.get(0); - try { - String topic = me.getTopic(); - String tags = me.getTags(); - String keys = me.getKeys(); - - String msgBody = new String(me.getBody(), RemotingHelper.DEFAULT_CHARSET); - System.err.println("topic: " + topic + ",tags: " + tags + ", keys: " + keys + ",body: " + msgBody); - } catch (Exception e) { - e.printStackTrace(); - // 消息重发次数 - int recousumeTimes = me.getReconsumeTimes(); - System.err.println("recousumeTimes: " + recousumeTimes); - if(recousumeTimes == 3) { - /* - * 对于broke消息重发到一定次数的时候 - * 记录日志.... - * 做补偿处理 - */ - System.out.println("消息无法消费 msid="+me.getMsgId()); - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; - } - - // broke消息重发 - return ConsumeConcurrentlyStatus.RECONSUME_LATER; - } - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; - } - }); - - consumer.start(); - System.err.println("consumer start..."); - - } -} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/async/Producer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/async/Producer.java deleted file mode 100644 index 4f8a1411..00000000 --- a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/async/Producer.java +++ /dev/null @@ -1,49 +0,0 @@ -package cn.lastwhisper.rocketmq.quickstart.async; - -import cn.lastwhisper.rocketmq.contants.Const; -import org.apache.rocketmq.client.exception.MQBrokerException; -import org.apache.rocketmq.client.exception.MQClientException; -import org.apache.rocketmq.client.producer.DefaultMQProducer; -import org.apache.rocketmq.client.producer.SendCallback; -import org.apache.rocketmq.client.producer.SendResult; -import org.apache.rocketmq.common.message.Message; -import org.apache.rocketmq.remoting.exception.RemotingException; - -public class Producer { - - public static void main(String[] args) throws MQClientException, RemotingException, MQBrokerException, InterruptedException { - - DefaultMQProducer producer = new DefaultMQProducer("test_async_producer_name"); - - producer.setNamesrvAddr(Const.NAMESRV_ADDR_SINGLE); - - producer.start(); - - for (int i = 0; i < 5; i++) { - // 1、创建消息 - Message message = new Message("test_quick_topic", // 主题 - "TagA", // 标签 - "key" + i, // 用户自定义的key ,唯一的标识 - ("Hello RocketMQ" + i).getBytes()); // 消息内容实体(byte[]) - // 2、发送消息 - //SendResult sr = producer.send(message); - //System.err.println("消息发出:" + sr); - producer.send(message, new SendCallback() { - @Override - public void onSuccess(SendResult sendResult) { - System.err.println("msgId: " + sendResult.getMsgId() + ", status: " + sendResult.getSendStatus()); - } - - @Override - public void onException(Throwable e) { - e.printStackTrace(); - System.err.println("------发送失败"); - } - }); - - } - - //producer.shutdown(); - - } -} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/ms/Consumer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/ms/Consumer.java deleted file mode 100644 index fad59a22..00000000 --- a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/ms/Consumer.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.lastwhisper.rocketmq.quickstart.ms; - -import cn.lastwhisper.rocketmq.contants.Const; -import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; -import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; -import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; -import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; -import org.apache.rocketmq.client.exception.MQClientException; -import org.apache.rocketmq.common.consumer.ConsumeFromWhere; -import org.apache.rocketmq.common.message.MessageExt; -import org.apache.rocketmq.remoting.common.RemotingHelper; - -import java.util.List; - -public class Consumer { - - - public static void main(String[] args) throws MQClientException { - - DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("test_quick_ms_consumer_name"); - - //consumer.setNamesrvAddr(Const.NAMESRV_ADDR_MASTER_SLAVE); - - consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); - - consumer.subscribe("test_quick_topic", "*"); - - consumer.registerMessageListener(new MessageListenerConcurrently() { - - @Override - public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { - MessageExt me = msgs.get(0); - try { - String topic = me.getTopic(); - String tags = me.getTags(); - String keys = me.getKeys(); - - // 模拟消息消费失败异常 - //if(keys.equals("key1")) { - // System.err.println("消息消费失败.."); - // int a = 1/0; - //} - - String msgBody = new String(me.getBody(), RemotingHelper.DEFAULT_CHARSET); - System.err.println("topic: " + topic + ",tags: " + tags + ", keys: " + keys + ",body: " + msgBody); - } catch (Exception e) { - e.printStackTrace(); - // 消息重发次数 - int recousumeTimes = me.getReconsumeTimes(); - System.err.println("recousumeTimes: " + recousumeTimes); - if(recousumeTimes == 3) { - /* - * 对于broke消息重发到一定次数的时候 - * 记录日志.... - * 做补偿处理 - */ - System.out.println("消息无法消费 msid="+me.getMsgId()); - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; - } - - // broke消息重发 - return ConsumeConcurrentlyStatus.RECONSUME_LATER; - } - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; - } - }); - - consumer.start(); - System.err.println("consumer start..."); - - } -} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/ms/Producer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/ms/Producer.java deleted file mode 100644 index 72fa4766..00000000 --- a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/ms/Producer.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.lastwhisper.rocketmq.quickstart.ms; - -import cn.lastwhisper.rocketmq.contants.Const; -import org.apache.rocketmq.client.exception.MQBrokerException; -import org.apache.rocketmq.client.exception.MQClientException; -import org.apache.rocketmq.client.producer.DefaultMQProducer; -import org.apache.rocketmq.client.producer.SendResult; -import org.apache.rocketmq.common.message.Message; -import org.apache.rocketmq.remoting.exception.RemotingException; - -public class Producer { - - public static void main(String[] args) throws MQClientException, RemotingException, MQBrokerException, InterruptedException { - - DefaultMQProducer producer = new DefaultMQProducer("test_quick_ms_consumer_name"); - - producer.setNamesrvAddr(Const.NAMESRV_ADDR_MASTER_SLAVE); - - producer.start(); - - for (int i = 0; i < 1; i++) { - // 1、创建消息 - Message message = new Message("test_quick_topic", // 主题 - "TagA", // 标签 - "key" + i, // 用户自定义的key ,唯一的标识 - ("Hello RocketMQ" + i).getBytes()); // 消息内容实体(byte[]) - // 2、发送消息 - SendResult sr = producer.send(message); - System.err.println("消息发出:" + sr); - } - producer.shutdown(); - - } -} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/sync/Consumer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/sync/Consumer.java deleted file mode 100644 index a9ab5f0e..00000000 --- a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/sync/Consumer.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.lastwhisper.rocketmq.quickstart.sync; - -import cn.lastwhisper.rocketmq.contants.Const; -import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; -import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; -import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; -import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; -import org.apache.rocketmq.client.exception.MQClientException; -import org.apache.rocketmq.common.consumer.ConsumeFromWhere; -import org.apache.rocketmq.common.message.MessageExt; -import org.apache.rocketmq.remoting.common.RemotingHelper; - -import java.util.List; - -public class Consumer { - - - public static void main(String[] args) throws MQClientException { - - DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("test_quick_consumer_name"); - - consumer.setNamesrvAddr(Const.NAMESRV_ADDR_SINGLE); - - consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); - - consumer.subscribe("test_quick_topic", "*"); - - consumer.registerMessageListener(new MessageListenerConcurrently() { - - @Override - public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { - MessageExt me = msgs.get(0); - try { - String topic = me.getTopic(); - String tags = me.getTags(); - String keys = me.getKeys(); - - // 模拟消息消费失败异常 - if(keys.equals("key1")) { - System.err.println("消息消费失败.."); - int a = 1/0; - } - - String msgBody = new String(me.getBody(), RemotingHelper.DEFAULT_CHARSET); - System.err.println("topic: " + topic + ",tags: " + tags + ", keys: " + keys + ",body: " + msgBody); - } catch (Exception e) { - e.printStackTrace(); - // 消息重发次数 - int recousumeTimes = me.getReconsumeTimes(); - System.err.println("recousumeTimes: " + recousumeTimes); - if(recousumeTimes == 3) { - /* - * 对于broke消息重发到一定次数的时候 - * 记录日志.... - * 做补偿处理 - */ - System.out.println("消息无法消费 msid="+me.getMsgId()); - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; - } - - // broke消息重发 - return ConsumeConcurrentlyStatus.RECONSUME_LATER; - } - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; - } - }); - - consumer.start(); - System.err.println("consumer start..."); - - } -} diff --git a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/sync/Producer.java b/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/sync/Producer.java deleted file mode 100644 index 415b6eec..00000000 --- a/distributed/mq/rocketmq/rocketmq-api/src/main/java/cn/lastwhisper/rocketmq/quickstart/sync/Producer.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.lastwhisper.rocketmq.quickstart.sync; - -import cn.lastwhisper.rocketmq.contants.Const; -import org.apache.rocketmq.client.exception.MQBrokerException; -import org.apache.rocketmq.client.exception.MQClientException; -import org.apache.rocketmq.client.producer.DefaultMQProducer; -import org.apache.rocketmq.client.producer.SendResult; -import org.apache.rocketmq.common.message.Message; -import org.apache.rocketmq.remoting.exception.RemotingException; - -public class Producer { - - public static void main(String[] args) throws MQClientException, RemotingException, MQBrokerException, InterruptedException { - - DefaultMQProducer producer = new DefaultMQProducer("test_quick_producer_name"); - - producer.setNamesrvAddr(Const.NAMESRV_ADDR_SINGLE); - - producer.start(); - - for (int i = 0; i < 5; i++) { - // 1、创建消息 - Message message = new Message("test_quick_topic", // 主题 - "TagA", // 标签 - "key" + i, // 用户自定义的key ,唯一的标识 - ("Hello RocketMQ" + i).getBytes()); // 消息内容实体(byte[]) - // 2、发送消息 - SendResult sr = producer.send(message); - System.err.println("消息发出:" + sr); - } - producer.shutdown(); - - } -} diff --git a/distributed/mq/rocketmq/springboot-rocketmq/pom.xml b/distributed/mq/rocketmq/springboot-rocketmq/pom.xml new file mode 100644 index 00000000..916c2fed --- /dev/null +++ b/distributed/mq/rocketmq/springboot-rocketmq/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + springboot-rocketmq + org.example + 0.0.1 + + + + org.apache.rocketmq + rocketmq-spring-boot-starter + 2.1.1 + + + org.springframework.boot + spring-boot-starter + + + org.springframework + spring-core + + + org.springframework + spring-webmvc + + + + + org.springframework.boot + spring-boot-starter-web + 2.1.6.RELEASE + + + org.springframework.boot + spring-boot-starter-test + 2.1.6.RELEASE + + + io.springfox + springfox-swagger-ui + 2.9.2 + + + io.springfox + springfox-swagger2 + 2.9.2 + + + + \ No newline at end of file diff --git a/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/RocketMQSBApplication.java b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/RocketMQSBApplication.java new file mode 100644 index 00000000..ee55cb04 --- /dev/null +++ b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/RocketMQSBApplication.java @@ -0,0 +1,18 @@ +package com.roy.rocketmq; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author :楼兰 + * @date :Created in 2020/11/28 + * @description: + **/ + +@SpringBootApplication +public class RocketMQSBApplication { + + public static void main(String[] args) { + SpringApplication.run(RocketMQSBApplication.class,args); + } +} diff --git a/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/basic/SpringConsumer.java b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/basic/SpringConsumer.java new file mode 100644 index 00000000..c75e1cd1 --- /dev/null +++ b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/basic/SpringConsumer.java @@ -0,0 +1,21 @@ +package com.roy.rocketmq.basic; + +import org.apache.rocketmq.spring.annotation.ConsumeMode; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.stereotype.Component; + +/** + * 注意下@RocketMQMessageListener这个注解的其他属性 + * @author :楼兰 + * @date :Created in 2020/10/22 + * @description: + **/ +@Component +@RocketMQMessageListener(consumerGroup = "MyConsumerGroup", topic = "TestTopic",consumeMode= ConsumeMode.CONCURRENTLY) +public class SpringConsumer implements RocketMQListener { + @Override + public void onMessage(String message) { + System.out.println("Received message : "+ message); + } +} diff --git a/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/basic/SpringProducer.java b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/basic/SpringProducer.java new file mode 100644 index 00000000..fb8119fd --- /dev/null +++ b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/basic/SpringProducer.java @@ -0,0 +1,46 @@ +package com.roy.rocketmq.basic; + +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.apache.rocketmq.spring.support.RocketMQHeaders; +import org.springframework.messaging.Message; +import org.springframework.messaging.support.MessageBuilder; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * @author :楼兰 + * @date :Created in 2020/10/22 + * @description: + **/ +@Component +public class SpringProducer { + + @Resource + private RocketMQTemplate rocketMQTemplate; + + public void sendMessage(String topic,String msg){ + this.rocketMQTemplate.convertAndSend(topic,msg); + } + + public void sendMessageInTransaction(String topic,String msg) throws InterruptedException { + String[] tags = new String[] {"TagA", "TagB", "TagC", "TagD", "TagE"}; + for (int i = 0; i < 10; i++) { + //尝试在Header中加入一些自定义的属性。 + Message message = MessageBuilder.withPayload(msg) + .setHeader(RocketMQHeaders.TRANSACTION_ID,"TransID_"+i) + //发到事务监听器里后,这个自己设定的TAGS属性会丢失。但是上面那个属性不会丢失。 + .setHeader(RocketMQHeaders.TAGS,tags[i % tags.length]) + //MyProp在事务监听器里也能拿到,为什么就单单这个RocketMQHeaders.TAGS拿不到?这只能去调源码了。 + .setHeader("MyProp","MyProp_"+i) + .build(); + String destination =topic+":"+tags[i % tags.length]; + //这里发送事务消息时,还是会转换成RocketMQ的Message对象,再调用RocketMQ的API完成事务消息机制。 + SendResult sendResult = rocketMQTemplate.sendMessageInTransaction(destination, message,destination); + System.out.printf("%s%n", sendResult); + + Thread.sleep(10); + } + } +} diff --git a/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/config/ExtRocketMQTemplate.java b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/config/ExtRocketMQTemplate.java new file mode 100644 index 00000000..7569c2cf --- /dev/null +++ b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/config/ExtRocketMQTemplate.java @@ -0,0 +1,13 @@ +package com.roy.rocketmq.config; + +import org.apache.rocketmq.spring.annotation.ExtRocketMQTemplateConfiguration; +import org.apache.rocketmq.spring.core.RocketMQTemplate; + +/** + * @author :楼兰 + * @date :Created in 2020/12/4 + * @description: + **/ +@ExtRocketMQTemplateConfiguration() +public class ExtRocketMQTemplate extends RocketMQTemplate { +} diff --git a/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/config/MyTransactionImpl.java b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/config/MyTransactionImpl.java new file mode 100644 index 00000000..8944944b --- /dev/null +++ b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/config/MyTransactionImpl.java @@ -0,0 +1,65 @@ +package com.roy.rocketmq.config; + +import org.apache.commons.lang3.StringUtils; +import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; +import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; +import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState; +import org.apache.rocketmq.spring.support.RocketMQHeaders; +import org.apache.rocketmq.spring.support.RocketMQUtil; +import org.springframework.messaging.Message; +import org.springframework.messaging.converter.StringMessageConverter; + +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author :楼兰 + * @date :Created in 2020/11/5 + * @description: 事务消息监听器 + * 关于@RocketMQTransactionListener 这个注解,有点奇怪。2.0.4版本中,是需要指定txProducerGroup指向一个消息发送者组。不同的组可以有不同的事务消息逻辑。 + * 但是到了2.1.1版本,只能指定rocketMQTemplateBeanMame,也就是说如果你有多个发送者组需要有不同的事务消息逻辑,那就需要定义多个RocketMQTemplate。 + * 而且这个版本中,虽然重现了我们在原生API中的事务消息逻辑,但是测试过程中还是发现一些奇怪的特性,用的时候要注意点。 + **/ +//@RocketMQTransactionListener(txProducerGroup = "springBootGroup2") +@RocketMQTransactionListener(rocketMQTemplateBeanName = "rocketMQTemplate") +public class MyTransactionImpl implements RocketMQLocalTransactionListener { + + private ConcurrentHashMap localTrans = new ConcurrentHashMap<>(); + @Override + public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) { + Object transId = msg.getHeaders().get(RocketMQHeaders.PREFIX+RocketMQHeaders.TRANSACTION_ID); + String destination = arg.toString(); + localTrans.put(transId,msg); + //这个msg的实现类是GenericMessage,里面实现了toString方法 + //在Header中自定义的RocketMQHeaders.TAGS属性,到这里就没了。但是RocketMQHeaders.TRANSACTION_ID这个属性就还在。 + //而message的Header里面会默认保存RocketMQHeaders里的属性,但是都会加上一个RocketMQHeaders.PREFIX前缀 + System.out.println("executeLocalTransaction msg = "+msg); + //转成RocketMQ的Message对象 + org.apache.rocketmq.common.message.Message message = RocketMQUtil.convertToRocketMessage(new StringMessageConverter(),"UTF-8",destination, msg); + String tags = message.getTags(); + if(StringUtils.contains(tags,"TagA")){ + return RocketMQLocalTransactionState.COMMIT; + }else if(StringUtils.contains(tags,"TagB")){ + return RocketMQLocalTransactionState.ROLLBACK; + }else{ + return RocketMQLocalTransactionState.UNKNOWN; + } + } + //延迟检查的时间间隔要有点奇怪。 + @Override + public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { + String transId = msg.getHeaders().get(RocketMQHeaders.PREFIX+RocketMQHeaders.TRANSACTION_ID).toString(); + Message originalMessage = localTrans.get(transId); + //这里能够获取到自定义的transaction_id属性 + System.out.println("checkLocalTransaction msg = "+originalMessage); + //获取标签时,自定义的RocketMQHeaders.TAGS拿不到,但是框架会封装成一个带RocketMQHeaders.PREFIX的属性 +// String tags = msg.getHeaders().get(RocketMQHeaders.TAGS).toString(); + String tags = msg.getHeaders().get(RocketMQHeaders.PREFIX+RocketMQHeaders.TAGS).toString(); + if(StringUtils.contains(tags,"TagC")){ + return RocketMQLocalTransactionState.COMMIT; + }else if(StringUtils.contains(tags,"TagD")){ + return RocketMQLocalTransactionState.ROLLBACK; + }else{ + return RocketMQLocalTransactionState.UNKNOWN; + } + } +} diff --git a/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/config/Swagger2.java b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/config/Swagger2.java new file mode 100644 index 00000000..464b3f5c --- /dev/null +++ b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/config/Swagger2.java @@ -0,0 +1,41 @@ +package com.roy.rocketmq.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + * @author :楼兰 + * @date :Created in 2020/11/5 + * @description: + **/ + +@Configuration +@EnableSwagger2 +public class Swagger2 { + + @Bean + public Docket createRestApi() { + return new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo()) + .select() +// .apis(RequestHandlerSelectors.basePackage("com.didispace.web")) + .paths(PathSelectors.any()) + .build(); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("Spring Boot中使用Swagger2构建RESTful APIs") + .description("SpringBoot集成RocketMQ") + .contact("楼兰") + .version("1.0") + .build(); + } +} diff --git a/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/controller/MQTestController.java b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/controller/MQTestController.java new file mode 100644 index 00000000..7b2bfde0 --- /dev/null +++ b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/controller/MQTestController.java @@ -0,0 +1,33 @@ +package com.roy.rocketmq.controller; + +import com.roy.rocketmq.basic.SpringProducer; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * @author :楼兰 + * @date :Created in 2020/10/27 + * @description: + **/ +@RestController +@RequestMapping("/MQTest") +public class MQTestController { + + private final String topic = "TestTopic"; + @Resource + private SpringProducer producer; + @RequestMapping("/sendMessage") + public String sendMessage(String message){ + producer.sendMessage(topic,message); + return "消息发送完成"; + } + + //这个发送事务消息的例子中有很多问题,需要注意下。 + @RequestMapping("/sendTransactionMessage") + public String sendTransactionMessage(String message) throws InterruptedException { + producer.sendMessageInTransaction(topic,message); + return "消息发送完成"; + } +} \ No newline at end of file diff --git a/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/domain/OrderPaidEvent.java b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/domain/OrderPaidEvent.java new file mode 100644 index 00000000..482203d1 --- /dev/null +++ b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/domain/OrderPaidEvent.java @@ -0,0 +1,39 @@ +package com.roy.rocketmq.domain; + +import java.math.BigDecimal; + +/** + * @author :楼兰 + * @date :Created in 2020/11/28 + * @description: + **/ + +public class OrderPaidEvent { + private String orderId; + + private BigDecimal paidMoney; + + public OrderPaidEvent() { + } + + public OrderPaidEvent(String orderId, BigDecimal paidMoney) { + this.orderId = orderId; + this.paidMoney = paidMoney; + } + + public String getOrderId() { + return orderId; + } + + public void setOrderId(String orderId) { + this.orderId = orderId; + } + + public BigDecimal getPaidMoney() { + return paidMoney; + } + + public void setPaidMoney(BigDecimal paidMoney) { + this.paidMoney = paidMoney; + } +} diff --git a/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/domain/ProductWithPayload.java b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/domain/ProductWithPayload.java new file mode 100644 index 00000000..6bb51feb --- /dev/null +++ b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/domain/ProductWithPayload.java @@ -0,0 +1,43 @@ +package com.roy.rocketmq.domain; + +/** + * @author :楼兰 + * @date :Created in 2020/11/28 + * @description: + **/ + +public class ProductWithPayload { + private String productName; + private T payload; + + public ProductWithPayload() { + } + + public ProductWithPayload(String productName, T payload) { + this.productName = productName; + this.payload = payload; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public T getPayload() { + return payload; + } + + public void setPayload(T payload) { + this.payload = payload; + } + + @Override public String toString() { + return "ProductWithPayload{" + + "productName='" + productName + '\'' + + ", payload=" + payload + + '}'; + } +} diff --git a/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/domain/User.java b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/domain/User.java new file mode 100644 index 00000000..c2e6d49d --- /dev/null +++ b/distributed/mq/rocketmq/springboot-rocketmq/src/main/java/com/roy/rocketmq/domain/User.java @@ -0,0 +1,38 @@ +package com.roy.rocketmq.domain; + +/** + * @author :楼兰 + * @date :Created in 2020/11/28 + * @description: + **/ + +public class User { + private String userName; + private Byte userAge; + + public String getUserName() { + return userName; + } + + public User setUserName(String userName) { + this.userName = userName; + return this; + } + + public Byte getUserAge() { + return userAge; + } + + public User setUserAge(Byte userAge) { + this.userAge = userAge; + return this; + } + + @Override + public String toString() { + return "User{" + + "userName='" + userName + '\'' + + ", userAge=" + userAge + + '}'; + } +} diff --git a/distributed/mq/rocketmq/springboot-rocketmq/src/main/resources/application.properties b/distributed/mq/rocketmq/springboot-rocketmq/src/main/resources/application.properties new file mode 100644 index 00000000..fcadafe9 --- /dev/null +++ b/distributed/mq/rocketmq/springboot-rocketmq/src/main/resources/application.properties @@ -0,0 +1,2 @@ +rocketmq.name-server=192.168.232.128:9876 +rocketmq.producer.group=springBootGroup \ No newline at end of file diff --git a/distributed/mq/rocketmq/springboot-rocketmq/src/test/java/com/roy/rocketmq/SpringRocketTest.java b/distributed/mq/rocketmq/springboot-rocketmq/src/test/java/com/roy/rocketmq/SpringRocketTest.java new file mode 100644 index 00000000..52a1a9e0 --- /dev/null +++ b/distributed/mq/rocketmq/springboot-rocketmq/src/test/java/com/roy/rocketmq/SpringRocketTest.java @@ -0,0 +1,121 @@ +package com.roy.rocketmq; + +import com.alibaba.fastjson.TypeReference; +import com.roy.rocketmq.domain.OrderPaidEvent; +import com.roy.rocketmq.domain.ProductWithPayload; +import com.roy.rocketmq.domain.User; +import org.apache.rocketmq.client.producer.SendCallback; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.spring.core.RocketMQLocalRequestCallback; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.apache.rocketmq.spring.support.RocketMQHeaders; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageHeaders; +import org.springframework.messaging.support.MessageBuilder; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.MimeTypeUtils; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +/** + * @author :楼兰 + * @date :Created in 2020/11/28 + * @description: + **/ + +@RunWith(SpringRunner.class) +@SpringBootTest +public class SpringRocketTest { + + @Resource + private RocketMQTemplate rocketMQTemplate; + + @Test + public void sendMessageTest(){ + String springTopic="TestTopic"; + //发送字符消息 + SendResult sendResult = rocketMQTemplate.syncSend(springTopic, "Hello, World!"); + System.out.printf("syncSend1 to topic %s sendResult=%s %n", springTopic, sendResult); + + sendResult = rocketMQTemplate.syncSend(springTopic, new User().setUserAge((byte) 18).setUserName("Kitty")); + System.out.printf("syncSend1 to topic %s sendResult=%s %n", springTopic, sendResult); + + sendResult = rocketMQTemplate.syncSend(springTopic, MessageBuilder.withPayload( + new User().setUserAge((byte) 21).setUserName("Lester")).setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON_VALUE).build()); + System.out.printf("syncSend1 to topic %s sendResult=%s %n", springTopic, sendResult); + + //发送对象消息 + rocketMQTemplate.asyncSend(springTopic, new OrderPaidEvent("T_001", new BigDecimal("88.00")), new SendCallback() { + @Override + public void onSuccess(SendResult var1) { + System.out.printf("async onSucess SendResult=%s %n", var1); + } + + @Override + public void onException(Throwable var1) { + System.out.printf("async onException Throwable=%s %n", var1); + } + }); + + //发送指定TAG的消息 + rocketMQTemplate.convertAndSend(springTopic + ":tag0", "I'm from tag0"); // tag0 will not be consumer-selected + System.out.printf("syncSend topic %s tag %s %n", springTopic, "tag0"); + rocketMQTemplate.convertAndSend(springTopic + ":tag1", "I'm from tag1"); + System.out.printf("syncSend topic %s tag %s %n", springTopic, "tag1"); + + //同步发送消息并且返回一个String类型的结果。 + String replyString = rocketMQTemplate.sendAndReceive(springTopic, "request string", String.class); + System.out.printf("send %s and receive %s %n", "request string", replyString); + + //同步发送消息并且返回一个Byte数组类型的结果。 + byte[] replyBytes = rocketMQTemplate.sendAndReceive(springTopic, MessageBuilder.withPayload("request byte[]").build(), byte[].class, 3000); + System.out.printf("send %s and receive %s %n", "request byte[]", new String(replyBytes)); + + //同步发送一个带hash参数的请求(排序消息),并返回一个User类型的结果 + User requestUser = new User().setUserAge((byte) 9).setUserName("requestUserName"); + User replyUser = rocketMQTemplate.sendAndReceive(springTopic, requestUser, User.class, "order-id"); + System.out.printf("send %s and receive %s %n", requestUser, replyUser); + //同步发送一个带延迟级别的消息(延迟消息),并返回一个泛型结果 + ProductWithPayload replyGenericObject = rocketMQTemplate.sendAndReceive(springTopic, "request generic", + new TypeReference>() { + }.getType(), 30000, 2); + System.out.printf("send %s and receive %s %n", "request generic", replyGenericObject); + + //异步发送消息,返回String类型结果。 + rocketMQTemplate.sendAndReceive(springTopic, "request string", new RocketMQLocalRequestCallback() { + @Override public void onSuccess(String message) { + System.out.printf("send %s and receive %s %n", "request string", message); + } + + @Override public void onException(Throwable e) { + e.printStackTrace(); + } + }); + //异步发送消息,并返回一个User类型的结果。 + rocketMQTemplate.sendAndReceive(springTopic, new User().setUserAge((byte) 9).setUserName("requestUserName"), new RocketMQLocalRequestCallback() { + @Override public void onSuccess(User message) { + System.out.printf("send user object and receive %s %n", message.toString()); + } + + @Override public void onException(Throwable e) { + e.printStackTrace(); + } + }, 5000); + //发送批量消息 + List msgs = new ArrayList(); + for (int i = 0; i < 10; i++) { + msgs.add(MessageBuilder.withPayload("Hello RocketMQ Batch Msg#" + i). + setHeader(RocketMQHeaders.KEYS, "KEY_" + i).build()); + } + + SendResult sr = rocketMQTemplate.syncSend(springTopic, msgs, 60000); + + System.out.printf("--- Batch messages send result :" + sr); + } +} diff --git a/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/README.md b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/README.md new file mode 100644 index 00000000..189588e0 --- /dev/null +++ b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/README.md @@ -0,0 +1,4 @@ + +spring-cloud-starter-stream-rocketmq + + diff --git a/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/pom.xml b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/pom.xml new file mode 100644 index 00000000..277badd0 --- /dev/null +++ b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + cn.cunchang + stream-rocketmq + 0.0.1-SNAPSHOT + rocketmq + rocketmq + + + 1.8 + + + + + + + diff --git a/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/pom.xml b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/pom.xml new file mode 100644 index 00000000..124f0268 --- /dev/null +++ b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/pom.xml @@ -0,0 +1,65 @@ + + + + 4.0.0 + cn.cunchang + rocketmq-consumer + 0.0.1-SNAPSHOT + rocketmq-consumer + rocketmq-consumer + + + 1.8 + 1.8 + 2.2.4.RELEASE + Hoxton.SR1 + 2.2.0.RELEASE + + + + + + + org.springframework.boot + spring-boot-starter-parent + ${spring.boot.version} + pom + import + + + org.springframework.cloud + spring-cloud-dependencies + ${spring.cloud.version} + pom + import + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + ${spring.cloud.alibaba.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + + com.alibaba.cloud + spring-cloud-starter-stream-rocketmq + + + + + diff --git a/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/src/main/java/cn/cunchang/RocketmqConsumerApplication.java b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/src/main/java/cn/cunchang/RocketmqConsumerApplication.java new file mode 100644 index 00000000..df89bd57 --- /dev/null +++ b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/src/main/java/cn/cunchang/RocketmqConsumerApplication.java @@ -0,0 +1,16 @@ +package cn.cunchang; + +import cn.cunchang.listener.MessageChannel; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.stream.annotation.EnableBinding; + +@EnableBinding(MessageChannel.class) +@SpringBootApplication +public class RocketmqConsumerApplication { + + public static void main(String[] args) { + SpringApplication.run(RocketmqConsumerApplication.class, args); + } + +} diff --git a/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/src/main/java/cn/cunchang/listener/MessageChannel.java b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/src/main/java/cn/cunchang/listener/MessageChannel.java new file mode 100644 index 00000000..4d78d688 --- /dev/null +++ b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/src/main/java/cn/cunchang/listener/MessageChannel.java @@ -0,0 +1,14 @@ +package cn.cunchang.listener; + +import org.springframework.cloud.stream.annotation.Input; +import org.springframework.messaging.SubscribableChannel; + +public interface MessageChannel { + + // 输入型消息通道 + String PAY_NOTICE_INPUT = "pay-notice-input"; + + @Input(PAY_NOTICE_INPUT) + SubscribableChannel payNoticeInput(); + +} diff --git a/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/src/main/java/cn/cunchang/listener/PayNoticeConsumer.java b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/src/main/java/cn/cunchang/listener/PayNoticeConsumer.java new file mode 100644 index 00000000..58569b20 --- /dev/null +++ b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/src/main/java/cn/cunchang/listener/PayNoticeConsumer.java @@ -0,0 +1,20 @@ +package cn.cunchang.listener; + +import cn.cunchang.message.PayResultMsg; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.stream.annotation.StreamListener; +import org.springframework.messaging.handler.annotation.Payload; +import org.springframework.stereotype.Component; + +@Component +public class PayNoticeConsumer { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @StreamListener(MessageChannel.PAY_NOTICE_INPUT) + public void payNoticeInputOnMessage(@Payload PayResultMsg message) { + logger.info("[onMessage][线程编号:{} 消息内容:{}]", Thread.currentThread().getId(), message); + } + +} diff --git a/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/src/main/java/cn/cunchang/message/PayResultMsg.java b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/src/main/java/cn/cunchang/message/PayResultMsg.java new file mode 100644 index 00000000..7b201e68 --- /dev/null +++ b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/src/main/java/cn/cunchang/message/PayResultMsg.java @@ -0,0 +1,84 @@ +package cn.cunchang.message; + +/** + * 支付结果消息 + * @author cunchang + */ +public class PayResultMsg { + + /** + * 支付流水号 + */ + private String payNo; + + /** + * 付款账号 + */ + private String payAccNo; + + /** + * 收款账户 + */ + private String revAccNo; + + /** + * 支付金额 + */ + private Long amount; + + /** + * 支付结果,0失败 1成功 + */ + private Integer result; + + public String getPayNo() { + return payNo; + } + + public void setPayNo(String payNo) { + this.payNo = payNo; + } + + public String getPayAccNo() { + return payAccNo; + } + + public void setPayAccNo(String payAccNo) { + this.payAccNo = payAccNo; + } + + public String getRevAccNo() { + return revAccNo; + } + + public void setRevAccNo(String revAccNo) { + this.revAccNo = revAccNo; + } + + public Long getAmount() { + return amount; + } + + public void setAmount(Long amount) { + this.amount = amount; + } + + public Integer getResult() { + return result; + } + + public void setResult(Integer result) { + this.result = result; + } + + @Override + public String toString() { + return "PayResultMsg{" + + "payNo='" + payNo + '\'' + + ", payAccNo='" + payAccNo + '\'' + + ", revAccNo='" + revAccNo + '\'' + + ", amount=" + amount + + ", result=" + result + + '}'; + } +} diff --git a/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/src/main/resources/application.yml b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/src/main/resources/application.yml new file mode 100644 index 00000000..6333035e --- /dev/null +++ b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-consumer/src/main/resources/application.yml @@ -0,0 +1,28 @@ +spring: + application: + name: stream-rocketmq-consumer + cloud: + # Spring Cloud Stream 配置项,对应 BindingServiceProperties 类 + stream: + # Binding 配置项,对应 BindingProperties Map + bindings: + pay-notice-input: + destination: pay-result # 目的地。这里使用 RocketMQ Topic + content-type: application/json # 内容格式。这里使用 JSON + group: pay-notice-consumer-group # 消费者分组,命名规则:组名+topic名 + + # Spring Cloud Stream RocketMQ 配置项 + rocketmq: + # RocketMQ Binder 配置项,对应 RocketMQBinderConfigurationProperties 类 + binder: + name-server: localhost:9876 # RocketMQ Namesrv 地址 + # RocketMQ 自定义 Binding 配置项,对应 RocketMQBindingProperties Map + bindings: + pay-notice-input: + # RocketMQ Consumer 配置项,对应 RocketMQConsumerProperties 类 + consumer: + enabled: true # 是否开启消费,默认为 true + broadcasting: false # 是否使用广播消费,默认为 false 使用集群消费 + +server: + port: ${random.int[10000,19999]} # 随机端口,方便启动多个消费者 diff --git a/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/pom.xml b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/pom.xml new file mode 100644 index 00000000..0ee441e4 --- /dev/null +++ b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/pom.xml @@ -0,0 +1,64 @@ + + + 4.0.0 + + cn.cunchang + rocketmq-producer + 0.0.1-SNAPSHOT + rocketmq-producer + rocketmq-producer + + + 1.8 + 1.8 + 2.2.4.RELEASE + Hoxton.SR1 + 2.2.0.RELEASE + + + + + + + org.springframework.boot + spring-boot-starter-parent + ${spring.boot.version} + pom + import + + + org.springframework.cloud + spring-cloud-dependencies + ${spring.cloud.version} + pom + import + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + ${spring.cloud.alibaba.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + + com.alibaba.cloud + spring-cloud-starter-stream-rocketmq + + + + diff --git a/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/src/main/java/cn/cunchang/RocketmqProducerApplication.java b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/src/main/java/cn/cunchang/RocketmqProducerApplication.java new file mode 100644 index 00000000..682a2fdc --- /dev/null +++ b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/src/main/java/cn/cunchang/RocketmqProducerApplication.java @@ -0,0 +1,16 @@ +package cn.cunchang; + +import cn.cunchang.message.MessageChannel; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.stream.annotation.EnableBinding; + +@EnableBinding(MessageChannel.class) +@SpringBootApplication +public class RocketmqProducerApplication { + + public static void main(String[] args) { + SpringApplication.run(RocketmqProducerApplication.class, args); + } + +} diff --git a/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/src/main/java/cn/cunchang/message/MessageChannel.java b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/src/main/java/cn/cunchang/message/MessageChannel.java new file mode 100644 index 00000000..54efb948 --- /dev/null +++ b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/src/main/java/cn/cunchang/message/MessageChannel.java @@ -0,0 +1,14 @@ +package cn.cunchang.message; + +import org.springframework.cloud.stream.annotation.Output; +import org.springframework.messaging.SubscribableChannel; + +public interface MessageChannel { + + // 输入型消息通道 + String PAY_NOTICE_OUTPUT = "pay-notice-output"; + + @Output(PAY_NOTICE_OUTPUT) + SubscribableChannel payNoticeOutput(); + +} diff --git a/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/src/main/java/cn/cunchang/message/PayResultMsg.java b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/src/main/java/cn/cunchang/message/PayResultMsg.java new file mode 100644 index 00000000..7b201e68 --- /dev/null +++ b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/src/main/java/cn/cunchang/message/PayResultMsg.java @@ -0,0 +1,84 @@ +package cn.cunchang.message; + +/** + * 支付结果消息 + * @author cunchang + */ +public class PayResultMsg { + + /** + * 支付流水号 + */ + private String payNo; + + /** + * 付款账号 + */ + private String payAccNo; + + /** + * 收款账户 + */ + private String revAccNo; + + /** + * 支付金额 + */ + private Long amount; + + /** + * 支付结果,0失败 1成功 + */ + private Integer result; + + public String getPayNo() { + return payNo; + } + + public void setPayNo(String payNo) { + this.payNo = payNo; + } + + public String getPayAccNo() { + return payAccNo; + } + + public void setPayAccNo(String payAccNo) { + this.payAccNo = payAccNo; + } + + public String getRevAccNo() { + return revAccNo; + } + + public void setRevAccNo(String revAccNo) { + this.revAccNo = revAccNo; + } + + public Long getAmount() { + return amount; + } + + public void setAmount(Long amount) { + this.amount = amount; + } + + public Integer getResult() { + return result; + } + + public void setResult(Integer result) { + this.result = result; + } + + @Override + public String toString() { + return "PayResultMsg{" + + "payNo='" + payNo + '\'' + + ", payAccNo='" + payAccNo + '\'' + + ", revAccNo='" + revAccNo + '\'' + + ", amount=" + amount + + ", result=" + result + + '}'; + } +} diff --git a/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/src/main/java/cn/cunchang/producer/ProducerController.java b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/src/main/java/cn/cunchang/producer/ProducerController.java new file mode 100644 index 00000000..52e69809 --- /dev/null +++ b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/src/main/java/cn/cunchang/producer/ProducerController.java @@ -0,0 +1,78 @@ +package cn.cunchang.producer; + +import cn.cunchang.message.MessageChannel; +import cn.cunchang.message.PayResultMsg; +import org.apache.rocketmq.common.message.MessageConst; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.messaging.Message; +import org.springframework.messaging.support.MessageBuilder; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Random; +import java.util.UUID; + +@RestController +@RequestMapping("/producer") +public class ProducerController { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + private MessageChannel messageChannel; + + /** + * http://127.0.0.1:18080/producer/send + * + * @return + */ + @GetMapping("/send") + public boolean send() { + // <2>创建 Message + + String payNo = UUID.randomUUID().toString(); + + PayResultMsg payResultMsg = new PayResultMsg(); + payResultMsg.setPayNo(payNo); + payResultMsg.setPayAccNo("10086"); + payResultMsg.setRevAccNo("10010"); + payResultMsg.setAmount(1000000L); + payResultMsg.setResult(1); + + // <3>创建 Spring Message 对象 + Message message = MessageBuilder.withPayload(payResultMsg) + .setHeader(MessageConst.PROPERTY_TAGS, "pay_notice_tag") // 设置 Tag + .setHeader(MessageConst.PROPERTY_KEYS, payNo) // 设置 key,方便在控制台查找。 + .build(); + System.out.println("topic:pay-result,msg:"+message); + // <4>发送消息 + boolean sendResult = messageChannel.payNoticeOutput().send(message); + logger.info("send,topic:pay-result,msg:{},sendResult:{}",message,sendResult); + return sendResult; + } + + @GetMapping("/send_delay") + public boolean sendDelay() { + // 创建 Message + PayResultMsg payResultMsg = new PayResultMsg(); + payResultMsg.setPayNo(UUID.randomUUID().toString()); + payResultMsg.setPayAccNo("10086"); + payResultMsg.setRevAccNo("10010"); + payResultMsg.setAmount(1000000L); + payResultMsg.setResult(1); + + // <3>创建 Spring Message 对象 + Message message = MessageBuilder.withPayload(payResultMsg) + .setHeader(MessageConst.PROPERTY_DELAY_TIME_LEVEL, "3") // 设置延迟级别为3,10 秒后消费。 + .build(); + // 发送消息 + boolean sendResult = messageChannel.payNoticeOutput().send(message); + logger.info("sendDelay,topic:pay-result,msg:{},sendResult:{}",message,sendResult); + return sendResult; + } + + +} diff --git a/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/src/main/resources/application.yml b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/src/main/resources/application.yml new file mode 100644 index 00000000..df5ed20e --- /dev/null +++ b/distributed/mq/rocketmq/springcloud-alibaba-rocketmq/rocketmq-producer/src/main/resources/application.yml @@ -0,0 +1,26 @@ +spring: + application: + name: stream-rocketmq-producer + cloud: + # Spring Cloud Stream 配置项,对应 BindingServiceProperties 类 + stream: + # Binding 配置项,对应 BindingProperties Map + bindings: + pay-notice-output: + destination: pay-result # 目的地。这里使用 RocketMQ Topic + content-type: application/json # 内容格式。这里使用 JSON + # Spring Cloud Stream RocketMQ 配置项 + rocketmq: + # RocketMQ Binder 配置项,对应 RocketMQBinderConfigurationProperties 类 + binder: + name-server: localhost:9876 # RocketMQ Namesrv 地址 + # RocketMQ 自定义 Binding 配置项,对应 RocketMQBindingProperties Map + bindings: + pay-notice-output: + # RocketMQ Producer 配置项,对应 RocketMQProducerProperties 类 + producer: + group: pay-center # 生产者分组 + sync: true # 是否同步发送消息,默认为 false 异步。 + +server: + port: 18080 diff --git a/distributed/netty/pom.xml b/distributed/netty/pom.xml deleted file mode 100644 index fb57fb32..00000000 --- a/distributed/netty/pom.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - 4.0.0 - - cn.lastwhisper - netty - 1.0-SNAPSHOT - - - 4.11 - 4.1.9.Final - UTF-8 - UTF-8 - - - - - - io.netty - netty-all - ${netty.version} - - - - - - - - junit - junit - ${junit.version} - - - - - - io.netty - netty-all - - - - - - - junit - junit - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.3 - - 1.7 - 1.7 - - - - maven-clean-plugin - 2.6.1 - - - maven-failsafe-plugin - 2.18.1 - - - maven-surefire-plugin - 2.18.1 - - - org.apache.maven.plugins - maven-jar-plugin - 2.6 - - - org.codehaus.mojo - exec-maven-plugin - 1.2.1 - - - - - \ No newline at end of file diff --git a/distributed/netty/src/main/java/cn/lastwhisper/netty/common/Constant.java b/distributed/netty/src/main/java/cn/lastwhisper/netty/common/Constant.java deleted file mode 100644 index 34ff0e2c..00000000 --- a/distributed/netty/src/main/java/cn/lastwhisper/netty/common/Constant.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.netty.common; - -/** - * - * @author lastwhisper - * @date 2020/2/8 - */ -public interface Constant { - - String ip = "127.0.0.1"; - Integer port = 9090; - -} diff --git a/distributed/netty/src/main/java/cn/lastwhisper/netty/echo/client/EchoClient.java b/distributed/netty/src/main/java/cn/lastwhisper/netty/echo/client/EchoClient.java deleted file mode 100644 index f732dc8c..00000000 --- a/distributed/netty/src/main/java/cn/lastwhisper/netty/echo/client/EchoClient.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.lastwhisper.netty.echo.client; - -import cn.lastwhisper.netty.common.Constant; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.nio.NioSocketChannel; - -import java.net.InetSocketAddress; - -/** - * echo客户端 - * @author lastwhisper - * @date 2020/2/21 - */ -public class EchoClient { - - public static void main(String[] args) throws Exception { - new EchoClient().start(Constant.ip, Constant.port); - } - - public void start(String host, int port) throws Exception { - - EventLoopGroup group = new NioEventLoopGroup(); - - try { - //1、创建 Bootstrap - Bootstrap bootstrap = new Bootstrap(); - //2、指定 EventLoopGroup 以处理客户端事件;需要适用于 NIO 的实现 - bootstrap.group(group) - //3、适用于 NIO 传输的Channel 类型 - .channel(NioSocketChannel.class) - //4、设置服务器的InetSocketAddress - .remoteAddress(new InetSocketAddress(host, port)) - //5、在创建Channel时,向 ChannelPipeline中添加一个 EchoClientHandler实例 - .handler(new ChannelInitializer() { - @Override - protected void initChannel(SocketChannel ch) throws Exception { - ch.pipeline().addLast(new EchoClientHandler()); - } - }); - //6、连接到远程节点,阻塞等待直到连接完成 - ChannelFuture f = bootstrap.connect().sync(); - //7、阻塞,直到Channel 关闭 - f.channel().closeFuture().sync(); - } finally { - //8、关闭线程池并且释放所有的资源 - group.shutdownGracefully().sync(); - } - - } - - -} diff --git a/distributed/netty/src/main/java/cn/lastwhisper/netty/echo/client/EchoClientHandler.java b/distributed/netty/src/main/java/cn/lastwhisper/netty/echo/client/EchoClientHandler.java deleted file mode 100644 index 47acd457..00000000 --- a/distributed/netty/src/main/java/cn/lastwhisper/netty/echo/client/EchoClientHandler.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.lastwhisper.netty.echo.client; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.util.CharsetUtil; - -/** - * echo客户端处理者 - * - * 客户端将拥有一个用来处理数据的 ChannelInboundHandler - * - * @author lastwhisper - * @date 2020/2/21 - */ -@ChannelHandler.Sharable// 标记该类的实例可以被多个 Channel 共享 -public class EchoClientHandler extends SimpleChannelInboundHandler { - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - // 当被通知 Channel是活跃的时候,发送一条消息 - ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", - CharsetUtil.UTF_8)); - } - - @Override - protected void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception { - // 记录已接收消息的转储 - System.out.println( - "Client received: " + in.toString(CharsetUtil.UTF_8)); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, - Throwable cause) { - //在发生异常时,记录错误并关闭Channel - cause.printStackTrace(); - ctx.close(); - } - -} diff --git a/distributed/netty/src/main/java/cn/lastwhisper/netty/echo/server/EchoServer.java b/distributed/netty/src/main/java/cn/lastwhisper/netty/echo/server/EchoServer.java deleted file mode 100644 index 8dd2150f..00000000 --- a/distributed/netty/src/main/java/cn/lastwhisper/netty/echo/server/EchoServer.java +++ /dev/null @@ -1,61 +0,0 @@ -package cn.lastwhisper.netty.echo.server; - -import cn.lastwhisper.netty.common.Constant; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.nio.NioServerSocketChannel; - -import java.net.InetSocketAddress; - -/** - * echo服务器端 - * - * 绑定到服务器将在其上监听并接受传入连接请求的端口; - * 配置 Channel,以将有关的入站消息通知给 EchoServerHandler 实例 - * - * @author lastwhisper - * @date 2020/2/21 - */ -public class EchoServer { - - public static void main(String[] args) throws Exception { - new EchoServer().start(Constant.port); - } - - public void start(int port) throws Exception { - //1、创建ChannelHandler和EventLoopGroup - final EchoServerHandler serverHandler = new EchoServerHandler(); - EventLoopGroup group = new NioEventLoopGroup(); - //2、创建ServerBootstrap - ServerBootstrap bootstrap = new ServerBootstrap(); - try { - bootstrap.group(group) - //3、指定所使用的 NIO传输 Channel - .channel(NioServerSocketChannel.class) - //4、使用指定的端口设置套接字地址 - .localAddress(new InetSocketAddress(port)) - //5、添加一个EchoServerHandler到子Channel的ChannelPipeline - .childHandler(new ChannelInitializer() { - @Override - public void initChannel(SocketChannel ch) throws Exception { - //EchoServerHandler 被标注为@Shareable,所以我们可以总是使用同样的实例 - //这里对于所有的客户端连接来说,都会使用同一个 EchoServerHandler,因为其被标注为@Sharable, - //这将在后面的章节中讲到。 - ch.pipeline().addLast(serverHandler); - } - }); - //6、异步地绑定服务器;调用 sync()方法阻塞等待直到绑定完成 - ChannelFuture cf = bootstrap.bind().sync(); - //7、获取 Channel 的CloseFuture,并且阻塞当前线程直到它完成 - cf.channel().closeFuture().sync(); - } finally { - //8、关闭 EventLoopGroup,释放所有的资源 - group.shutdownGracefully().sync(); - } - - } -} \ No newline at end of file diff --git a/distributed/netty/src/main/java/cn/lastwhisper/netty/echo/server/EchoServerHandler.java b/distributed/netty/src/main/java/cn/lastwhisper/netty/echo/server/EchoServerHandler.java deleted file mode 100644 index 94696c29..00000000 --- a/distributed/netty/src/main/java/cn/lastwhisper/netty/echo/server/EchoServerHandler.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.lastwhisper.netty.echo.server; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.util.CharsetUtil; - -/** - * echo服务器端处理者 - * 实现 ChannelInboundHandler 接口, 用来定义响应入站事件的方法 - * - * @author lastwhisper - * @date 2020/2/21 - */ -@ChannelHandler.Sharable //标示一个ChannelHandler 可以被多个 Channel 安全地共享 -public class EchoServerHandler extends ChannelInboundHandlerAdapter { - - // 对于每个传入的消息都要调用 - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - ByteBuf in = (ByteBuf) msg; - System.out.println( - "Server received: " + in.toString(CharsetUtil.UTF_8)); - // 将接收到的消息写给发送者,而不冲刷出站消息 - ctx.write(in); - } - - // 通知ChannelInboundHandler最后一次对channelRead()的调用是当前批量读取中的最后一条消息 - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - // 将未决消息冲刷到远程节点,并且关闭该 Channel - ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE); - } - - // 在读取操作期间, 有异常抛出时会调用 - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - cause.printStackTrace(); - // 关闭channel - ctx.close(); - } -} diff --git a/distributed/netty/src/main/java/cn/lastwhisper/netty/transfer/ChannelOperationExamples.java b/distributed/netty/src/main/java/cn/lastwhisper/netty/transfer/ChannelOperationExamples.java deleted file mode 100644 index 82f0c84c..00000000 --- a/distributed/netty/src/main/java/cn/lastwhisper/netty/transfer/ChannelOperationExamples.java +++ /dev/null @@ -1,74 +0,0 @@ -package cn.lastwhisper.netty.transfer; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.util.CharsetUtil; - -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; - -/** - * 代码清单 4-5 写出到 Channel - * - * 代码清单 4-6 从多个线程使用同一个 Channel - * - * @author Norman Maurer - */ -public class ChannelOperationExamples { - private static final Channel CHANNEL_FROM_SOMEWHERE = new NioSocketChannel(); - /** - * 代码清单 4-5 写出到 Channel - */ - public static void writingToChannel() { - Channel channel = CHANNEL_FROM_SOMEWHERE; // Get the channel reference from somewhere - //创建持有要写数据的 ByteBuf - ByteBuf buf = Unpooled.copiedBuffer("your data", CharsetUtil.UTF_8); - ChannelFuture cf = channel.writeAndFlush(buf); - //添加 ChannelFutureListener 以便在写操作完成后接收通知 - cf.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) { - //写操作完成,并且没有错误发生 - if (future.isSuccess()) { - System.out.println("Write successful"); - } else { - //记录错误 - System.err.println("Write error"); - future.cause().printStackTrace(); - } - } - }); - } - - /** - * 代码清单 4-6 从多个线程使用同一个 Channel - */ - public static void writingToChannelFromManyThreads() { - final Channel channel = CHANNEL_FROM_SOMEWHERE; // Get the channel reference from somewhere - //创建持有要写数据的ByteBuf - final ByteBuf buf = Unpooled.copiedBuffer("your data", - CharsetUtil.UTF_8); - //创建将数据写到Channel 的 Runnable - Runnable writer = new Runnable() { - @Override - public void run() { - channel.write(buf.duplicate()); - } - }; - //获取到线程池Executor 的引用 - Executor executor = Executors.newCachedThreadPool(); - - //递交写任务给线程池以便在某个线程中执行 - // write in one thread - executor.execute(writer); - - //递交另一个写任务以便在另一个线程中执行 - // write in another thread - executor.execute(writer); - //... - } -} diff --git a/distributed/netty/src/main/java/cn/lastwhisper/netty/transfer/NettyNioServer.java b/distributed/netty/src/main/java/cn/lastwhisper/netty/transfer/NettyNioServer.java deleted file mode 100644 index c72b8c2d..00000000 --- a/distributed/netty/src/main/java/cn/lastwhisper/netty/transfer/NettyNioServer.java +++ /dev/null @@ -1,62 +0,0 @@ -package cn.lastwhisper.netty.transfer; - -import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.*; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.nio.NioServerSocketChannel; - -import java.net.InetSocketAddress; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; - -/** - * 代码清单 4-4 使用 Netty 的异步网络处理 - * - * @author Norman Maurer - */ -public class NettyNioServer { - public void server(int port) throws Exception { - final ByteBuf buf = - Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Hi!\r\n", - StandardCharsets.UTF_8)); - //为非阻塞模式使用NioEventLoopGroup - NioEventLoopGroup group = new NioEventLoopGroup(); - try { - //创建ServerBootstrap - ServerBootstrap b = new ServerBootstrap(); - b.group(group).channel(NioServerSocketChannel.class) - .localAddress(new InetSocketAddress(port)) - //指定 ChannelInitializer,对于每个已接受的连接都调用它 - .childHandler(new ChannelInitializer() { - @Override - public void initChannel(SocketChannel ch) - throws Exception { - ch.pipeline().addLast( - //添加 ChannelInboundHandlerAdapter以接收和处理事件 - new ChannelInboundHandlerAdapter() { - @Override - public void channelActive( - //将消息写到客户端,并添加ChannelFutureListener, - //以便消息一被写完就关闭连接 - ChannelHandlerContext ctx) throws Exception { - ctx.writeAndFlush(buf.duplicate()) - .addListener( - ChannelFutureListener.CLOSE); - } - }); - } - } - ); - //绑定服务器以接受连接 - ChannelFuture f = b.bind().sync(); - f.channel().closeFuture().sync(); - } finally { - //释放所有的资源 - group.shutdownGracefully().sync(); - } - } -} - diff --git a/distributed/netty/src/main/java/cn/lastwhisper/netty/transfer/NettyOioServer.java b/distributed/netty/src/main/java/cn/lastwhisper/netty/transfer/NettyOioServer.java deleted file mode 100644 index 3c4051da..00000000 --- a/distributed/netty/src/main/java/cn/lastwhisper/netty/transfer/NettyOioServer.java +++ /dev/null @@ -1,62 +0,0 @@ -package cn.lastwhisper.netty.transfer; - -import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.*; -import io.netty.channel.oio.OioEventLoopGroup; -import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.oio.OioServerSocketChannel; - -import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; - -/** - * Listing 4.3 Blocking networking with Netty - * - * @author Norman Maurer - */ -public class NettyOioServer { - public void server(int port) - throws Exception { - final ByteBuf buf = - Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Hi!\r\n", StandardCharsets.UTF_8)); - EventLoopGroup group = new OioEventLoopGroup(); - try { - //创建 ServerBootstrap - ServerBootstrap b = new ServerBootstrap(); - b.group(group) - //使用 OioEventLoopGroup以允许阻塞模式(旧的I/O) - .channel(OioServerSocketChannel.class) - .localAddress(new InetSocketAddress(port)) - //指定 ChannelInitializer,对于每个已接受的连接都调用它 - .childHandler(new ChannelInitializer() { - @Override - public void initChannel(SocketChannel ch) - throws Exception { - ch.pipeline().addLast( - //添加一个 ChannelInboundHandlerAdapter以拦截和处理事件 - new ChannelInboundHandlerAdapter() { - @Override - public void channelActive( - ChannelHandlerContext ctx) - throws Exception { - ctx.writeAndFlush(buf.duplicate()) - .addListener( - //将消息写到客户端,并添加 ChannelFutureListener, - //以便消息一被写完就关闭连接 - ChannelFutureListener.CLOSE); - } - }); - } - }); - //绑定服务器以接受连接 - ChannelFuture f = b.bind().sync(); - f.channel().closeFuture().sync(); - } finally { - //释放所有的资源 - group.shutdownGracefully().sync(); - } - } -} - diff --git a/distributed/netty/src/main/java/cn/lastwhisper/netty/transfer/PlainNioServer.java b/distributed/netty/src/main/java/cn/lastwhisper/netty/transfer/PlainNioServer.java deleted file mode 100644 index f425cc3c..00000000 --- a/distributed/netty/src/main/java/cn/lastwhisper/netty/transfer/PlainNioServer.java +++ /dev/null @@ -1,87 +0,0 @@ -package cn.lastwhisper.netty.transfer; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.nio.ByteBuffer; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; -import java.util.Iterator; -import java.util.Set; - -/** - * 代码清单 4-2 未使用 Netty 的异步网络编程 - * - * @author Norman Maurer - */ -public class PlainNioServer { - public void serve(int port) throws IOException { - ServerSocketChannel serverChannel = ServerSocketChannel.open(); - serverChannel.configureBlocking(false); - ServerSocket ss = serverChannel.socket(); - InetSocketAddress address = new InetSocketAddress(port); - //将服务器绑定到选定的端口 - ss.bind(address); - //打开Selector来处理 Channel - Selector selector = Selector.open(); - //将ServerSocket注册到Selector以接受连接 - serverChannel.register(selector, SelectionKey.OP_ACCEPT); - final ByteBuffer msg = ByteBuffer.wrap("Hi!\r\n".getBytes()); - for (; ; ) { - try { - //等待需要处理的新事件;阻塞将一直持续到下一个传入事件 - selector.select(); - } catch (IOException ex) { - ex.printStackTrace(); - //handle exception - break; - } - //获取所有接收事件的SelectionKey实例 - Set readyKeys = selector.selectedKeys(); - Iterator iterator = readyKeys.iterator(); - while (iterator.hasNext()) { - SelectionKey key = iterator.next(); - iterator.remove(); - try { - //检查事件是否是一个新的已经就绪可以被接受的连接 - if (key.isAcceptable()) { - ServerSocketChannel server = - (ServerSocketChannel) key.channel(); - SocketChannel client = server.accept(); - client.configureBlocking(false); - //接受客户端,并将它注册到选择器 - client.register(selector, SelectionKey.OP_WRITE | - SelectionKey.OP_READ, msg.duplicate()); - System.out.println( - "Accepted connection from " + client); - } - //检查套接字是否已经准备好写数据 - if (key.isWritable()) { - SocketChannel client = - (SocketChannel) key.channel(); - ByteBuffer buffer = - (ByteBuffer) key.attachment(); - while (buffer.hasRemaining()) { - //将数据写到已连接的客户端 - if (client.write(buffer) == 0) { - break; - } - } - //关闭连接 - client.close(); - } - } catch (IOException ex) { - key.cancel(); - try { - key.channel().close(); - } catch (IOException cex) { - // ignore on close - } - } - } - } - } -} - diff --git a/distributed/netty/src/main/java/cn/lastwhisper/netty/transfer/PlainOioServer.java b/distributed/netty/src/main/java/cn/lastwhisper/netty/transfer/PlainOioServer.java deleted file mode 100644 index fd80ffbd..00000000 --- a/distributed/netty/src/main/java/cn/lastwhisper/netty/transfer/PlainOioServer.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.lastwhisper.netty.transfer; - -import java.io.IOException; -import java.io.OutputStream; -import java.net.ServerSocket; -import java.net.Socket; -import java.nio.charset.StandardCharsets; - -/** - * 代码清单 4-1 未使用 Netty 的阻塞网络编程 - * - * @author Norman Maurer - */ -public class PlainOioServer { - public void serve(int port) throws IOException { - //将服务器绑定到指定端口 - final ServerSocket socket = new ServerSocket(port); - try { - for (; ; ) { - //接受连接 - final Socket clientSocket = socket.accept(); - System.out.println( - "Accepted connection from " + clientSocket); - //创建一个新的线程来处理该连接 - new Thread(new Runnable() { - @Override - public void run() { - OutputStream out; - try { - //将消息写给已连接的客户端 - out = clientSocket.getOutputStream(); - out.write("Hi!\r\n".getBytes( - StandardCharsets.UTF_8)); - out.flush(); - //关闭连接 - clientSocket.close(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - try { - clientSocket.close(); - } catch (IOException ex) { - // ignore on close - } - } - //启动线程 - } - }).start(); - } - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/distributed/session/jwt-session/pom.xml b/distributed/session/jwt-session/pom.xml new file mode 100644 index 00000000..aee438d5 --- /dev/null +++ b/distributed/session/jwt-session/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.4.4 + + + cn.cunchang + jwt-session + 0.0.1-SNAPSHOT + jwt-session + jwt-session + + 1.8 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + com.auth0 + java-jwt + 3.10.3 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/distributed/session/jwt-session/src/main/java/cn/cunchang/Application.java b/distributed/session/jwt-session/src/main/java/cn/cunchang/Application.java new file mode 100644 index 00000000..2ba8082d --- /dev/null +++ b/distributed/session/jwt-session/src/main/java/cn/cunchang/Application.java @@ -0,0 +1,13 @@ +package cn.cunchang; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/distributed/session/jwt-session/src/main/java/cn/cunchang/config/LoginIntercepter.java b/distributed/session/jwt-session/src/main/java/cn/cunchang/config/LoginIntercepter.java new file mode 100644 index 00000000..304a7c6f --- /dev/null +++ b/distributed/session/jwt-session/src/main/java/cn/cunchang/config/LoginIntercepter.java @@ -0,0 +1,55 @@ +package cn.cunchang.config; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTDecodeException; +import com.auth0.jwt.exceptions.TokenExpiredException; +import com.auth0.jwt.interfaces.DecodedJWT; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.servlet.AsyncHandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@Component +public class LoginIntercepter implements AsyncHandlerInterceptor { + + public static final String JWT_KEY = "imooc"; + public static final String JWT_TOKEN = "token"; + public static final String UID = "uid"; + public static final String CURRENT_USER = "username"; + + /** + * 返回true, 表示不拦截,继续往下执行 + * 返回false/抛出异常,不再往下执行 + * @param request + * @param response + * @param handler + * @return + * @throws Exception + */ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String token = request.getHeader(JWT_TOKEN); + if (StringUtils.isEmpty(token)) { + throw new RuntimeException("token为空"); + } + + Algorithm algorithm = Algorithm.HMAC256(JWT_KEY); + JWTVerifier verifier = JWT.require(algorithm) + .build(); //Reusable verifier instance + try { + DecodedJWT jwt = verifier.verify(token); + request.setAttribute(UID, jwt.getClaim(UID).asInt()); + request.setAttribute(CURRENT_USER, jwt.getClaim(CURRENT_USER).asString()); + }catch (TokenExpiredException e) { + throw new RuntimeException("token过期"); + }catch (JWTDecodeException e) { + throw new RuntimeException("解码失败,token错误"); + } + + return true; + } +} diff --git a/distributed/session/jwt-session/src/main/java/cn/cunchang/config/WebMvcConfig.java b/distributed/session/jwt-session/src/main/java/cn/cunchang/config/WebMvcConfig.java new file mode 100644 index 00000000..164c8f0d --- /dev/null +++ b/distributed/session/jwt-session/src/main/java/cn/cunchang/config/WebMvcConfig.java @@ -0,0 +1,24 @@ +package cn.cunchang.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebMvcConfig implements WebMvcConfigurer { + + @Autowired + private LoginIntercepter loginIntercepter; + + @Override + public void addInterceptors(InterceptorRegistry registry) { +// registry.addInterceptor(loginIntercepter) +// .addPathPatterns("/user/address") // /user/** +// .addPathPatterns("/user/infoWithJwt"); + + registry.addInterceptor(loginIntercepter) + .addPathPatterns("/user/**") //未登录的都会被拦截 + .excludePathPatterns("/user/login"); + } +} diff --git a/distributed/session/jwt-session/src/main/java/cn/cunchang/controller/UserController.java b/distributed/session/jwt-session/src/main/java/cn/cunchang/controller/UserController.java new file mode 100644 index 00000000..f8d3d1dc --- /dev/null +++ b/distributed/session/jwt-session/src/main/java/cn/cunchang/controller/UserController.java @@ -0,0 +1,58 @@ +package cn.cunchang.controller; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; +import org.springframework.web.bind.annotation.*; + +import java.util.Date; + +import static cn.cunchang.config.LoginIntercepter.*; + +@RequestMapping("/user") +@RestController +public class UserController { + + /** + * http://localhost:8080/user/login?username=admin&password=123456 + * + * @param username + * @param password + * @return + */ + @GetMapping("/login") + public String login(@RequestParam String username, @RequestParam String password) { + Algorithm algorithm = Algorithm.HMAC256(JWT_KEY); + String token = JWT.create() + .withClaim(CURRENT_USER, username) + .withClaim(UID, 1) + .withExpiresAt(new Date(System.currentTimeMillis() + 3600000)) + .sign(algorithm); + return token; + } + + /** + * http://localhost:8080/user/current + * + * @param username + * @return + */ + @GetMapping("/current") + public String current(@RequestAttribute String username) { + return "当前登录的是:" + username; + } + + + /** + * http://localhost:8080/user/invalidate + * + * jwt无法使session失效 + * + * @return + */ + @GetMapping("/invalidate") + public void invalidate() { + + } + + +} diff --git a/springboot-integration-examples/spring-validated/src/main/resources/application.properties b/distributed/session/jwt-session/src/main/resources/application.properties similarity index 100% rename from springboot-integration-examples/spring-validated/src/main/resources/application.properties rename to distributed/session/jwt-session/src/main/resources/application.properties diff --git a/distributed/session/jwt-session/src/test/java/cn/cunchang/ApplicationTests.java b/distributed/session/jwt-session/src/test/java/cn/cunchang/ApplicationTests.java new file mode 100644 index 00000000..c13144bc --- /dev/null +++ b/distributed/session/jwt-session/src/test/java/cn/cunchang/ApplicationTests.java @@ -0,0 +1,13 @@ +package cn.cunchang; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/distributed/session/redis-session/pom.xml b/distributed/session/redis-session/pom.xml new file mode 100644 index 00000000..7acfe7cd --- /dev/null +++ b/distributed/session/redis-session/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.3.3.RELEASE + + + cn.cunchang + redis-session + 0.0.1-SNAPSHOT + redis-session + redis-session + + 1.8 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/distributed/session/redis-session/src/main/java/cn/cunchang/Application.java b/distributed/session/redis-session/src/main/java/cn/cunchang/Application.java new file mode 100644 index 00000000..2ba8082d --- /dev/null +++ b/distributed/session/redis-session/src/main/java/cn/cunchang/Application.java @@ -0,0 +1,13 @@ +package cn.cunchang; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/distributed/session/redis-session/src/main/java/cn/cunchang/controller/UserController.java b/distributed/session/redis-session/src/main/java/cn/cunchang/controller/UserController.java new file mode 100644 index 00000000..d365a24d --- /dev/null +++ b/distributed/session/redis-session/src/main/java/cn/cunchang/controller/UserController.java @@ -0,0 +1,60 @@ +package cn.cunchang.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.web.bind.annotation.*; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + + +@RequestMapping("/user") +@RestController +public class UserController { + + @Autowired + private StringRedisTemplate stringRedisTemplate; + + /** + * http://localhost:8080/user/login?username=admin&password=123456 + *

+ * 与前端配合,登录成功后,cookie记录token + * + * @param username + * @param password + * @return + */ + @GetMapping("/login") + public String login(@RequestParam String username, @RequestParam String password) { + //账号密码正确 + String key = "token_" + UUID.randomUUID().toString(); + stringRedisTemplate.opsForValue().set(key, username, 3600, TimeUnit.SECONDS); + return key; + } + + /** + * http://localhost:8080/user/current + * + * @param token + * @return + */ + @GetMapping("/current") + public String current(@RequestHeader String token) { + return "当前登录的是:" + stringRedisTemplate.opsForValue().get(token); + } + + /** + * http://localhost:8080/user/invalidate + * + * @param token + * @return + */ + @GetMapping("/invalidate") + public String invalidate(@RequestHeader String token) { + System.out.println("失效前 sessionId:" + token); + stringRedisTemplate.delete(token); + System.out.println("失效后 sessionId:" + null); + System.out.println("--------------------------------"); + return "session已失效" + " || sessionId:" + token; + } +} diff --git a/distributed/session/redis-session/src/main/resources/application.yml b/distributed/session/redis-session/src/main/resources/application.yml new file mode 100644 index 00000000..09cc596a --- /dev/null +++ b/distributed/session/redis-session/src/main/resources/application.yml @@ -0,0 +1,4 @@ +spring: + redis: + host: 127.0.0.1 + port: 6379 \ No newline at end of file diff --git a/distributed/session/redis-session/src/test/java/cn/cunchang/ApplicationTests.java b/distributed/session/redis-session/src/test/java/cn/cunchang/ApplicationTests.java new file mode 100644 index 00000000..c13144bc --- /dev/null +++ b/distributed/session/redis-session/src/test/java/cn/cunchang/ApplicationTests.java @@ -0,0 +1,13 @@ +package cn.cunchang; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/distributed/session/spring-session/pom.xml b/distributed/session/spring-session/pom.xml new file mode 100644 index 00000000..99f73e3d --- /dev/null +++ b/distributed/session/spring-session/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.3.3.RELEASE + + + cn.cuchang + spring-session + 0.0.1-SNAPSHOT + spring-session + spring-session + + 1.8 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.springframework.session + spring-session-data-redis + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/distributed/session/spring-session/src/main/java/cn/cuchang/Application.java b/distributed/session/spring-session/src/main/java/cn/cuchang/Application.java new file mode 100644 index 00000000..2b694e6a --- /dev/null +++ b/distributed/session/spring-session/src/main/java/cn/cuchang/Application.java @@ -0,0 +1,15 @@ +package cn.cuchang; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; + +@EnableRedisHttpSession +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/distributed/session/spring-session/src/main/java/cn/cuchang/controller/UserController.java b/distributed/session/spring-session/src/main/java/cn/cuchang/controller/UserController.java new file mode 100644 index 00000000..cae5fc84 --- /dev/null +++ b/distributed/session/spring-session/src/main/java/cn/cuchang/controller/UserController.java @@ -0,0 +1,64 @@ +package cn.cuchang.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpSession; + +@RequestMapping("/user") +@RestController +public class UserController { + + /** + * spring-session 与 tomcat-session 机制相同 + * request headers Cookie: JSESSIONID=2BB312D30D6F1246412D081615906D3B; SESSION=ZWJmNjliNDEtZWYxNy00NDg5LWJkZTktMjVkZGRlMzg3NjRl + * response headers Set-Cookie: SESSION=MzE2ZmE1YzMtMzQ0ZC00ZDQ1LWJlYTgtN2NiZGNmMWVlODk4; Path=/; HttpOnly; SameSite=Lax + * + */ + + /** + * http://localhost:8080/user/login?username=admin&password=123456 + * + * @param username + * @param session + * @return + */ + @GetMapping("/login") + public String login(@RequestParam String username, @RequestParam String password, HttpSession session) { + //账号密码正确 + session.setAttribute("login_user", username); + return "登录成功" + " || sessionId:" + session.getId(); + } + + + /** + * http://localhost:8080/user/current + * + * @param session + * @return + */ + @GetMapping("/current") + public String current(HttpSession session) { + return "当前登录的是:" + session.getAttribute("login_user") + " || sessionId:" + session.getId(); + } + + + /** + * http://localhost:8080/user/invalidate + * + * @param session + * @return + */ + @GetMapping("/invalidate") + public String invalidate(HttpSession session) { + System.out.println("失效前 sessionId:" + session.getId()); + session.invalidate(); + System.out.println("失效后 sessionId:" + session.getId()); + System.out.println("--------------------------------"); + return "session已失效" + " || sessionId:" + session.getId(); + } + + +} diff --git a/distributed/session/spring-session/src/main/resources/application.yml b/distributed/session/spring-session/src/main/resources/application.yml new file mode 100644 index 00000000..d6b60a18 --- /dev/null +++ b/distributed/session/spring-session/src/main/resources/application.yml @@ -0,0 +1,9 @@ +spring: + redis: + host: 127.0.0.1 + port: 6379 + session: + store-type: redis + timeout: 3600 + redis: + namespace: login_user #前缀 diff --git a/distributed/session/spring-session/src/test/java/cn/cuchang/ApplicationTests.java b/distributed/session/spring-session/src/test/java/cn/cuchang/ApplicationTests.java new file mode 100644 index 00000000..280d4bdf --- /dev/null +++ b/distributed/session/spring-session/src/test/java/cn/cuchang/ApplicationTests.java @@ -0,0 +1,13 @@ +package cn.cuchang; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/distributed/session/tomcat-session/pom.xml b/distributed/session/tomcat-session/pom.xml new file mode 100644 index 00000000..75ef685e --- /dev/null +++ b/distributed/session/tomcat-session/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.3.3.RELEASE + + + cn.cuchang + tomcat-session + 0.0.1-SNAPSHOT + tomcat-session + tomcat-session + + 1.8 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/distributed/session/tomcat-session/src/main/java/cn/cuchang/Application.java b/distributed/session/tomcat-session/src/main/java/cn/cuchang/Application.java new file mode 100644 index 00000000..04b96533 --- /dev/null +++ b/distributed/session/tomcat-session/src/main/java/cn/cuchang/Application.java @@ -0,0 +1,13 @@ +package cn.cuchang; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/distributed/session/tomcat-session/src/main/java/cn/cuchang/controller/UserController.java b/distributed/session/tomcat-session/src/main/java/cn/cuchang/controller/UserController.java new file mode 100644 index 00000000..de58137a --- /dev/null +++ b/distributed/session/tomcat-session/src/main/java/cn/cuchang/controller/UserController.java @@ -0,0 +1,61 @@ +package cn.cuchang.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpSession; + +@RequestMapping("/user") +@RestController +public class UserController { + + /** + * http://localhost:8080/user/login?username=admin&password=123456 + * + * @param username + * @param session + * @return + */ + @GetMapping("/login") + public String login(@RequestParam String username, @RequestParam String password, HttpSession session) { + //账号密码正确 + session.setAttribute("login_user", username); + return "登录成功" + " || sessionId:" + session.getId(); + } + + + /** + * http://localhost:8080/user/current + * + * @param session + * @return + */ + @GetMapping("/current") + public String current(HttpSession session) { + return "当前登录的是:" + session.getAttribute("login_user") + " || sessionId:" + session.getId(); + } + + + /** + * http://localhost:8080/user/invalidate + *

+ * 浏览器每次请求都会携带cookie,服务器端重新设置cookie + * request headers Cookie: JSESSIONID=2BB312D30D6F1246412D081615906D3B + * response headers Set-Cookie: JSESSIONID=9A7E034F309B2B0616737CA9937030D7; Path=/; HttpOnly + * + * @param session + * @return + */ + @GetMapping("/invalidate") + public String invalidate(HttpSession session) { + System.out.println("失效前 sessionId:" + session.getId()); + session.invalidate(); + System.out.println("失效后 sessionId:" + session.getId()); + System.out.println("--------------------------------"); + return "session已失效" + " || sessionId:" + session.getId(); + } + + +} diff --git a/springboot-integration-examples/springboot-banner/src/main/resources/application.properties b/distributed/session/tomcat-session/src/main/resources/application.properties similarity index 100% rename from springboot-integration-examples/springboot-banner/src/main/resources/application.properties rename to distributed/session/tomcat-session/src/main/resources/application.properties diff --git a/distributed/session/tomcat-session/src/test/java/cn/cuchang/ApplicationTests.java b/distributed/session/tomcat-session/src/test/java/cn/cuchang/ApplicationTests.java new file mode 100644 index 00000000..280d4bdf --- /dev/null +++ b/distributed/session/tomcat-session/src/test/java/cn/cuchang/ApplicationTests.java @@ -0,0 +1,13 @@ +package cn.cuchang; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/distributed/sharding-sphere/ShardingSphereDemo/README.md b/distributed/sharding-sphere/ShardingSphereDemo/README.md new file mode 100644 index 00000000..05185ddf --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/README.md @@ -0,0 +1,216 @@ + +application.properties;这个是真正用的配置,运行哪个demo,把01、02等等的配置copy就行了 + +# application01.properties; +分表,用到了一库两表 +```sql +CREATE TABLE course_1 ( + cid BIGINT(20) PRIMARY KEY, + cname VARCHAR(50) NOT NULL, + user_id BIGINT(20) NOT NULL, + cstatus varchar(10) NOT NULL +); + +CREATE TABLE course_2 ( + cid BIGINT(20) PRIMARY KEY, + cname VARCHAR(50) NOT NULL, + user_id BIGINT(20) NOT NULL, + cstatus varchar(10) NOT NULL +); +``` + + +```properties +#配置数据源 +# 数据源名称 +spring.shardingsphere.datasource.names=m1 + +spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource +spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver +spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/coursedb?serverTimezone=GMT%2B8 +spring.shardingsphere.datasource.m1.username=root +spring.shardingsphere.datasource.m1.password=123456 +#配置真实表分布 +spring.shardingsphere.sharding.tables.course.actual-data-nodes=m1.course_$->{1..2} +#主键生成策略 +# 主键字段名 +spring.shardingsphere.sharding.tables.course.key-generator.column=cid +# 主键生成算法 +spring.shardingsphere.sharding.tables.course.key-generator.type=SNOWFLAKE +# 雪花算法的参数 +spring.shardingsphere.sharding.tables.course.key-generator.props.worker.id=1 +#配置分表策略 +spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid +spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid%2+1} +#其他运行属性 +spring.shardingsphere.props.sql.show = true +spring.main.allow-bean-definition-overriding=true +``` + + + +# application02.properties; + +分库,用到了一个两库两表 + +```properties +#配置多个数据源 +spring.shardingsphere.datasource.names=m1,m2 + +spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource +spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver +spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/coursedb?serverTimezone=GMT%2B8 +spring.shardingsphere.datasource.m1.username=root +spring.shardingsphere.datasource.m1.password=123456 + +spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource +spring.shardingsphere.datasource.m2.driver-class-name=com.mysql.cj.jdbc.Driver +spring.shardingsphere.datasource.m2.url=jdbc:mysql://localhost:3306/coursedb2?serverTimezone=GMT%2B8 +spring.shardingsphere.datasource.m2.username=root +spring.shardingsphere.datasource.m2.password=123456 +#真实表分布,分库,分表 +spring.shardingsphere.sharding.tables.course.actual-data-nodes=m$->{1..2}.course_$->{1..2} + +#主键生成策略 +# 主键字段名 +spring.shardingsphere.sharding.tables.course.key-generator.column=cid +# 主键生成算法 +spring.shardingsphere.sharding.tables.course.key-generator.type=SNOWFLAKE +# 雪花算法的参数 +spring.shardingsphere.sharding.tables.course.key-generator.props.worker.id=1 +#配置分表策略 +spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid +spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid%2+1} +#其他运行属性 +spring.shardingsphere.props.sql.show = true +spring.main.allow-bean-definition-overriding=true +``` + + + +## inline策略不支持范围查询 +```properties +#inline分片策略 +spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid +spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid%2+1} +#inline分库策略 +spring.shardingsphere.sharding.tables.course.database-strategy.inline.sharding-column=cid +spring.shardingsphere.sharding.tables.course.database-strategy.inline.algorithm-expression=m$->{cid%2+1} +``` + +```text +org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: +### Error querying database. Cause: java.lang.IllegalStateException: Inline strategy cannot support this type sharding:RangeRouteValue(columnName=cid, tableName=course, valueRange=[730100102537940992‥730100102990925824]) +### The error may exist in com/roy/shardingDemo/mapper/CourseMapper.java (best guess) +### The error may involve defaultParameterMap +### The error occurred while setting parameters +### SQL: SELECT cid,cname,user_id,cstatus FROM course WHERE cid BETWEEN ? AND ? ORDER BY cid DESC +### Cause: java.lang.IllegalStateException: Inline strategy cannot support this type sharding:RangeRouteValue(columnName=cid, tableName=course, valueRange=[730100102537940992‥730100102990925824]) + + at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:77) + at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446) + at com.sun.proxy.$Proxy61.selectList(Unknown Source) + at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:230) + at com.baomidou.mybatisplus.core.override.PageMapperMethod.executeForMany(PageMapperMethod.java:173) + at com.baomidou.mybatisplus.core.override.PageMapperMethod.execute(PageMapperMethod.java:86) + at com.baomidou.mybatisplus.core.override.PageMapperProxy.invoke(PageMapperProxy.java:64) + at com.sun.proxy.$Proxy68.selectList(Unknown Source) + at com.roy.shardingDemo.ShardingJDBCTest.queryCourse(ShardingJDBCTest.java:56) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56) + at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) +``` + +## standard标准分片策略 +解决inline策略不支持范围查询 + + +```properties +#standard标准分片策略 +spring.shardingsphere.sharding.tables.course.table-strategy.standard.sharding-column=cid +spring.shardingsphere.sharding.tables.course.table-strategy.standard.precise-algorithm-class-name=com.roy.shardingDemo.algorithem.MyPreciseTableShardingAlgorithm +spring.shardingsphere.sharding.tables.course.table-strategy.standard.range-algorithm-class-name=com.roy.shardingDemo.algorithem.MyRangeTableShardingAlgorithm + +spring.shardingsphere.sharding.tables.course.database-strategy.standard.sharding-column=cid +spring.shardingsphere.sharding.tables.course.database-strategy.standard.precise-algorithm-class-name=com.roy.shardingDemo.algorithem.MyPreciseDSShardingAlgorithm +spring.shardingsphere.sharding.tables.course.database-strategy.standard.range-algorithm-class-name=com.roy.shardingDemo.algorithem.MyRangeDSShardingAlgorithm +``` + +standard标准分片策略支持自己根据一个分片键,实现精确和范围选择实际库表的逻辑 +缺点:多个分片键字段的复杂查询,会扫全库全表 + + + +## complex复杂分片策略 + +支持自己根据多个分片键分片键,选择实际库表的逻辑 + +```properties +#complex复杂分片策略 +spring.shardingsphere.sharding.tables.course.table-strategy.complex.sharding-columns= cid, user_id +spring.shardingsphere.sharding.tables.course.table-strategy.complex.algorithm-class-name=com.roy.shardingDemo.algorithem.MyComplexTableShardingAlgorithm + +spring.shardingsphere.sharding.tables.course.database-strategy.complex.sharding-columns=cid, user_id +spring.shardingsphere.sharding.tables.course.database-strategy.complex.algorithm-class-name=com.roy.shardingDemo.algorithem.MyComplexDSShardingAlgorithm +``` + + + +## hint强制路由策略 + +强制路由 + +```properties +#hint强制路由策略 +spring.shardingsphere.sharding.tables.course.table-strategy.hint.algorithm-class-name=com.roy.shardingDemo.algorithem.MyHintTableShardingAlgorithm +``` + + + +# application03.properties + +绑定表 + + + +# application04.properties + +读写分离 + +```properties +#配置主从数据源,要基于MySQL主从架构。 +spring.shardingsphere.datasource.names=m0,s0 + +spring.shardingsphere.datasource.m0.type=com.alibaba.druid.pool.DruidDataSource +spring.shardingsphere.datasource.m0.driver-class-name=com.mysql.cj.jdbc.Driver +spring.shardingsphere.datasource.m0.url=jdbc:mysql://localhost:3307/masterdemo?serverTimezone=GMT%2B8 +spring.shardingsphere.datasource.m0.username=root +spring.shardingsphere.datasource.m0.password=123456 + +spring.shardingsphere.datasource.s0.type=com.alibaba.druid.pool.DruidDataSource +spring.shardingsphere.datasource.s0.driver-class-name=com.mysql.cj.jdbc.Driver +spring.shardingsphere.datasource.s0.url=jdbc:mysql://localhost:3308/masterdemo?serverTimezone=GMT%2B8 +spring.shardingsphere.datasource.s0.username=root +spring.shardingsphere.datasource.s0.password=123456 +#读写分离规则, m0 主库,s0 从库 +spring.shardingsphere.sharding.master-slave-rules.ds0.master-data-source-name=m0 +spring.shardingsphere.sharding.master-slave-rules.ds0.slave-data-source-names[0]=s0 +#基于读写分离的表分片 +spring.shardingsphere.sharding.tables.t_dict.actual-data-nodes=ds0.t_dict + +spring.shardingsphere.sharding.tables.t_dict.key-generator.column=dict_id +spring.shardingsphere.sharding.tables.t_dict.key-generator.type=SNOWFLAKE +spring.shardingsphere.sharding.tables.t_dict.key-generator.props.worker.id=1 + +spring.shardingsphere.props.sql.show = true +spring.main.allow-bean-definition-overriding=true +``` + +# application05.properties +主从读写分离 + diff --git a/distributed/sharding-sphere/ShardingSphereDemo/pom.xml b/distributed/sharding-sphere/ShardingSphereDemo/pom.xml new file mode 100644 index 00000000..fdeb5778 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/pom.xml @@ -0,0 +1,64 @@ + + + 4.0.0 + + com.roy + ShardingSphereDemo + 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + + + + + org.springframework.boot + spring-boot-dependencies + 2.3.1.RELEASE + pom + import + + + + + + + org.apache.shardingsphere + sharding-jdbc-spring-boot-starter + 4.1.1 + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-test + + + com.alibaba + druid + 1.1.22 + + + mysql + mysql-connector-java + + + com.baomidou + mybatis-plus-boot-starter + 3.0.5 + + + \ No newline at end of file diff --git a/distributed/sharding-sphere/ShardingSphereDemo/sql/course.sql b/distributed/sharding-sphere/ShardingSphereDemo/sql/course.sql new file mode 100644 index 00000000..bf0fdafa --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/sql/course.sql @@ -0,0 +1,13 @@ +CREATE TABLE course_1 ( + cid BIGINT(20) PRIMARY KEY, + cname VARCHAR(50) NOT NULL, + user_id BIGINT(20) NOT NULL, + cstatus varchar(10) NOT NULL +); + +CREATE TABLE course_2 ( + cid BIGINT(20) PRIMARY KEY, + cname VARCHAR(50) NOT NULL, + user_id BIGINT(20) NOT NULL, + cstatus varchar(10) NOT NULL +); \ No newline at end of file diff --git a/distributed/sharding-sphere/ShardingSphereDemo/sql/t_dict.sql b/distributed/sharding-sphere/ShardingSphereDemo/sql/t_dict.sql new file mode 100644 index 00000000..5b49e836 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/sql/t_dict.sql @@ -0,0 +1,17 @@ +-- 在三个库中创建 +CREATE TABLE `t_dict` ( + `dict_id` bigint(0) PRIMARY KEY NOT NULL, + `ustatus` varchar(100) NOT NULL, + `uvalue` varchar(100) NOT NULL +); +-- 在userdb中创建 +CREATE TABLE `t_dict_1` ( + `dict_id` bigint(0) PRIMARY KEY NOT NULL, + `ustatus` varchar(100) NOT NULL, + `uvalue` varchar(100) NOT NULL +); +CREATE TABLE `t_dict_2` ( + `dict_id` bigint(0) PRIMARY KEY NOT NULL, + `ustatus` varchar(100) NOT NULL, + `uvalue` varchar(100) NOT NULL +); \ No newline at end of file diff --git a/distributed/sharding-sphere/ShardingSphereDemo/sql/t_user.sql b/distributed/sharding-sphere/ShardingSphereDemo/sql/t_user.sql new file mode 100644 index 00000000..1af8f8e4 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/sql/t_user.sql @@ -0,0 +1,20 @@ +-- 在userdb中创建 +CREATE TABLE `t_user` ( + `user_id` bigint(0) PRIMARY KEY NOT NULL, + `username` varchar(100) NOT NULL, + `ustatus` varchar(50) NOT NULL, + `uage` int(3) +); + +CREATE TABLE `t_user_1` ( + `user_id` bigint(0) PRIMARY KEY NOT NULL, + `username` varchar(100) NOT NULL, + `ustatus` varchar(50) NOT NULL, + `uage` int(3) +); +CREATE TABLE `t_user_2` ( + `user_id` bigint(0) PRIMARY KEY NOT NULL, + `username` varchar(100) NOT NULL, + `ustatus` varchar(50) NOT NULL, + `uage` int(3) +); \ No newline at end of file diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/ShardingJDBCApplication.java b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/ShardingJDBCApplication.java new file mode 100644 index 00000000..e413dcf1 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/ShardingJDBCApplication.java @@ -0,0 +1,19 @@ +package com.roy.shardingDemo; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author :楼兰 + * @date :Created in 2021/1/4 + * @description: + **/ + +@MapperScan("com.roy.shardingDemo.mapper") +@SpringBootApplication +public class ShardingJDBCApplication { + public static void main(String[] args) { + SpringApplication.run(ShardingJDBCApplication.class,args); + } +} diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyComplexDSShardingAlgorithm.java b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyComplexDSShardingAlgorithm.java new file mode 100644 index 00000000..851cc6b6 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyComplexDSShardingAlgorithm.java @@ -0,0 +1,42 @@ +package com.roy.shardingDemo.algorithem; + +import com.google.common.collect.Range; +import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm; +import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * @author :楼兰 + * @date :Created in 2021/1/6 + * @description: + **/ + +public class MyComplexDSShardingAlgorithm implements ComplexKeysShardingAlgorithm { +// SELECT cid,cname,user_id,cstatus FROM course +// WHERE cid BETWEEN ? AND ? AND user_id = ? + @Override + public Collection doSharding(Collection availableTargetNames, ComplexKeysShardingValue shardingValue) { + Range cidRange = shardingValue.getColumnNameAndRangeValuesMap().get("cid"); + Collection userIdCol = shardingValue.getColumnNameAndShardingValuesMap().get("user_id"); + + Long upperVal = cidRange.upperEndpoint(); + Long lowerVal = cidRange.lowerEndpoint(); + + List res = new ArrayList<>(); + + for(Long userId: userIdCol){ + //course_{userID%2+1} + BigInteger userIdB = BigInteger.valueOf(userId); + BigInteger target = (userIdB.mod(new BigInteger("2"))).add(new BigInteger("1")); + + res.add("m"+target); + } + + return res; + } +} diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyComplexTableShardingAlgorithm.java b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyComplexTableShardingAlgorithm.java new file mode 100644 index 00000000..e1843996 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyComplexTableShardingAlgorithm.java @@ -0,0 +1,39 @@ +package com.roy.shardingDemo.algorithem; + +import com.google.common.collect.Range; +import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm; +import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author :楼兰 + * @date :Created in 2021/1/6 + * @description: + **/ + +public class MyComplexTableShardingAlgorithm implements ComplexKeysShardingAlgorithm { + @Override + public Collection doSharding(Collection availableTargetNames, ComplexKeysShardingValue shardingValue) { + Range cidRange = shardingValue.getColumnNameAndRangeValuesMap().get("cid"); + Collection userIdCol = shardingValue.getColumnNameAndShardingValuesMap().get("user_id"); + + Long upperVal = cidRange.upperEndpoint(); + Long lowerVal = cidRange.lowerEndpoint(); + + List res = new ArrayList<>(); + + for(Long userId: userIdCol){ + //course_{userID%2+1} + BigInteger userIdB = BigInteger.valueOf(userId); + BigInteger target = (userIdB.mod(new BigInteger("2"))).add(new BigInteger("1")); + + res.add(shardingValue.getLogicTableName()+"_"+target); + } + + return res; + } +} diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyHintTableShardingAlgorithm.java b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyHintTableShardingAlgorithm.java new file mode 100644 index 00000000..9152eaf6 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyHintTableShardingAlgorithm.java @@ -0,0 +1,24 @@ +package com.roy.shardingDemo.algorithem; + +import org.apache.shardingsphere.api.sharding.hint.HintShardingAlgorithm; +import org.apache.shardingsphere.api.sharding.hint.HintShardingValue; + +import java.util.Arrays; +import java.util.Collection; + +/** + * @author :楼兰 + * @date :Created in 2021/1/6 + * @description: + **/ + +public class MyHintTableShardingAlgorithm implements HintShardingAlgorithm { + @Override + public Collection doSharding(Collection availableTargetNames, HintShardingValue shardingValue) { + String key = shardingValue.getLogicTableName() + "_" + shardingValue.getValues().toArray()[0]; + if(availableTargetNames.contains(key)){ + return Arrays.asList(key); + } + throw new UnsupportedOperationException("route "+ key +" is not supported ,please check your config"); + } +} diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyPreciseDSShardingAlgorithm.java b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyPreciseDSShardingAlgorithm.java new file mode 100644 index 00000000..7bb72a21 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyPreciseDSShardingAlgorithm.java @@ -0,0 +1,32 @@ +package com.roy.shardingDemo.algorithem; + +import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm; +import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue; + +import java.math.BigInteger; +import java.util.Collection; + +/** + * @author :楼兰 + * @date :Created in 2021/1/6 + * @description: + **/ + +public class MyPreciseDSShardingAlgorithm implements PreciseShardingAlgorithm { + //select * from course where cid = ? or cid in (?,?) + @Override + public String doSharding(Collection availableTargetNames, PreciseShardingValue shardingValue) { + String logicTableName = shardingValue.getLogicTableName(); + String cid = shardingValue.getColumnName(); + Long cidValue = shardingValue.getValue(); + //实现 course_$->{cid%2+1) + BigInteger shardingValueB = BigInteger.valueOf(cidValue); + BigInteger resB = (shardingValueB.mod(new BigInteger("2"))).add(new BigInteger("1")); + String key = "m"+resB; + if(availableTargetNames.contains(key)){ + return key; + } + //couse_1, course_2 + throw new UnsupportedOperationException("route "+ key +" is not supported ,please check your config"); + } +} diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyPreciseTableShardingAlgorithm.java b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyPreciseTableShardingAlgorithm.java new file mode 100644 index 00000000..09be0830 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyPreciseTableShardingAlgorithm.java @@ -0,0 +1,38 @@ +package com.roy.shardingDemo.algorithem; + +import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm; +import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue; + +import java.math.BigInteger; +import java.util.Collection; + +/** + * @author :楼兰 + * @date :Created in 2021/1/6 + * @description: + **/ + +public class MyPreciseTableShardingAlgorithm implements PreciseShardingAlgorithm { + + /** + * select * from course where cid = ? or cid in (?,?) + * @param availableTargetNames 真实表 course_1、course_2 + * @param shardingValue 精确条件值 + * @return 查询条件选中的真实表 course_1 or course_2 + */ + @Override + public String doSharding(Collection availableTargetNames, PreciseShardingValue shardingValue) { + String logicTableName = shardingValue.getLogicTableName(); + String cid = shardingValue.getColumnName(); + Long cidValue = shardingValue.getValue(); + //实现 course_$->{cid%2+1) + BigInteger shardingValueB = BigInteger.valueOf(cidValue); + BigInteger resB = (shardingValueB.mod(new BigInteger("2"))).add(new BigInteger("1")); + String key = logicTableName+"_"+resB; + if(availableTargetNames.contains(key)){ + return key; + } + //couse_1, course_2 + throw new UnsupportedOperationException("route "+ key +" is not supported ,please check your config"); + } +} diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyRangeDSShardingAlgorithm.java b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyRangeDSShardingAlgorithm.java new file mode 100644 index 00000000..0b44e4c1 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyRangeDSShardingAlgorithm.java @@ -0,0 +1,25 @@ +package com.roy.shardingDemo.algorithem; + +import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm; +import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue; + +import java.util.Arrays; +import java.util.Collection; + +/** + * @author :楼兰 + * @date :Created in 2021/1/6 + * @description: + **/ + +public class MyRangeDSShardingAlgorithm implements RangeShardingAlgorithm { + @Override + public Collection doSharding(Collection availableTargetNames, RangeShardingValue shardingValue) { + //select * from course where cid between 1 and 100; + Long upperVal = shardingValue.getValueRange().upperEndpoint();//100 + Long lowerVal = shardingValue.getValueRange().lowerEndpoint();//1 + + String logicTableName = shardingValue.getLogicTableName(); + return Arrays.asList("m1","m2"); + } +} diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyRangeTableShardingAlgorithm.java b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyRangeTableShardingAlgorithm.java new file mode 100644 index 00000000..762ead06 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/algorithem/MyRangeTableShardingAlgorithm.java @@ -0,0 +1,32 @@ +package com.roy.shardingDemo.algorithem; + +import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm; +import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue; +import sun.rmi.runtime.Log; + +import java.util.Arrays; +import java.util.Collection; + +/** + * @author :楼兰 + * @date :Created in 2021/1/6 + * @description: + **/ + +public class MyRangeTableShardingAlgorithm implements RangeShardingAlgorithm { + /** + * select * from course where cid between 1 and 100; + * @param availableTargetNames 真实表 course_1、course_2 + * @param shardingValue 范围条件值 + * @return 查询条件选中的真实表 course_1、course_2 + */ + @Override + public Collection doSharding(Collection availableTargetNames, RangeShardingValue shardingValue) { + + Long upperVal = shardingValue.getValueRange().upperEndpoint();//100 + Long lowerVal = shardingValue.getValueRange().lowerEndpoint();//1 + + String logicTableName = shardingValue.getLogicTableName(); + return Arrays.asList(logicTableName+"_1",logicTableName+"_2"); + } +} diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/entity/Course.java b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/entity/Course.java new file mode 100644 index 00000000..1ed83084 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/entity/Course.java @@ -0,0 +1,57 @@ +package com.roy.shardingDemo.entity; + +/** + * @author :楼兰 + * @date :Created in 2021/1/4 + * @description: + **/ + +public class Course { + + private Long cid; + private String cname; + private Long userId; + private String cstatus; + + public Long getCid() { + return cid; + } + + public void setCid(Long cid) { + this.cid = cid; + } + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getCstatus() { + return cstatus; + } + + public void setCstatus(String cstatus) { + this.cstatus = cstatus; + } + + @Override + public String toString() { + return "Course{" + + "cid=" + cid + + ", cname='" + cname + '\'' + + ", userId=" + userId + + ", cstatus='" + cstatus + '\'' + + '}'; + } +} diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/entity/Dict.java b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/entity/Dict.java new file mode 100644 index 00000000..e1271491 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/entity/Dict.java @@ -0,0 +1,48 @@ +package com.roy.shardingDemo.entity; + +import com.baomidou.mybatisplus.annotation.TableName; + +/** + * @author :楼兰 + * @date :Created in 2021/1/5 + * @description: + **/ +@TableName("t_dict") +public class Dict { + private Long dictId; + private String ustatus; + private String uvalue; + + public Long getDictId() { + return dictId; + } + + public void setDictId(Long dictId) { + this.dictId = dictId; + } + + public String getUstatus() { + return ustatus; + } + + public void setUstatus(String ustatus) { + this.ustatus = ustatus; + } + + public String getUvalue() { + return uvalue; + } + + public void setUvalue(String uvalue) { + this.uvalue = uvalue; + } + + @Override + public String toString() { + return "Dict{" + + "dictId=" + dictId + + ", ustatus='" + ustatus + '\'' + + ", uvalue='" + uvalue + '\'' + + '}'; + } +} diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/entity/User.java b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/entity/User.java new file mode 100644 index 00000000..cbdaddd5 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/entity/User.java @@ -0,0 +1,59 @@ +package com.roy.shardingDemo.entity; + +import com.baomidou.mybatisplus.annotation.TableName; + +/** + * @author :楼兰 + * @date :Created in 2021/1/5 + * @description: + **/ +@TableName("user") +public class User { + + private Long userId; + private String username; + private String ustatus; + private int uage; + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getUstatus() { + return ustatus; + } + + public void setUstatus(String ustatus) { + this.ustatus = ustatus; + } + + public int getUage() { + return uage; + } + + public void setUage(int uage) { + this.uage = uage; + } + + @Override + public String toString() { + return "User{" + + "userId=" + userId + + ", username='" + username + '\'' + + ", ustatus='" + ustatus + '\'' + + ", uage=" + uage + + '}'; + } +} diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/mapper/CourseMapper.java b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/mapper/CourseMapper.java new file mode 100644 index 00000000..2155b1e0 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/mapper/CourseMapper.java @@ -0,0 +1,13 @@ +package com.roy.shardingDemo.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.roy.shardingDemo.entity.Course; + +/** + * @author :楼兰 + * @date :Created in 2021/1/4 + * @description: + **/ + +public interface CourseMapper extends BaseMapper { +} diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/mapper/DictMapper.java b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/mapper/DictMapper.java new file mode 100644 index 00000000..7ad36404 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/mapper/DictMapper.java @@ -0,0 +1,12 @@ +package com.roy.shardingDemo.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.roy.shardingDemo.entity.Dict; + +/** + * @author :楼兰 + * @date :Created in 2021/1/5 + * @description: + **/ +public interface DictMapper extends BaseMapper { +} diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/mapper/UserMapper.java b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/mapper/UserMapper.java new file mode 100644 index 00000000..9a66da47 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/java/com/roy/shardingDemo/mapper/UserMapper.java @@ -0,0 +1,18 @@ +package com.roy.shardingDemo.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.roy.shardingDemo.entity.User; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * @author :楼兰 + * @date :Created in 2021/1/5 + * @description: + **/ +public interface UserMapper extends BaseMapper { + + @Select("select u.user_id,u.username,d.uvalue ustatus from user u left join t_dict d on u.ustatus = d.ustatus") + public List queryUserStatus(); +} diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application.properties b/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application.properties new file mode 100644 index 00000000..839026ac --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application.properties @@ -0,0 +1,29 @@ +spring.shardingsphere.datasource.names=m1 + +spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource +spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver +spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/coursedb?serverTimezone=GMT%2B8 +spring.shardingsphere.datasource.m1.username=root +spring.shardingsphere.datasource.m1.password=123456 + + +spring.shardingsphere.sharding.tables.t_dict.actual-data-nodes=m1.t_dict_$->{1..2} + +spring.shardingsphere.sharding.tables.t_dict.key-generator.column=dict_id +spring.shardingsphere.sharding.tables.t_dict.key-generator.type=SNOWFLAKE +spring.shardingsphere.sharding.tables.t_dict.key-generator.props.worker.id=1 +spring.shardingsphere.sharding.tables.t_dict.table-strategy.inline.sharding-column=ustatus +spring.shardingsphere.sharding.tables.t_dict.table-strategy.inline.algorithm-expression=t_dict_$->{ustatus.toInteger()%2+1} + +spring.shardingsphere.sharding.tables.user.actual-data-nodes=m1.t_user_$->{1..2} +spring.shardingsphere.sharding.tables.user.key-generator.column=user_id +spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE +spring.shardingsphere.sharding.tables.user.key-generator.props.worker.id=1 +spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=ustatus +spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=t_user_$->{ustatus.toInteger()%2+1} +#\u7ED1\u5B9A\u8868\u793A\u4F8B +spring.shardingsphere.sharding.binding-tables[0]=user,t_dict + +spring.shardingsphere.props.sql.show = true +spring.main.allow-bean-definition-overriding=true + diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application01.properties b/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application01.properties new file mode 100644 index 00000000..cdbfcca4 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application01.properties @@ -0,0 +1,25 @@ +#\u914D\u7F6E\u6570\u636E\u6E90 +# \u6570\u636E\u6E90\u540D\u79F0 +spring.shardingsphere.datasource.names=m1 + +spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource +spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver +spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/coursedb?serverTimezone=GMT%2B8 +spring.shardingsphere.datasource.m1.username=root +spring.shardingsphere.datasource.m1.password=123456 +#\u914D\u7F6E\u771F\u5B9E\u8868\u5206\u5E03 +spring.shardingsphere.sharding.tables.course.actual-data-nodes=m1.course_$->{1..2} +#\u4E3B\u952E\u751F\u6210\u7B56\u7565 +# \u4E3B\u952E\u5B57\u6BB5\u540D +spring.shardingsphere.sharding.tables.course.key-generator.column=cid +# \u4E3B\u952E\u751F\u6210\u7B97\u6CD5 +spring.shardingsphere.sharding.tables.course.key-generator.type=SNOWFLAKE +# \u96EA\u82B1\u7B97\u6CD5\u7684\u53C2\u6570 +spring.shardingsphere.sharding.tables.course.key-generator.props.worker.id=1 +#\u914D\u7F6E\u5206\u8868\u7B56\u7565 +spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid +spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid%2+1} +#\u5176\u4ED6\u8FD0\u884C\u5C5E\u6027 +spring.shardingsphere.props.sql.show = true +spring.main.allow-bean-definition-overriding=true + diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application02.properties b/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application02.properties new file mode 100644 index 00000000..d83d0dc3 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application02.properties @@ -0,0 +1,56 @@ +#\u914D\u7F6E\u591A\u4E2A\u6570\u636E\u6E90 +spring.shardingsphere.datasource.names=m1,m2 + +spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource +spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver +spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/coursedb?serverTimezone=GMT%2B8 +spring.shardingsphere.datasource.m1.username=root +spring.shardingsphere.datasource.m1.password=123456 + +spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource +spring.shardingsphere.datasource.m2.driver-class-name=com.mysql.cj.jdbc.Driver +spring.shardingsphere.datasource.m2.url=jdbc:mysql://localhost:3306/coursedb2?serverTimezone=GMT%2B8 +spring.shardingsphere.datasource.m2.username=root +spring.shardingsphere.datasource.m2.password=123456 +#\u771F\u5B9E\u8868\u5206\u5E03\uFF0C\u5206\u5E93\uFF0C\u5206\u8868 +spring.shardingsphere.sharding.tables.course.actual-data-nodes=m$->{1..2}.course_$->{1..2} + +spring.shardingsphere.sharding.tables.course.key-generator.column=cid +spring.shardingsphere.sharding.tables.course.key-generator.type=SNOWFLAKE +spring.shardingsphere.sharding.tables.course.key-generator.props.worker.id=1 + +#inline\u7B56\u7565\u4E0D\u652F\u6301\u8303\u56F4\u67E5\u8BE2 +#inline\u5206\u7247\u7B56\u7565 +spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid +spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid%2+1} +#inline\u5206\u5E93\u7B56\u7565 +spring.shardingsphere.sharding.tables.course.database-strategy.inline.sharding-column=cid +spring.shardingsphere.sharding.tables.course.database-strategy.inline.algorithm-expression=m$->{cid%2+1} + +#standard\u6807\u51C6\u5206\u7247\u7B56\u7565 +#spring.shardingsphere.sharding.tables.course.table-strategy.standard.sharding-column=cid +#spring.shardingsphere.sharding.tables.course.table-strategy.standard.precise-algorithm-class-name=com.roy.shardingDemo.algorithem.MyPreciseTableShardingAlgorithm +#spring.shardingsphere.sharding.tables.course.table-strategy.standard.range-algorithm-class-name=com.roy.shardingDemo.algorithem.MyRangeTableShardingAlgorithm +# +#spring.shardingsphere.sharding.tables.course.database-strategy.standard.sharding-column=cid +#spring.shardingsphere.sharding.tables.course.database-strategy.standard.precise-algorithm-class-name=com.roy.shardingDemo.algorithem.MyPreciseDSShardingAlgorithm +#spring.shardingsphere.sharding.tables.course.database-strategy.standard.range-algorithm-class-name=com.roy.shardingDemo.algorithem.MyRangeDSShardingAlgorithm + +##complex\u590D\u6742\u5206\u7247\u7B56\u7565 +#spring.shardingsphere.sharding.tables.course.table-strategy.complex.sharding-columns= cid, user_id +#spring.shardingsphere.sharding.tables.course.table-strategy.complex.algorithm-class-name=com.roy.shardingDemo.algorithem.MyComplexTableShardingAlgorithm +# +#spring.shardingsphere.sharding.tables.course.database-strategy.complex.sharding-columns=cid, user_id +#spring.shardingsphere.sharding.tables.course.database-strategy.complex.algorithm-class-name=com.roy.shardingDemo.algorithem.MyComplexDSShardingAlgorithm + +##hint\u5F3A\u5236\u8DEF\u7531\u7B56\u7565 +#spring.shardingsphere.sharding.tables.course.table-strategy.hint.algorithm-class-name=com.roy.shardingDemo.algorithem.MyHintTableShardingAlgorithm + +##\u5E7F\u64AD\u8868\u914D\u7F6E +#spring.shardingsphere.sharding.broadcast-tables=t_dict +#spring.shardingsphere.sharding.tables.t_dict.key-generator.column=dict_id +#spring.shardingsphere.sharding.tables.t_dict.key-generator.type=SNOWFLAKE + +spring.shardingsphere.props.sql.show = true +spring.main.allow-bean-definition-overriding=true + diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application03.properties b/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application03.properties new file mode 100644 index 00000000..839026ac --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application03.properties @@ -0,0 +1,29 @@ +spring.shardingsphere.datasource.names=m1 + +spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource +spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver +spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/coursedb?serverTimezone=GMT%2B8 +spring.shardingsphere.datasource.m1.username=root +spring.shardingsphere.datasource.m1.password=123456 + + +spring.shardingsphere.sharding.tables.t_dict.actual-data-nodes=m1.t_dict_$->{1..2} + +spring.shardingsphere.sharding.tables.t_dict.key-generator.column=dict_id +spring.shardingsphere.sharding.tables.t_dict.key-generator.type=SNOWFLAKE +spring.shardingsphere.sharding.tables.t_dict.key-generator.props.worker.id=1 +spring.shardingsphere.sharding.tables.t_dict.table-strategy.inline.sharding-column=ustatus +spring.shardingsphere.sharding.tables.t_dict.table-strategy.inline.algorithm-expression=t_dict_$->{ustatus.toInteger()%2+1} + +spring.shardingsphere.sharding.tables.user.actual-data-nodes=m1.t_user_$->{1..2} +spring.shardingsphere.sharding.tables.user.key-generator.column=user_id +spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE +spring.shardingsphere.sharding.tables.user.key-generator.props.worker.id=1 +spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=ustatus +spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=t_user_$->{ustatus.toInteger()%2+1} +#\u7ED1\u5B9A\u8868\u793A\u4F8B +spring.shardingsphere.sharding.binding-tables[0]=user,t_dict + +spring.shardingsphere.props.sql.show = true +spring.main.allow-bean-definition-overriding=true + diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application04.properties b/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application04.properties new file mode 100644 index 00000000..90cd795d --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application04.properties @@ -0,0 +1,27 @@ +#\u914D\u7F6E\u4E3B\u4ECE\u6570\u636E\u6E90\uFF0C\u8981\u57FA\u4E8EMySQL\u4E3B\u4ECE\u67B6\u6784\u3002 +spring.shardingsphere.datasource.names=m0,s0 + +spring.shardingsphere.datasource.m0.type=com.alibaba.druid.pool.DruidDataSource +spring.shardingsphere.datasource.m0.driver-class-name=com.mysql.cj.jdbc.Driver +spring.shardingsphere.datasource.m0.url=jdbc:mysql://localhost:3307/masterdemo?serverTimezone=GMT%2B8 +spring.shardingsphere.datasource.m0.username=root +spring.shardingsphere.datasource.m0.password=123456 + +spring.shardingsphere.datasource.s0.type=com.alibaba.druid.pool.DruidDataSource +spring.shardingsphere.datasource.s0.driver-class-name=com.mysql.cj.jdbc.Driver +spring.shardingsphere.datasource.s0.url=jdbc:mysql://localhost:3308/masterdemo?serverTimezone=GMT%2B8 +spring.shardingsphere.datasource.s0.username=root +spring.shardingsphere.datasource.s0.password=123456 +#\u8BFB\u5199\u5206\u79BB\u89C4\u5219\uFF0C m0 \u4E3B\u5E93\uFF0Cs0 \u4ECE\u5E93 +spring.shardingsphere.sharding.master-slave-rules.ds0.master-data-source-name=m0 +spring.shardingsphere.sharding.master-slave-rules.ds0.slave-data-source-names[0]=s0 +#\u57FA\u4E8E\u8BFB\u5199\u5206\u79BB\u7684\u8868\u5206\u7247 +spring.shardingsphere.sharding.tables.t_dict.actual-data-nodes=ds0.t_dict + +spring.shardingsphere.sharding.tables.t_dict.key-generator.column=dict_id +spring.shardingsphere.sharding.tables.t_dict.key-generator.type=SNOWFLAKE +spring.shardingsphere.sharding.tables.t_dict.key-generator.props.worker.id=1 + +spring.shardingsphere.props.sql.show = true +spring.main.allow-bean-definition-overriding=true + diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application05.properties b/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application05.properties new file mode 100644 index 00000000..2b95a865 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/main/resources/application05.properties @@ -0,0 +1,26 @@ +spring.shardingsphere.datasource.names=m0,s0 + +spring.shardingsphere.datasource.m0.type=com.alibaba.druid.pool.DruidDataSource +spring.shardingsphere.datasource.m0.driver-class-name=com.mysql.cj.jdbc.Driver +spring.shardingsphere.datasource.m0.url=jdbc:mysql://localhost:3307/masterdemo?serverTimezone=GMT%2B8 +spring.shardingsphere.datasource.m0.username=root +spring.shardingsphere.datasource.m0.password=123456 + +spring.shardingsphere.datasource.s0.type=com.alibaba.druid.pool.DruidDataSource +spring.shardingsphere.datasource.s0.driver-class-name=com.mysql.cj.jdbc.Driver +spring.shardingsphere.datasource.s0.url=jdbc:mysql://localhost:3308/masterdemo?serverTimezone=GMT%2B8 +spring.shardingsphere.datasource.s0.username=root +spring.shardingsphere.datasource.s0.password=123456 + +spring.shardingsphere.sharding.master-slave-rules.ds0.master-data-source-name=m0 +spring.shardingsphere.sharding.master-slave-rules.ds0.slave-data-source-names[0]=s0 + +spring.shardingsphere.sharding.tables.t_dict.actual-data-nodes=ds0.t_dict + +spring.shardingsphere.sharding.tables.t_dict.key-generator.column=dict_id +spring.shardingsphere.sharding.tables.t_dict.key-generator.type=SNOWFLAKE +spring.shardingsphere.sharding.tables.t_dict.key-generator.props.worker.id=1 + +spring.shardingsphere.props.sql.show = true +spring.main.allow-bean-definition-overriding=true + diff --git a/distributed/sharding-sphere/ShardingSphereDemo/src/test/java/com/roy/shardingDemo/ShardingJDBCTest.java b/distributed/sharding-sphere/ShardingSphereDemo/src/test/java/com/roy/shardingDemo/ShardingJDBCTest.java new file mode 100644 index 00000000..6d4345f4 --- /dev/null +++ b/distributed/sharding-sphere/ShardingSphereDemo/src/test/java/com/roy/shardingDemo/ShardingJDBCTest.java @@ -0,0 +1,137 @@ +package com.roy.shardingDemo; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.roy.shardingDemo.entity.Course; +import com.roy.shardingDemo.entity.Dict; +import com.roy.shardingDemo.entity.User; +import com.roy.shardingDemo.mapper.CourseMapper; +import com.roy.shardingDemo.mapper.DictMapper; +import com.roy.shardingDemo.mapper.UserMapper; +import org.apache.shardingsphere.api.hint.HintManager; +import org.junit.Test; +import org.junit.jupiter.api.Tags; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @author :楼兰 + * @date :Created in 2021/1/4 + * @description: + **/ + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ShardingJDBCTest { + @Resource + CourseMapper courseMapper; + @Resource + DictMapper dictMapper; + @Resource + UserMapper userMapper; + + @Test + public void addCourse(){ + for(int i = 0 ; i < 10 ; i ++){ + Course c = new Course(); +// c.setCid(Long.valueOf(i)); + c.setCname("shardingsphere"); + c.setUserId(Long.valueOf(""+(1000+i))); + c.setCstatus("1"); + courseMapper.insert(c); + } + } + + @Test + public void queryCourse(){ + //select * from course + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.orderByDesc("cid"); +// wrapper.eq("cid",730100102537940992L); +// wrapper.in("cid",730100102537940992L,730100102990925824L); + List courses = courseMapper.selectList(wrapper); + System.out.println("条数:"+courses.size()); + for (Course course : courses) { + System.out.println("查询结果:"+ course); + } + } + + @Test + public void queryOrderRange(){ + //select * from course + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.between("cid",730100102537940992L,730100102990925824L); +// wrapper.in() + List courses = courseMapper.selectList(wrapper); + courses.forEach(course -> System.out.println(course)); + } + + @Test + public void queryCourseComplex(){ + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.between("cid",730100102537940992L,730100102990925824L); + wrapper.eq("user_id",1004L); +// wrapper.in() + List courses = courseMapper.selectList(wrapper); + courses.forEach(course -> System.out.println(course)); + } + + @Test + public void queryCourseByHint(){ + HintManager hintManager = HintManager.getInstance(); + hintManager.addTableShardingValue("course",2); + List courses = courseMapper.selectList(null); + courses.forEach(course -> System.out.println(course)); + hintManager.close(); + } + + @Test + public void addDict(){ + Dict d1 = new Dict(); + d1.setUstatus("1"); + d1.setUvalue("正常"); + dictMapper.insert(d1); + + Dict d2 = new Dict(); + d2.setUstatus("0"); + d2.setUvalue("不正常"); + dictMapper.insert(d2); + + for(int i = 0 ; i < 10 ; i ++){ + User user = new User(); + user.setUsername("user No "+i); + user.setUstatus(""+(i%2)); + user.setUage(i*10); + userMapper.insert(user); + } + } + + @Test + public void queryUserStatus(){ + List users = userMapper.queryUserStatus(); + users.forEach(user -> System.out.println(user)); + } + + @Test + public void addDictByMS(){ + Dict d1 = new Dict(); + d1.setUstatus("1"); + d1.setUvalue("正常"); + dictMapper.insert(d1); + + Dict d2 = new Dict(); + d2.setUstatus("0"); + d2.setUvalue("不正常"); + dictMapper.insert(d2); + } + + @Test + public void queryDictByMS(){ + List dicts = dictMapper.selectList(null); + dicts.forEach(dict -> System.out.println(dict)); + } + +} diff --git a/distributed/springcloud-debug/consumer/pom.xml b/distributed/springcloud-debug/consumer/pom.xml new file mode 100644 index 00000000..4fc58712 --- /dev/null +++ b/distributed/springcloud-debug/consumer/pom.xml @@ -0,0 +1,46 @@ + + + + springcloud-debug + cn.cunchang + 1.0-SNAPSHOT + + 4.0.0 + + consumer + + + 8 + 8 + + + + + + org.springframework.boot + spring-boot-starter-web + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/distributed/springcloud-debug/consumer/src/main/java/cn/cunchang/ConsumerApplication.java b/distributed/springcloud-debug/consumer/src/main/java/cn/cunchang/ConsumerApplication.java new file mode 100644 index 00000000..01503bcb --- /dev/null +++ b/distributed/springcloud-debug/consumer/src/main/java/cn/cunchang/ConsumerApplication.java @@ -0,0 +1,30 @@ +package cn.cunchang; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@EnableFeignClients +@SpringBootApplication +public class ConsumerApplication { + + public static void main(String[] args) { + SpringApplication.run(ConsumerApplication.class, args); + } + + @Autowired + private HelloFeignClient helloFeignClient; + + @GetMapping("/sayHello") + public String test(String name) { + String result = helloFeignClient.sayHello(name); + return result; + } + +} + + diff --git a/distributed/springcloud-debug/consumer/src/main/java/cn/cunchang/HelloFeignClient.java b/distributed/springcloud-debug/consumer/src/main/java/cn/cunchang/HelloFeignClient.java new file mode 100644 index 00000000..a1c68eca --- /dev/null +++ b/distributed/springcloud-debug/consumer/src/main/java/cn/cunchang/HelloFeignClient.java @@ -0,0 +1,12 @@ +package cn.cunchang; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; + +@FeignClient(value = "producer") +public interface HelloFeignClient { + @RequestMapping(value = "/hello", method = RequestMethod.GET) + String sayHello(@RequestParam("name") String name); +} \ No newline at end of file diff --git a/distributed/springcloud-debug/consumer/src/main/resources/application.yml b/distributed/springcloud-debug/consumer/src/main/resources/application.yml new file mode 100644 index 00000000..d9beaa1e --- /dev/null +++ b/distributed/springcloud-debug/consumer/src/main/resources/application.yml @@ -0,0 +1,20 @@ +server: + port: 8055 + +spring: + application: + name: consumer #微服务名称 + + #配置nacos注册中心地址 + cloud: + nacos: + discovery: + server-addr: 127.0.0.1:8848 + + + +management: + endpoints: + web: + exposure: + include: '*' diff --git a/distributed/springcloud-debug/pom.xml b/distributed/springcloud-debug/pom.xml new file mode 100644 index 00000000..879711f2 --- /dev/null +++ b/distributed/springcloud-debug/pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + pom + + consumer + producer + + + + org.springframework.boot + spring-boot-starter-parent + 2.3.2.RELEASE + + + + cn.cunchang + springcloud-debug + 1.0-SNAPSHOT + + + 8 + 8 + Hoxton.SR8 + 2.2.5.RELEASE + + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + ${spring-cloud-alibaba.version} + pom + import + + + + + + \ No newline at end of file diff --git a/distributed/springcloud-debug/producer/pom.xml b/distributed/springcloud-debug/producer/pom.xml new file mode 100644 index 00000000..f989a257 --- /dev/null +++ b/distributed/springcloud-debug/producer/pom.xml @@ -0,0 +1,46 @@ + + + + springcloud-debug + cn.cunchang + 1.0-SNAPSHOT + + 4.0.0 + + producer + + + 8 + 8 + + + + + + org.springframework.boot + spring-boot-starter-web + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/distributed/springcloud-debug/producer/src/main/java/cn/cunchang/HelloController.java b/distributed/springcloud-debug/producer/src/main/java/cn/cunchang/HelloController.java new file mode 100644 index 00000000..692d45e4 --- /dev/null +++ b/distributed/springcloud-debug/producer/src/main/java/cn/cunchang/HelloController.java @@ -0,0 +1,13 @@ +package cn.cunchang; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloController { + @GetMapping("/hello") + public String hello(@RequestParam("name") String name) { + return "hello " + name; + } +} \ No newline at end of file diff --git a/distributed/springcloud-debug/producer/src/main/java/cn/cunchang/ProducerApplication.java b/distributed/springcloud-debug/producer/src/main/java/cn/cunchang/ProducerApplication.java new file mode 100644 index 00000000..a2983df4 --- /dev/null +++ b/distributed/springcloud-debug/producer/src/main/java/cn/cunchang/ProducerApplication.java @@ -0,0 +1,15 @@ +package cn.cunchang; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ProducerApplication { + + public static void main(String[] args) { + SpringApplication.run(ProducerApplication.class, args); + } + +} + + diff --git a/distributed/springcloud-debug/producer/src/main/resources/application.yml b/distributed/springcloud-debug/producer/src/main/resources/application.yml new file mode 100644 index 00000000..2a95114e --- /dev/null +++ b/distributed/springcloud-debug/producer/src/main/resources/application.yml @@ -0,0 +1,20 @@ +server: + port: 8056 + +spring: + application: + name: producer #微服务名称 + + #配置nacos注册中心地址 + cloud: + nacos: + discovery: + server-addr: 127.0.0.1:8848 + + + +management: + endpoints: + web: + exposure: + include: '*' diff --git a/distributed/springcloud-netflix/order/order-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/distributed/springcloud-netflix/order/order-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 00000000..a013af2f --- /dev/null +++ b/distributed/springcloud-netflix/order/order-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,8 @@ +{ + "properties": [ + { + "name": "hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds", + "type": "java.lang.String", + "description": "Description for hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds." + } +] } \ No newline at end of file diff --git a/distributed/springcloud-netflix/order/order-server/src/test/java/cn/lastwhisper/order/OrderApplicationTests.java b/distributed/springcloud-netflix/order/order-server/src/test/java/cn/lastwhisper/order/OrderApplicationTests.java index 2967ca3c..a2b55963 100644 --- a/distributed/springcloud-netflix/order/order-server/src/test/java/cn/lastwhisper/order/OrderApplicationTests.java +++ b/distributed/springcloud-netflix/order/order-server/src/test/java/cn/lastwhisper/order/OrderApplicationTests.java @@ -1,6 +1,5 @@ package cn.lastwhisper.order; -import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; diff --git a/distributed/sso/cas/Client1/pom.xml b/distributed/sso/cas/Client1/pom.xml deleted file mode 100644 index 4ce98b6f..00000000 --- a/distributed/sso/cas/Client1/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - cas - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - Client1 - war - - - UTF-8 - - - - - - org.jasig.cas.client - cas-client-core - 3.3.3 - - - javax.servlet - servlet-api - 2.5 - provided - - - - - - org.apache.tomcat.maven - tomcat7-maven-plugin - 2.2 - - - 9001 - - / - - - - - \ No newline at end of file diff --git a/distributed/sso/cas/Client1/src/main/webapp/WEB-INF/web.xml b/distributed/sso/cas/Client1/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index dc8e8dcd..00000000 --- a/distributed/sso/cas/Client1/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - org.jasig.cas.client.session.SingleSignOutHttpSessionListener - - - - - CAS Single Sign Out Filter - org.jasig.cas.client.session.SingleSignOutFilter - - - CAS Single Sign Out Filter - /* - - - - - CASFilter - org.jasig.cas.client.authentication.AuthenticationFilter - - casServerLoginUrl - http://localhost:8080/cas/login - - - - serverName - http://localhost:9001 - - - - CASFilter - /* - - - - - CAS Validation Filter - - org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter - - - casServerUrlPrefix - http://localhost:8080/cas - - - serverName - http://localhost:9001 - - - - CAS Validation Filter - /* - - - - - CAS HttpServletRequest Wrapper Filter - - org.jasig.cas.client.util.HttpServletRequestWrapperFilter - - - - CAS HttpServletRequest Wrapper Filter - /* - - - - \ No newline at end of file diff --git a/distributed/sso/cas/Client1/src/main/webapp/index.jsp b/distributed/sso/cas/Client1/src/main/webapp/index.jsp deleted file mode 100644 index a067b722..00000000 --- a/distributed/sso/cas/Client1/src/main/webapp/index.jsp +++ /dev/null @@ -1,9 +0,0 @@ -<%@ page contentType="text/html;charset=UTF-8" language="java" %> - - - 青橙团购 - - -<%=request.getRemoteUser()%> , 欢迎来到青橙团购~ - - diff --git a/distributed/sso/cas/Client2/pom.xml b/distributed/sso/cas/Client2/pom.xml deleted file mode 100644 index e5f33357..00000000 --- a/distributed/sso/cas/Client2/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - cas - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - Client2 - war - - - UTF-8 - - - - - org.jasig.cas.client - cas-client-core - 3.3.3 - - - javax.servlet - servlet-api - 2.5 - provided - - - - - - org.apache.tomcat.maven - tomcat7-maven-plugin - 2.2 - - - 9002 - - / - - - - - \ No newline at end of file diff --git a/distributed/sso/cas/Client2/src/main/webapp/WEB-INF/web.xml b/distributed/sso/cas/Client2/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 7ad10cff..00000000 --- a/distributed/sso/cas/Client2/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - org.jasig.cas.client.session.SingleSignOutHttpSessionListener - - - - - CAS Single Sign Out Filter - org.jasig.cas.client.session.SingleSignOutFilter - - - CAS Single Sign Out Filter - /* - - - - - CASFilter - org.jasig.cas.client.authentication.AuthenticationFilter - - casServerLoginUrl - http://localhost:8080/cas/login - - - - serverName - http://localhost:9002 - - - - CASFilter - /* - - - - - CAS Validation Filter - - org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter - - casServerUrlPrefix - http://localhost:8080/cas - - - serverName - http://localhost:9002 - - - - CAS Validation Filter - /* - - - - - CAS HttpServletRequest Wrapper Filter - - org.jasig.cas.client.util.HttpServletRequestWrapperFilter - - - CAS HttpServletRequest Wrapper Filter - /* - - - - \ No newline at end of file diff --git a/distributed/sso/cas/Client2/src/main/webapp/index.jsp b/distributed/sso/cas/Client2/src/main/webapp/index.jsp deleted file mode 100644 index e076e7e9..00000000 --- a/distributed/sso/cas/Client2/src/main/webapp/index.jsp +++ /dev/null @@ -1,11 +0,0 @@ -<%@ page contentType="text/html;charset=UTF-8" language="java" %> - - - 青橙秒杀 - - -<%=request.getRemoteUser()%> , 欢迎来到青橙秒杀~ - - - - diff --git a/distributed/sso/cas/Client3/pom.xml b/distributed/sso/cas/Client3/pom.xml deleted file mode 100644 index d8663f71..00000000 --- a/distributed/sso/cas/Client3/pom.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - cas - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - Client3 - war - - - UTF-8 - 5.0.5.RELEASE - - - - - org.springframework.security - spring-security-config - ${spring.version} - - - org.springframework.security - spring-security-cas - ${spring.version} - - - org.jasig.cas.client - cas-client-core - 3.3.3 - - - org.slf4j - log4j-over-slf4j - - - - - javax.servlet - servlet-api - 2.5 - provided - - - - - - org.apache.tomcat.maven - tomcat7-maven-plugin - 2.2 - - - 9003 - - / - - - - - \ No newline at end of file diff --git a/distributed/sso/cas/Client3/src/main/java/cn/lastwhisper/service/UserDetailServiceImpl.java b/distributed/sso/cas/Client3/src/main/java/cn/lastwhisper/service/UserDetailServiceImpl.java deleted file mode 100644 index a1fa6c63..00000000 --- a/distributed/sso/cas/Client3/src/main/java/cn/lastwhisper/service/UserDetailServiceImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.lastwhisper.service; - -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author Administrator - */ -public class UserDetailServiceImpl implements UserDetailsService { - - @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - - List authorityList=new ArrayList(); - authorityList.add(new SimpleGrantedAuthority("ROLE_USER")); - - return new User(username,"",authorityList); - } -} diff --git a/distributed/sso/cas/Client3/src/main/resources/spring-security.xml b/distributed/sso/cas/Client3/src/main/resources/spring-security.xml deleted file mode 100644 index 89e0e60c..00000000 --- a/distributed/sso/cas/Client3/src/main/resources/spring-security.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/distributed/sso/cas/Client3/src/main/webapp/WEB-INF/web.xml b/distributed/sso/cas/Client3/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index ad19c666..00000000 --- a/distributed/sso/cas/Client3/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - contextConfigLocation - classpath:spring-security.xml - - - - org.springframework.web.context.ContextLoaderListener - - - - - springSecurityFilterChain - org.springframework.web.filter.DelegatingFilterProxy - - - springSecurityFilterChain - /* - - - \ No newline at end of file diff --git a/distributed/sso/cas/Client3/src/main/webapp/index.jsp b/distributed/sso/cas/Client3/src/main/webapp/index.jsp deleted file mode 100644 index a9b7f988..00000000 --- a/distributed/sso/cas/Client3/src/main/webapp/index.jsp +++ /dev/null @@ -1,11 +0,0 @@ -<%@ page import="org.springframework.security.core.context.SecurityContextHolder" %> -<%@ page contentType="text/html;charset=UTF-8" language="java" %> - - - 青橙用户中心 - - -<%=SecurityContextHolder.getContext().getAuthentication().getName()%> 欢迎来到青橙用户中心 -退出 - - diff --git a/distributed/sso/cas/pom.xml b/distributed/sso/cas/pom.xml deleted file mode 100644 index f4efaf0b..00000000 --- a/distributed/sso/cas/pom.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - 4.0.0 - - cn.lastwhisper - cas - pom - 1.0-SNAPSHOT - - product - order - user - - - - \ No newline at end of file diff --git a/distributed/sso/cas/readme.md b/distributed/sso/cas/readme.md deleted file mode 100644 index 9794fb3e..00000000 --- a/distributed/sso/cas/readme.md +++ /dev/null @@ -1,4 +0,0 @@ -1、cas原生使用 -Client1登录之后,Client2不用登录 -2、cas整和Spring Security -Client3可以和Client1、Client2项目进行单点登录 \ No newline at end of file diff --git a/distributed/transaction/README.md b/distributed/transaction/README.md new file mode 100644 index 00000000..6494d044 --- /dev/null +++ b/distributed/transaction/README.md @@ -0,0 +1,5 @@ +分布式事务 + +- demo :产生分布式事务的案例 +- seata-AT-demo:AT模式解决方案 + diff --git a/distributed/transaction/demo/account-service/pom.xml b/distributed/transaction/demo/account-service/pom.xml new file mode 100644 index 00000000..f306a58a --- /dev/null +++ b/distributed/transaction/demo/account-service/pom.xml @@ -0,0 +1,40 @@ + + + + seata-demo + cn.itcast.demo + 1.0-SNAPSHOT + + 4.0.0 + + account-service + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + mysql + mysql-connector-java + + + com.baomidou + mybatis-plus-boot-starter + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/AccountApplication.java b/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/AccountApplication.java new file mode 100644 index 00000000..14674828 --- /dev/null +++ b/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/AccountApplication.java @@ -0,0 +1,16 @@ +package cn.itcast.account; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author 虎哥 + */ +@MapperScan("cn.itcast.account.mapper") +@SpringBootApplication +public class AccountApplication { + public static void main(String[] args) { + SpringApplication.run(AccountApplication.class, args); + } +} diff --git a/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/entity/Account.java b/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/entity/Account.java new file mode 100644 index 00000000..3ac25e0a --- /dev/null +++ b/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/entity/Account.java @@ -0,0 +1,17 @@ +package cn.itcast.account.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author 虎哥 + */ +@Data +@TableName("account_tbl") +public class Account { + @TableId + private Long id; + private String userId; + private Integer money; +} diff --git a/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/mapper/AccountMapper.java b/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/mapper/AccountMapper.java new file mode 100644 index 00000000..42b2f9b0 --- /dev/null +++ b/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/mapper/AccountMapper.java @@ -0,0 +1,15 @@ +package cn.itcast.account.mapper; + +import cn.itcast.account.entity.Account; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +/** + * @author 虎哥 + */ +public interface AccountMapper extends BaseMapper { + + @Update("update account_tbl set money = money - ${money} where user_id = #{userId}") + int debit(@Param("userId") String userId, @Param("money") int money); +} diff --git a/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/service/AccountService.java b/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/service/AccountService.java new file mode 100644 index 00000000..7b5123ad --- /dev/null +++ b/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/service/AccountService.java @@ -0,0 +1,8 @@ +package cn.itcast.account.service; + +public interface AccountService { + /** + * 从用户账户中借出 + */ + void debit(String userId, int money); +} \ No newline at end of file diff --git a/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/service/impl/AccountServiceImpl.java b/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/service/impl/AccountServiceImpl.java new file mode 100644 index 00000000..5deb5dbe --- /dev/null +++ b/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/service/impl/AccountServiceImpl.java @@ -0,0 +1,32 @@ +package cn.itcast.account.service.impl; + +import cn.itcast.account.mapper.AccountMapper; +import cn.itcast.account.service.AccountService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author 虎哥 + */ +@Slf4j +@Service +public class AccountServiceImpl implements AccountService { + private final AccountMapper accountMapper; + + public AccountServiceImpl(AccountMapper accountMapper) { + this.accountMapper = accountMapper; + } + + @Override + @Transactional + public void debit(String userId, int money) { + log.info("开始扣款"); + try { + accountMapper.debit(userId, money); + } catch (Exception e) { + throw new RuntimeException("扣款失败,可能是余额不足!"); + } + log.info("扣款成功"); + } +} diff --git a/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/web/AccountController.java b/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/web/AccountController.java new file mode 100644 index 00000000..0be5d75d --- /dev/null +++ b/distributed/transaction/demo/account-service/src/main/java/cn/itcast/account/web/AccountController.java @@ -0,0 +1,28 @@ +package cn.itcast.account.web; + +import cn.itcast.account.service.AccountService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author 虎哥 + */ +@RestController +@RequestMapping("account") +public class AccountController { + + private final AccountService accountService; + + public AccountController(AccountService accountService) { + this.accountService = accountService; + } + + @PutMapping("/{userId}/{money}") + public ResponseEntity debit(@PathVariable("userId") String userId, @PathVariable("money") Integer money){ + accountService.debit(userId, money); + return ResponseEntity.noContent().build(); + } +} diff --git a/distributed/transaction/demo/account-service/src/main/resources/application.yml b/distributed/transaction/demo/account-service/src/main/resources/application.yml new file mode 100644 index 00000000..356a1476 --- /dev/null +++ b/distributed/transaction/demo/account-service/src/main/resources/application.yml @@ -0,0 +1,24 @@ +server: + port: 8083 +spring: + application: + name: account-service + datasource: + driver-class-name: com.mysql.jdbc.Driver + url: jdbc:mysql:///seata_demo?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false + username: root + password: 123456 +eureka: + client: + service-url: + defaultZone: http://127.0.0.1:8761/eureka +mybatis-plus: + global-config: + db-config: + insert-strategy: not_null + update-strategy: not_null + id-type: auto +logging: + level: + org.springframework.cloud.alibaba.seata.web: debug + cn.itcast: debug \ No newline at end of file diff --git a/distributed/transaction/demo/eureka-server/pom.xml b/distributed/transaction/demo/eureka-server/pom.xml new file mode 100644 index 00000000..f65149d5 --- /dev/null +++ b/distributed/transaction/demo/eureka-server/pom.xml @@ -0,0 +1,28 @@ + + + + seata-demo + cn.itcast.demo + 1.0-SNAPSHOT + + 4.0.0 + + eureka-server + + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-server + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/distributed/transaction/demo/eureka-server/src/main/java/cn/itcast/eureka/EurekaApplication.java b/distributed/transaction/demo/eureka-server/src/main/java/cn/itcast/eureka/EurekaApplication.java new file mode 100644 index 00000000..3d13ae11 --- /dev/null +++ b/distributed/transaction/demo/eureka-server/src/main/java/cn/itcast/eureka/EurekaApplication.java @@ -0,0 +1,16 @@ +package cn.itcast.eureka; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; + +/** + * @author 虎哥 + */ +@EnableEurekaServer +@SpringBootApplication +public class EurekaApplication { + public static void main(String[] args) { + SpringApplication.run(EurekaApplication.class, args); + } +} diff --git a/distributed/transaction/demo/eureka-server/src/main/resources/application.yml b/distributed/transaction/demo/eureka-server/src/main/resources/application.yml new file mode 100644 index 00000000..cf2ce780 --- /dev/null +++ b/distributed/transaction/demo/eureka-server/src/main/resources/application.yml @@ -0,0 +1,14 @@ +server: + port: 8761 +spring: + application: + name: eureka-server +ribbon: + eureka: + enabled: true +eureka: + client: + registerWithEureka: false + fetchRegistry: false + serviceUrl: + defaultZone: http://localhost:${server.port}/eureka/ \ No newline at end of file diff --git a/distributed/transaction/demo/order-service/pom.xml b/distributed/transaction/demo/order-service/pom.xml new file mode 100644 index 00000000..4272ff39 --- /dev/null +++ b/distributed/transaction/demo/order-service/pom.xml @@ -0,0 +1,44 @@ + + + + seata-demo + cn.itcast.demo + 1.0-SNAPSHOT + + 4.0.0 + + order-service + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + mysql + mysql-connector-java + + + com.baomidou + mybatis-plus-boot-starter + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/OrderApplication.java b/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/OrderApplication.java new file mode 100644 index 00000000..42c9661d --- /dev/null +++ b/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/OrderApplication.java @@ -0,0 +1,18 @@ +package cn.itcast.order; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author 虎哥 + */ +@MapperScan("cn.itcast.order.mapper") +@EnableFeignClients +@SpringBootApplication +public class OrderApplication { + public static void main(String[] args) { + SpringApplication.run(OrderApplication.class, args); + } +} diff --git a/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/client/AccountClient.java b/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/client/AccountClient.java new file mode 100644 index 00000000..6efb7039 --- /dev/null +++ b/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/client/AccountClient.java @@ -0,0 +1,15 @@ +package cn.itcast.order.client; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; + +/** + * @author 虎哥 + */ +@FeignClient("account-service") +public interface AccountClient { + + @PutMapping("/account/{userId}/{money}") + void debit(@PathVariable("userId") String userId, @PathVariable("money") Integer money); +} diff --git a/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/client/StorageClient.java b/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/client/StorageClient.java new file mode 100644 index 00000000..5ae5deae --- /dev/null +++ b/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/client/StorageClient.java @@ -0,0 +1,14 @@ +package cn.itcast.order.client; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; + +/** + * @author 虎哥 + */ +@FeignClient("storage-service") +public interface StorageClient { + @PutMapping("/storage/{code}/{count}") + void deduct(@PathVariable("code") String code, @PathVariable("count") Integer count); +} diff --git a/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/entity/Order.java b/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/entity/Order.java new file mode 100644 index 00000000..b71c2560 --- /dev/null +++ b/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/entity/Order.java @@ -0,0 +1,20 @@ +package cn.itcast.order.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author 虎哥 + */ +@Data +@TableName("order_tbl") +public class Order { + @TableId(type = IdType.AUTO) + private Long id; + private String userId; + private String commodityCode; + private Integer count; + private Integer money; +} diff --git a/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/mapper/OrderMapper.java b/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/mapper/OrderMapper.java new file mode 100644 index 00000000..b90f5993 --- /dev/null +++ b/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/mapper/OrderMapper.java @@ -0,0 +1,10 @@ +package cn.itcast.order.mapper; + +import cn.itcast.order.entity.Order; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @author 虎哥 + */ +public interface OrderMapper extends BaseMapper { +} diff --git a/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/service/OrderService.java b/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/service/OrderService.java new file mode 100644 index 00000000..3063dad1 --- /dev/null +++ b/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/service/OrderService.java @@ -0,0 +1,11 @@ +package cn.itcast.order.service; + +import cn.itcast.order.entity.Order; + +public interface OrderService { + + /** + * 创建订单 + */ + Long create(Order order); +} \ No newline at end of file diff --git a/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/service/impl/OrderServiceImpl.java b/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/service/impl/OrderServiceImpl.java new file mode 100644 index 00000000..1192654b --- /dev/null +++ b/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/service/impl/OrderServiceImpl.java @@ -0,0 +1,46 @@ +package cn.itcast.order.service.impl; + +import cn.itcast.order.client.AccountClient; +import cn.itcast.order.client.StorageClient; +import cn.itcast.order.entity.Order; +import cn.itcast.order.mapper.OrderMapper; +import cn.itcast.order.service.OrderService; +import feign.FeignException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author 虎哥 + */ +@Slf4j +@Service +public class OrderServiceImpl implements OrderService { + + private final AccountClient accountClient; + private final StorageClient storageClient; + private final OrderMapper orderMapper; + + public OrderServiceImpl(AccountClient accountClient, StorageClient storageClient, OrderMapper orderMapper) { + this.accountClient = accountClient; + this.storageClient = storageClient; + this.orderMapper = orderMapper; + } + + @Override + @Transactional + public Long create(Order order) { + // 创建订单 + orderMapper.insert(order); + try { + // 扣库存 + storageClient.deduct(order.getCommodityCode(), order.getCount()); + // 扣款 + accountClient.debit(order.getUserId(), order.getMoney()); + } catch (FeignException e) { + log.error("下单失败,原因:{}", e.contentUTF8()); + throw new RuntimeException(e.contentUTF8()); + } + return order.getId(); + } +} diff --git a/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/web/OrderController.java b/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/web/OrderController.java new file mode 100644 index 00000000..fcfb48c5 --- /dev/null +++ b/distributed/transaction/demo/order-service/src/main/java/cn/itcast/order/web/OrderController.java @@ -0,0 +1,29 @@ +package cn.itcast.order.web; + +import cn.itcast.order.entity.Order; +import cn.itcast.order.service.OrderService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author 虎哥 + */ +@RestController +@RequestMapping("order") +public class OrderController { + + private final OrderService orderService; + + public OrderController(OrderService orderService) { + this.orderService = orderService; + } + + @PostMapping + public ResponseEntity createOrder(Order order){ + Long orderId = orderService.create(order); + return ResponseEntity.status(HttpStatus.CREATED).body(orderId); + } +} diff --git a/distributed/transaction/demo/order-service/src/main/resources/application.yml b/distributed/transaction/demo/order-service/src/main/resources/application.yml new file mode 100644 index 00000000..44f65362 --- /dev/null +++ b/distributed/transaction/demo/order-service/src/main/resources/application.yml @@ -0,0 +1,27 @@ +server: + port: 8082 +spring: + application: + name: order-service + datasource: + driver-class-name: com.mysql.jdbc.Driver + url: jdbc:mysql:///seata_demo?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false + username: root + password: 123456 +eureka: + client: + service-url: + defaultZone: http://127.0.0.1:8761/eureka + instance: + prefer-ip-address: true + hostname: 127.0.0.1 +mybatis-plus: + global-config: + db-config: + insert-strategy: not_null + update-strategy: not_null + id-type: auto +logging: + level: + org.springframework.cloud.alibaba.seata.web: debug + cn.itcast: debug \ No newline at end of file diff --git a/distributed/transaction/demo/pom.xml b/distributed/transaction/demo/pom.xml new file mode 100644 index 00000000..7459ded2 --- /dev/null +++ b/distributed/transaction/demo/pom.xml @@ -0,0 +1,93 @@ + + + 4.0.0 + + cn.itcast.demo + seata-demo + 1.0-SNAPSHOT + + storage-service + account-service + order-service + eureka-server + + pom + + + org.springframework.boot + spring-boot-starter-parent + 2.1.12.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + Greenwich.SR5 + 3.3.0 + 5.1.47 + 2.1.0.RELEASE + 1.1.0 + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + mysql + mysql-connector-java + ${mysql.version} + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis.plus.version} + + + com.alibaba.cloud + spring-cloud-alibaba-seata + ${alibaba.seata.version} + + + seata-all + io.seata + + + + + seata-all + io.seata + ${seata.version} + + + + + + + org.apache.commons + commons-lang3 + 3.4 + + + org.projectlombok + lombok + + + + org.springframework.boot + spring-boot-starter-test + test + + + \ No newline at end of file diff --git a/distributed/transaction/demo/storage-service/pom.xml b/distributed/transaction/demo/storage-service/pom.xml new file mode 100644 index 00000000..3c9d9958 --- /dev/null +++ b/distributed/transaction/demo/storage-service/pom.xml @@ -0,0 +1,40 @@ + + + + seata-demo + cn.itcast.demo + 1.0-SNAPSHOT + + 4.0.0 + + storage-service + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + mysql + mysql-connector-java + + + com.baomidou + mybatis-plus-boot-starter + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/StorageApplication.java b/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/StorageApplication.java new file mode 100644 index 00000000..52310a96 --- /dev/null +++ b/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/StorageApplication.java @@ -0,0 +1,16 @@ +package cn.itcast.storage; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author 虎哥 + */ +@MapperScan("cn.itcast.storage.mapper") +@SpringBootApplication +public class StorageApplication { + public static void main(String[] args) { + SpringApplication.run(StorageApplication.class, args); + } +} diff --git a/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/entity/Storage.java b/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/entity/Storage.java new file mode 100644 index 00000000..c96afff7 --- /dev/null +++ b/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/entity/Storage.java @@ -0,0 +1,17 @@ +package cn.itcast.storage.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author 虎哥 + */ +@Data +@TableName("storage_tbl") +public class Storage { + @TableId + private Long id; + private String commodityCode; + private Integer count; +} diff --git a/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/mapper/StorageMapper.java b/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/mapper/StorageMapper.java new file mode 100644 index 00000000..afea1ee2 --- /dev/null +++ b/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/mapper/StorageMapper.java @@ -0,0 +1,14 @@ +package cn.itcast.storage.mapper; + +import cn.itcast.storage.entity.Storage; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +/** + * @author 虎哥 + */ +public interface StorageMapper extends BaseMapper { + @Update("update storage_tbl set `count` = `count` - #{count} where commodity_code = #{code}") + int deduct(@Param("code") String commodityCode, @Param("count") int count); +} diff --git a/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/service/StorageService.java b/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/service/StorageService.java new file mode 100644 index 00000000..e0b594af --- /dev/null +++ b/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/service/StorageService.java @@ -0,0 +1,9 @@ +package cn.itcast.storage.service; + +public interface StorageService{ + + /** + * 扣除存储数量 + */ + void deduct(String commodityCode, int count); +} \ No newline at end of file diff --git a/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/service/impl/StorageServiceImpl.java b/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/service/impl/StorageServiceImpl.java new file mode 100644 index 00000000..7d430da0 --- /dev/null +++ b/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/service/impl/StorageServiceImpl.java @@ -0,0 +1,31 @@ +package cn.itcast.storage.service.impl; + +import cn.itcast.storage.mapper.StorageMapper; +import cn.itcast.storage.service.StorageService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author 虎哥 + */ +@Slf4j +@Service +public class StorageServiceImpl implements StorageService { + + @Autowired + private StorageMapper storageMapper; + + @Transactional + @Override + public void deduct(String commodityCode, int count) { + log.info("开始扣减库存"); + try { + storageMapper.deduct(commodityCode, count); + } catch (Exception e) { + throw new RuntimeException("扣减库存失败,可能是库存不足!"); + } + log.info("扣减库存成功"); + } +} diff --git a/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/web/StorageController.java b/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/web/StorageController.java new file mode 100644 index 00000000..1e953e76 --- /dev/null +++ b/distributed/transaction/demo/storage-service/src/main/java/cn/itcast/storage/web/StorageController.java @@ -0,0 +1,34 @@ +package cn.itcast.storage.web; + +import cn.itcast.storage.service.StorageService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author 虎哥 + */ +@RestController +@RequestMapping("storage") +public class StorageController { + + private final StorageService storageService; + + public StorageController(StorageService storageService) { + this.storageService = storageService; + } + + /** + * 扣减库存 + * @param code 商品编号 + * @param count 要扣减的数量 + * @return 无 + */ + @PutMapping("/{code}/{count}") + public ResponseEntity deduct(@PathVariable("code") String code,@PathVariable("count") Integer count){ + storageService.deduct(code, count); + return ResponseEntity.noContent().build(); + } +} diff --git a/distributed/transaction/demo/storage-service/src/main/resources/application.yml b/distributed/transaction/demo/storage-service/src/main/resources/application.yml new file mode 100644 index 00000000..277e7f31 --- /dev/null +++ b/distributed/transaction/demo/storage-service/src/main/resources/application.yml @@ -0,0 +1,24 @@ +server: + port: 8081 +spring: + application: + name: storage-service + datasource: + driver-class-name: com.mysql.jdbc.Driver + url: jdbc:mysql:///seata_demo?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false + username: root + password: 123456 +eureka: + client: + service-url: + defaultZone: http://127.0.0.1:8761/eureka +mybatis-plus: + global-config: + db-config: + insert-strategy: not_null + update-strategy: not_null + id-type: auto +logging: + level: + org.springframework.cloud.alibaba.seata.web: debug + cn.itcast: debug \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/account-service/pom.xml b/distributed/transaction/seata-AT-demo/account-service/pom.xml new file mode 100644 index 00000000..15d62906 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/account-service/pom.xml @@ -0,0 +1,56 @@ + + + + seata-demo + cn.itcast.demo + 1.0-SNAPSHOT + + 4.0.0 + + account-service + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + mysql + mysql-connector-java + + + com.baomidou + mybatis-plus-boot-starter + + + com.alibaba.cloud + spring-cloud-alibaba-seata + ${alibaba.seata.version} + + + seata-all + io.seata + + + + + seata-all + io.seata + ${seata.version} + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/AccountApplication.java b/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/AccountApplication.java new file mode 100644 index 00000000..14674828 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/AccountApplication.java @@ -0,0 +1,16 @@ +package cn.itcast.account; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author 虎哥 + */ +@MapperScan("cn.itcast.account.mapper") +@SpringBootApplication +public class AccountApplication { + public static void main(String[] args) { + SpringApplication.run(AccountApplication.class, args); + } +} diff --git a/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/config/DataSourceProxyConfig.java b/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/config/DataSourceProxyConfig.java new file mode 100644 index 00000000..27c4157d --- /dev/null +++ b/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/config/DataSourceProxyConfig.java @@ -0,0 +1,22 @@ +package cn.itcast.account.config; + +import io.seata.rm.datasource.DataSourceProxy; +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; + +@Configuration +public class DataSourceProxyConfig { + + @Bean + public SqlSessionFactory sqlSessionFactoryBean(DataSource dataSource) throws Exception { + // 因为使用的是mybatis,这里定义SqlSessionFactoryBean + SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); + // 配置数据源代理 + sqlSessionFactoryBean.setDataSource(new DataSourceProxy(dataSource)); + return sqlSessionFactoryBean.getObject(); + } +} \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/entity/Account.java b/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/entity/Account.java new file mode 100644 index 00000000..3ac25e0a --- /dev/null +++ b/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/entity/Account.java @@ -0,0 +1,17 @@ +package cn.itcast.account.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author 虎哥 + */ +@Data +@TableName("account_tbl") +public class Account { + @TableId + private Long id; + private String userId; + private Integer money; +} diff --git a/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/mapper/AccountMapper.java b/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/mapper/AccountMapper.java new file mode 100644 index 00000000..42b2f9b0 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/mapper/AccountMapper.java @@ -0,0 +1,15 @@ +package cn.itcast.account.mapper; + +import cn.itcast.account.entity.Account; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +/** + * @author 虎哥 + */ +public interface AccountMapper extends BaseMapper { + + @Update("update account_tbl set money = money - ${money} where user_id = #{userId}") + int debit(@Param("userId") String userId, @Param("money") int money); +} diff --git a/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/service/AccountService.java b/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/service/AccountService.java new file mode 100644 index 00000000..7b5123ad --- /dev/null +++ b/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/service/AccountService.java @@ -0,0 +1,8 @@ +package cn.itcast.account.service; + +public interface AccountService { + /** + * 从用户账户中借出 + */ + void debit(String userId, int money); +} \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/service/impl/AccountServiceImpl.java b/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/service/impl/AccountServiceImpl.java new file mode 100644 index 00000000..5deb5dbe --- /dev/null +++ b/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/service/impl/AccountServiceImpl.java @@ -0,0 +1,32 @@ +package cn.itcast.account.service.impl; + +import cn.itcast.account.mapper.AccountMapper; +import cn.itcast.account.service.AccountService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author 虎哥 + */ +@Slf4j +@Service +public class AccountServiceImpl implements AccountService { + private final AccountMapper accountMapper; + + public AccountServiceImpl(AccountMapper accountMapper) { + this.accountMapper = accountMapper; + } + + @Override + @Transactional + public void debit(String userId, int money) { + log.info("开始扣款"); + try { + accountMapper.debit(userId, money); + } catch (Exception e) { + throw new RuntimeException("扣款失败,可能是余额不足!"); + } + log.info("扣款成功"); + } +} diff --git a/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/web/AccountController.java b/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/web/AccountController.java new file mode 100644 index 00000000..0be5d75d --- /dev/null +++ b/distributed/transaction/seata-AT-demo/account-service/src/main/java/cn/itcast/account/web/AccountController.java @@ -0,0 +1,28 @@ +package cn.itcast.account.web; + +import cn.itcast.account.service.AccountService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author 虎哥 + */ +@RestController +@RequestMapping("account") +public class AccountController { + + private final AccountService accountService; + + public AccountController(AccountService accountService) { + this.accountService = accountService; + } + + @PutMapping("/{userId}/{money}") + public ResponseEntity debit(@PathVariable("userId") String userId, @PathVariable("money") Integer money){ + accountService.debit(userId, money); + return ResponseEntity.noContent().build(); + } +} diff --git a/distributed/transaction/seata-AT-demo/account-service/src/main/resources/application.yml b/distributed/transaction/seata-AT-demo/account-service/src/main/resources/application.yml new file mode 100644 index 00000000..4c669ca1 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/account-service/src/main/resources/application.yml @@ -0,0 +1,29 @@ +server: + port: 8083 +spring: + application: + name: account-service + datasource: + driver-class-name: com.mysql.jdbc.Driver + url: jdbc:mysql:///seata_demo?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false + username: root + password: 123456 + cloud: + alibaba: + seata: + tx-service-group: test_tx_group # 定义事务组的名称 + +eureka: + client: + service-url: + defaultZone: http://127.0.0.1:8761/eureka +mybatis-plus: + global-config: + db-config: + insert-strategy: not_null + update-strategy: not_null + id-type: auto +logging: + level: + org.springframework.cloud.alibaba.seata.web: debug + cn.itcast: debug \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/account-service/src/main/resources/file.conf b/distributed/transaction/seata-AT-demo/account-service/src/main/resources/file.conf new file mode 100644 index 00000000..3103c110 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/account-service/src/main/resources/file.conf @@ -0,0 +1,65 @@ +transport { + # tcp udt unix-domain-socket + type = "TCP" + #NIO NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the client batch send request enable + enableClientBatchSendRequest = true + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size,will not be used for UDT + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" +} +service { + vgroupMapping.test_tx_group = "seata_tc_server" + #only support when registry.type=file, please don't set multiple addresses + seata_tc_server.grouplist = "127.0.0.1:8091" + #degrade, current not support + enableDegrade = false + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + asyncCommitBufferLimit = 10000 + lock { + retryInterval = 10 + retryTimes = 30 + retryPolicyBranchRollbackOnConflict = true + } + reportRetryCount = 5 + tableMetaCheckEnable = false + reportSuccessEnable = false + } + tm { + commitRetryCount = 5 + rollbackRetryCount = 5 + } + undo { + dataValidation = true + logSerialization = "jackson" + logTable = "undo_log" + } + log { + exceptionRate = 100 + } +} \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/account-service/src/main/resources/registry.conf b/distributed/transaction/seata-AT-demo/account-service/src/main/resources/registry.conf new file mode 100644 index 00000000..0e8a8659 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/account-service/src/main/resources/registry.conf @@ -0,0 +1,34 @@ +registry { + # 指定注册中心类型,这里使用eureka类型 + type = "eureka" + # 各种注册中心的配置。。这里省略,只保留了eureka和Zookeeper + eureka { + serviceUrl = "http://localhost:8761/eureka" + application = "seata_tc_server" + weight = "1" + } + zk { + cluster = "default" + serverAddr = "127.0.0.1:2181" + session.timeout = 6000 + connect.timeout = 2000 + } +} + +config { + # 配置文件方式,可以支持 file、nacos 、apollo、zk、consul、etcd3 + type = "file" + nacos { + serverAddr = "localhost" + namespace = "" + group = "SEATA_GROUP" + } + zk { + serverAddr = "127.0.0.1:2181" + session.timeout = 6000 + connect.timeout = 2000 + } + file { + name = "file.conf" + } +} \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/eureka-server/pom.xml b/distributed/transaction/seata-AT-demo/eureka-server/pom.xml new file mode 100644 index 00000000..f65149d5 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/eureka-server/pom.xml @@ -0,0 +1,28 @@ + + + + seata-demo + cn.itcast.demo + 1.0-SNAPSHOT + + 4.0.0 + + eureka-server + + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-server + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/eureka-server/src/main/java/cn/itcast/eureka/EurekaApplication.java b/distributed/transaction/seata-AT-demo/eureka-server/src/main/java/cn/itcast/eureka/EurekaApplication.java new file mode 100644 index 00000000..3d13ae11 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/eureka-server/src/main/java/cn/itcast/eureka/EurekaApplication.java @@ -0,0 +1,16 @@ +package cn.itcast.eureka; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; + +/** + * @author 虎哥 + */ +@EnableEurekaServer +@SpringBootApplication +public class EurekaApplication { + public static void main(String[] args) { + SpringApplication.run(EurekaApplication.class, args); + } +} diff --git a/distributed/transaction/seata-AT-demo/eureka-server/src/main/resources/application.yml b/distributed/transaction/seata-AT-demo/eureka-server/src/main/resources/application.yml new file mode 100644 index 00000000..cf2ce780 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/eureka-server/src/main/resources/application.yml @@ -0,0 +1,14 @@ +server: + port: 8761 +spring: + application: + name: eureka-server +ribbon: + eureka: + enabled: true +eureka: + client: + registerWithEureka: false + fetchRegistry: false + serviceUrl: + defaultZone: http://localhost:${server.port}/eureka/ \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/order-service/pom.xml b/distributed/transaction/seata-AT-demo/order-service/pom.xml new file mode 100644 index 00000000..bac29e00 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/order-service/pom.xml @@ -0,0 +1,61 @@ + + + + seata-demo + cn.itcast.demo + 1.0-SNAPSHOT + + 4.0.0 + + order-service + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + mysql + mysql-connector-java + + + com.baomidou + mybatis-plus-boot-starter + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + com.alibaba.cloud + spring-cloud-alibaba-seata + ${alibaba.seata.version} + + + seata-all + io.seata + + + + + seata-all + io.seata + ${seata.version} + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/OrderApplication.java b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/OrderApplication.java new file mode 100644 index 00000000..42c9661d --- /dev/null +++ b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/OrderApplication.java @@ -0,0 +1,18 @@ +package cn.itcast.order; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author 虎哥 + */ +@MapperScan("cn.itcast.order.mapper") +@EnableFeignClients +@SpringBootApplication +public class OrderApplication { + public static void main(String[] args) { + SpringApplication.run(OrderApplication.class, args); + } +} diff --git a/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/client/AccountClient.java b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/client/AccountClient.java new file mode 100644 index 00000000..6efb7039 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/client/AccountClient.java @@ -0,0 +1,15 @@ +package cn.itcast.order.client; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; + +/** + * @author 虎哥 + */ +@FeignClient("account-service") +public interface AccountClient { + + @PutMapping("/account/{userId}/{money}") + void debit(@PathVariable("userId") String userId, @PathVariable("money") Integer money); +} diff --git a/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/client/StorageClient.java b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/client/StorageClient.java new file mode 100644 index 00000000..5ae5deae --- /dev/null +++ b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/client/StorageClient.java @@ -0,0 +1,14 @@ +package cn.itcast.order.client; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; + +/** + * @author 虎哥 + */ +@FeignClient("storage-service") +public interface StorageClient { + @PutMapping("/storage/{code}/{count}") + void deduct(@PathVariable("code") String code, @PathVariable("count") Integer count); +} diff --git a/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/config/DataSourceProxyConfig.java b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/config/DataSourceProxyConfig.java new file mode 100644 index 00000000..840ff68c --- /dev/null +++ b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/config/DataSourceProxyConfig.java @@ -0,0 +1,23 @@ +package cn.itcast.order.config; + +import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; +import io.seata.rm.datasource.DataSourceProxy; +import org.apache.ibatis.session.SqlSessionFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; + +@Configuration +public class DataSourceProxyConfig { + + @Bean + public SqlSessionFactory sqlSessionFactoryBean(DataSource dataSource) throws Exception { + // 订单服务中引入了mybatis-plus,所以要使用特殊的SqlSessionFactoryBean + MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean(); + // 代理数据源 + sqlSessionFactoryBean.setDataSource(new DataSourceProxy(dataSource)); + // 生成SqlSessionFactory + return sqlSessionFactoryBean.getObject(); + } +} \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/entity/Order.java b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/entity/Order.java new file mode 100644 index 00000000..b71c2560 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/entity/Order.java @@ -0,0 +1,20 @@ +package cn.itcast.order.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author 虎哥 + */ +@Data +@TableName("order_tbl") +public class Order { + @TableId(type = IdType.AUTO) + private Long id; + private String userId; + private String commodityCode; + private Integer count; + private Integer money; +} diff --git a/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/mapper/OrderMapper.java b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/mapper/OrderMapper.java new file mode 100644 index 00000000..b90f5993 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/mapper/OrderMapper.java @@ -0,0 +1,10 @@ +package cn.itcast.order.mapper; + +import cn.itcast.order.entity.Order; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @author 虎哥 + */ +public interface OrderMapper extends BaseMapper { +} diff --git a/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/service/OrderService.java b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/service/OrderService.java new file mode 100644 index 00000000..3063dad1 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/service/OrderService.java @@ -0,0 +1,11 @@ +package cn.itcast.order.service; + +import cn.itcast.order.entity.Order; + +public interface OrderService { + + /** + * 创建订单 + */ + Long create(Order order); +} \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/service/impl/OrderServiceImpl.java b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/service/impl/OrderServiceImpl.java new file mode 100644 index 00000000..ad23ac37 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/service/impl/OrderServiceImpl.java @@ -0,0 +1,47 @@ +package cn.itcast.order.service.impl; + +import cn.itcast.order.client.AccountClient; +import cn.itcast.order.client.StorageClient; +import cn.itcast.order.entity.Order; +import cn.itcast.order.mapper.OrderMapper; +import cn.itcast.order.service.OrderService; +import feign.FeignException; +import io.seata.spring.annotation.GlobalTransactional; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * @author 虎哥 + */ +@Slf4j +@Service +public class OrderServiceImpl implements OrderService { + + private final AccountClient accountClient; + private final StorageClient storageClient; + private final OrderMapper orderMapper; + + public OrderServiceImpl(AccountClient accountClient, StorageClient storageClient, OrderMapper orderMapper) { + this.accountClient = accountClient; + this.storageClient = storageClient; + this.orderMapper = orderMapper; + } + + @Override +// @Transactional + @GlobalTransactional + public Long create(Order order) { + // 创建订单 + orderMapper.insert(order); + try { + // 扣库存 + storageClient.deduct(order.getCommodityCode(), order.getCount()); + // 扣款 + accountClient.debit(order.getUserId(), order.getMoney()); + } catch (FeignException e) { + log.error("下单失败,原因:{}", e.contentUTF8()); + throw new RuntimeException(e.contentUTF8()); + } + return order.getId(); + } +} diff --git a/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/web/OrderController.java b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/web/OrderController.java new file mode 100644 index 00000000..fcfb48c5 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/order-service/src/main/java/cn/itcast/order/web/OrderController.java @@ -0,0 +1,29 @@ +package cn.itcast.order.web; + +import cn.itcast.order.entity.Order; +import cn.itcast.order.service.OrderService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author 虎哥 + */ +@RestController +@RequestMapping("order") +public class OrderController { + + private final OrderService orderService; + + public OrderController(OrderService orderService) { + this.orderService = orderService; + } + + @PostMapping + public ResponseEntity createOrder(Order order){ + Long orderId = orderService.create(order); + return ResponseEntity.status(HttpStatus.CREATED).body(orderId); + } +} diff --git a/distributed/transaction/seata-AT-demo/order-service/src/main/resources/application.yml b/distributed/transaction/seata-AT-demo/order-service/src/main/resources/application.yml new file mode 100644 index 00000000..98771382 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/order-service/src/main/resources/application.yml @@ -0,0 +1,32 @@ +server: + port: 8082 +spring: + application: + name: order-service + datasource: + driver-class-name: com.mysql.jdbc.Driver + url: jdbc:mysql:///seata_demo?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false + username: root + password: 123456 + cloud: + alibaba: + seata: + tx-service-group: test_tx_group # 定义事务组的名称 + +eureka: + client: + service-url: + defaultZone: http://127.0.0.1:8761/eureka + instance: + prefer-ip-address: true + hostname: 127.0.0.1 +mybatis-plus: + global-config: + db-config: + insert-strategy: not_null + update-strategy: not_null + id-type: auto +logging: + level: + org.springframework.cloud.alibaba.seata.web: debug + cn.itcast: debug \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/order-service/src/main/resources/file.conf b/distributed/transaction/seata-AT-demo/order-service/src/main/resources/file.conf new file mode 100644 index 00000000..3103c110 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/order-service/src/main/resources/file.conf @@ -0,0 +1,65 @@ +transport { + # tcp udt unix-domain-socket + type = "TCP" + #NIO NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the client batch send request enable + enableClientBatchSendRequest = true + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size,will not be used for UDT + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" +} +service { + vgroupMapping.test_tx_group = "seata_tc_server" + #only support when registry.type=file, please don't set multiple addresses + seata_tc_server.grouplist = "127.0.0.1:8091" + #degrade, current not support + enableDegrade = false + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + asyncCommitBufferLimit = 10000 + lock { + retryInterval = 10 + retryTimes = 30 + retryPolicyBranchRollbackOnConflict = true + } + reportRetryCount = 5 + tableMetaCheckEnable = false + reportSuccessEnable = false + } + tm { + commitRetryCount = 5 + rollbackRetryCount = 5 + } + undo { + dataValidation = true + logSerialization = "jackson" + logTable = "undo_log" + } + log { + exceptionRate = 100 + } +} \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/order-service/src/main/resources/registry.conf b/distributed/transaction/seata-AT-demo/order-service/src/main/resources/registry.conf new file mode 100644 index 00000000..0e8a8659 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/order-service/src/main/resources/registry.conf @@ -0,0 +1,34 @@ +registry { + # 指定注册中心类型,这里使用eureka类型 + type = "eureka" + # 各种注册中心的配置。。这里省略,只保留了eureka和Zookeeper + eureka { + serviceUrl = "http://localhost:8761/eureka" + application = "seata_tc_server" + weight = "1" + } + zk { + cluster = "default" + serverAddr = "127.0.0.1:2181" + session.timeout = 6000 + connect.timeout = 2000 + } +} + +config { + # 配置文件方式,可以支持 file、nacos 、apollo、zk、consul、etcd3 + type = "file" + nacos { + serverAddr = "localhost" + namespace = "" + group = "SEATA_GROUP" + } + zk { + serverAddr = "127.0.0.1:2181" + session.timeout = 6000 + connect.timeout = 2000 + } + file { + name = "file.conf" + } +} \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/pom.xml b/distributed/transaction/seata-AT-demo/pom.xml new file mode 100644 index 00000000..7459ded2 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/pom.xml @@ -0,0 +1,93 @@ + + + 4.0.0 + + cn.itcast.demo + seata-demo + 1.0-SNAPSHOT + + storage-service + account-service + order-service + eureka-server + + pom + + + org.springframework.boot + spring-boot-starter-parent + 2.1.12.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + Greenwich.SR5 + 3.3.0 + 5.1.47 + 2.1.0.RELEASE + 1.1.0 + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + mysql + mysql-connector-java + ${mysql.version} + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis.plus.version} + + + com.alibaba.cloud + spring-cloud-alibaba-seata + ${alibaba.seata.version} + + + seata-all + io.seata + + + + + seata-all + io.seata + ${seata.version} + + + + + + + org.apache.commons + commons-lang3 + 3.4 + + + org.projectlombok + lombok + + + + org.springframework.boot + spring-boot-starter-test + test + + + \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/storage-service/pom.xml b/distributed/transaction/seata-AT-demo/storage-service/pom.xml new file mode 100644 index 00000000..24ede774 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/storage-service/pom.xml @@ -0,0 +1,56 @@ + + + + seata-demo + cn.itcast.demo + 1.0-SNAPSHOT + + 4.0.0 + + storage-service + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + mysql + mysql-connector-java + + + com.baomidou + mybatis-plus-boot-starter + + + com.alibaba.cloud + spring-cloud-alibaba-seata + ${alibaba.seata.version} + + + seata-all + io.seata + + + + + seata-all + io.seata + ${seata.version} + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/StorageApplication.java b/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/StorageApplication.java new file mode 100644 index 00000000..52310a96 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/StorageApplication.java @@ -0,0 +1,16 @@ +package cn.itcast.storage; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author 虎哥 + */ +@MapperScan("cn.itcast.storage.mapper") +@SpringBootApplication +public class StorageApplication { + public static void main(String[] args) { + SpringApplication.run(StorageApplication.class, args); + } +} diff --git a/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/config/DataSourceProxyConfig.java b/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/config/DataSourceProxyConfig.java new file mode 100644 index 00000000..0400e720 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/config/DataSourceProxyConfig.java @@ -0,0 +1,22 @@ +package cn.itcast.storage.config; + +import io.seata.rm.datasource.DataSourceProxy; +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; + +@Configuration +public class DataSourceProxyConfig { + + @Bean + public SqlSessionFactory sqlSessionFactoryBean(DataSource dataSource) throws Exception { + // 因为使用的是mybatis,这里定义SqlSessionFactoryBean + SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); + // 配置数据源代理 + sqlSessionFactoryBean.setDataSource(new DataSourceProxy(dataSource)); + return sqlSessionFactoryBean.getObject(); + } +} \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/entity/Storage.java b/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/entity/Storage.java new file mode 100644 index 00000000..c96afff7 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/entity/Storage.java @@ -0,0 +1,17 @@ +package cn.itcast.storage.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author 虎哥 + */ +@Data +@TableName("storage_tbl") +public class Storage { + @TableId + private Long id; + private String commodityCode; + private Integer count; +} diff --git a/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/mapper/StorageMapper.java b/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/mapper/StorageMapper.java new file mode 100644 index 00000000..afea1ee2 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/mapper/StorageMapper.java @@ -0,0 +1,14 @@ +package cn.itcast.storage.mapper; + +import cn.itcast.storage.entity.Storage; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +/** + * @author 虎哥 + */ +public interface StorageMapper extends BaseMapper { + @Update("update storage_tbl set `count` = `count` - #{count} where commodity_code = #{code}") + int deduct(@Param("code") String commodityCode, @Param("count") int count); +} diff --git a/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/service/StorageService.java b/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/service/StorageService.java new file mode 100644 index 00000000..e0b594af --- /dev/null +++ b/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/service/StorageService.java @@ -0,0 +1,9 @@ +package cn.itcast.storage.service; + +public interface StorageService{ + + /** + * 扣除存储数量 + */ + void deduct(String commodityCode, int count); +} \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/service/impl/StorageServiceImpl.java b/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/service/impl/StorageServiceImpl.java new file mode 100644 index 00000000..7d430da0 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/service/impl/StorageServiceImpl.java @@ -0,0 +1,31 @@ +package cn.itcast.storage.service.impl; + +import cn.itcast.storage.mapper.StorageMapper; +import cn.itcast.storage.service.StorageService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author 虎哥 + */ +@Slf4j +@Service +public class StorageServiceImpl implements StorageService { + + @Autowired + private StorageMapper storageMapper; + + @Transactional + @Override + public void deduct(String commodityCode, int count) { + log.info("开始扣减库存"); + try { + storageMapper.deduct(commodityCode, count); + } catch (Exception e) { + throw new RuntimeException("扣减库存失败,可能是库存不足!"); + } + log.info("扣减库存成功"); + } +} diff --git a/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/web/StorageController.java b/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/web/StorageController.java new file mode 100644 index 00000000..1e953e76 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/storage-service/src/main/java/cn/itcast/storage/web/StorageController.java @@ -0,0 +1,34 @@ +package cn.itcast.storage.web; + +import cn.itcast.storage.service.StorageService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author 虎哥 + */ +@RestController +@RequestMapping("storage") +public class StorageController { + + private final StorageService storageService; + + public StorageController(StorageService storageService) { + this.storageService = storageService; + } + + /** + * 扣减库存 + * @param code 商品编号 + * @param count 要扣减的数量 + * @return 无 + */ + @PutMapping("/{code}/{count}") + public ResponseEntity deduct(@PathVariable("code") String code,@PathVariable("count") Integer count){ + storageService.deduct(code, count); + return ResponseEntity.noContent().build(); + } +} diff --git a/distributed/transaction/seata-AT-demo/storage-service/src/main/resources/application.yml b/distributed/transaction/seata-AT-demo/storage-service/src/main/resources/application.yml new file mode 100644 index 00000000..619e5f70 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/storage-service/src/main/resources/application.yml @@ -0,0 +1,29 @@ +server: + port: 8081 +spring: + application: + name: storage-service + datasource: + driver-class-name: com.mysql.jdbc.Driver + url: jdbc:mysql:///seata_demo?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false + username: root + password: 123456 + cloud: + alibaba: + seata: + tx-service-group: test_tx_group # 定义事务组的名称 + +eureka: + client: + service-url: + defaultZone: http://127.0.0.1:8761/eureka +mybatis-plus: + global-config: + db-config: + insert-strategy: not_null + update-strategy: not_null + id-type: auto +logging: + level: + org.springframework.cloud.alibaba.seata.web: debug + cn.itcast: debug \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/storage-service/src/main/resources/file.conf b/distributed/transaction/seata-AT-demo/storage-service/src/main/resources/file.conf new file mode 100644 index 00000000..3103c110 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/storage-service/src/main/resources/file.conf @@ -0,0 +1,65 @@ +transport { + # tcp udt unix-domain-socket + type = "TCP" + #NIO NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the client batch send request enable + enableClientBatchSendRequest = true + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size,will not be used for UDT + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" +} +service { + vgroupMapping.test_tx_group = "seata_tc_server" + #only support when registry.type=file, please don't set multiple addresses + seata_tc_server.grouplist = "127.0.0.1:8091" + #degrade, current not support + enableDegrade = false + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + asyncCommitBufferLimit = 10000 + lock { + retryInterval = 10 + retryTimes = 30 + retryPolicyBranchRollbackOnConflict = true + } + reportRetryCount = 5 + tableMetaCheckEnable = false + reportSuccessEnable = false + } + tm { + commitRetryCount = 5 + rollbackRetryCount = 5 + } + undo { + dataValidation = true + logSerialization = "jackson" + logTable = "undo_log" + } + log { + exceptionRate = 100 + } +} \ No newline at end of file diff --git a/distributed/transaction/seata-AT-demo/storage-service/src/main/resources/registry.conf b/distributed/transaction/seata-AT-demo/storage-service/src/main/resources/registry.conf new file mode 100644 index 00000000..0e8a8659 --- /dev/null +++ b/distributed/transaction/seata-AT-demo/storage-service/src/main/resources/registry.conf @@ -0,0 +1,34 @@ +registry { + # 指定注册中心类型,这里使用eureka类型 + type = "eureka" + # 各种注册中心的配置。。这里省略,只保留了eureka和Zookeeper + eureka { + serviceUrl = "http://localhost:8761/eureka" + application = "seata_tc_server" + weight = "1" + } + zk { + cluster = "default" + serverAddr = "127.0.0.1:2181" + session.timeout = 6000 + connect.timeout = 2000 + } +} + +config { + # 配置文件方式,可以支持 file、nacos 、apollo、zk、consul、etcd3 + type = "file" + nacos { + serverAddr = "localhost" + namespace = "" + group = "SEATA_GROUP" + } + zk { + serverAddr = "127.0.0.1:2181" + session.timeout = 6000 + connect.timeout = 2000 + } + file { + name = "file.conf" + } +} \ No newline at end of file diff --git a/distributed/transaction/seata_demo.sql b/distributed/transaction/seata_demo.sql new file mode 100644 index 00000000..0a298a90 --- /dev/null +++ b/distributed/transaction/seata_demo.sql @@ -0,0 +1,69 @@ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for account_tbl +-- ---------------------------- +DROP TABLE IF EXISTS `account_tbl`; +CREATE TABLE `account_tbl` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `money` int(11) UNSIGNED NULL DEFAULT 0, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of account_tbl +-- ---------------------------- +INSERT INTO `account_tbl` VALUES (1, 'user202003032042012', 1000); + +-- ---------------------------- +-- Table structure for order_tbl +-- ---------------------------- +DROP TABLE IF EXISTS `order_tbl`; +CREATE TABLE `order_tbl` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `commodity_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `count` int(11) NULL DEFAULT 0, + `money` int(11) NULL DEFAULT 0, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Table structure for storage_tbl +-- ---------------------------- +DROP TABLE IF EXISTS `storage_tbl`; +CREATE TABLE `storage_tbl` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `commodity_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `count` int(11) UNSIGNED NULL DEFAULT 0, + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `commodity_code`(`commodity_code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of storage_tbl +-- ---------------------------- +INSERT INTO `storage_tbl` VALUES (1, '100202003032041', 10); + +-- ---------------------------- +-- Table structure for undo_log +-- ---------------------------- +DROP TABLE IF EXISTS `undo_log`; +CREATE TABLE `undo_log` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `branch_id` bigint(20) NOT NULL, + `xid` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `context` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `rollback_info` longblob NOT NULL, + `log_status` int(11) NOT NULL, + `log_created` datetime(0) NOT NULL, + `log_modified` datetime(0) NOT NULL, + `ext` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; + +SET FOREIGN_KEY_CHECKS = 1; diff --git "a/distributed/transaction/\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.zip" "b/distributed/transaction/\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.zip" new file mode 100644 index 00000000..6ba7dd9e Binary files /dev/null and "b/distributed/transaction/\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.zip" differ diff --git a/framework/flyway/pom.xml b/framework/flyway/pom.xml new file mode 100644 index 00000000..e42c823a --- /dev/null +++ b/framework/flyway/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + cn.lastwhisper + flyway + 1.0-SNAPSHOT + + + 1.8 + + + + + + org.flywaydb + flyway-core + 6.0.6 + + + + + mysql + mysql-connector-java + 8.0.17 + + + + \ No newline at end of file diff --git a/framework/flyway/src/main/java/cn/lastwhisper/flyway/App.java b/framework/flyway/src/main/java/cn/lastwhisper/flyway/App.java new file mode 100644 index 00000000..65cc37f8 --- /dev/null +++ b/framework/flyway/src/main/java/cn/lastwhisper/flyway/App.java @@ -0,0 +1,16 @@ +package cn.lastwhisper.flyway; + +import org.flywaydb.core.Flyway; + +public class App { + public static void main(String[] args) { + // Create the Flyway instance and point it to the database + Flyway flyway = Flyway.configure().dataSource( + "jdbc:mysql://localhost:3306/application?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8", + "root", "root").load(); + + // Start the migration + // 默认 flyway.locations=classpath:/db/migration + flyway.migrate(); + } +} \ No newline at end of file diff --git a/springboot-integration-examples/springboot-flyway/src/main/resources/db/migration/V1__Create_person_table.sql b/framework/flyway/src/main/resources/db/migration/V1__Create_person_table.sql similarity index 100% rename from springboot-integration-examples/springboot-flyway/src/main/resources/db/migration/V1__Create_person_table.sql rename to framework/flyway/src/main/resources/db/migration/V1__Create_person_table.sql diff --git a/springboot-integration-examples/springboot-flyway/src/main/resources/db/migration/V2__Add_people.sql b/framework/flyway/src/main/resources/db/migration/V2__Add_people.sql similarity index 100% rename from springboot-integration-examples/springboot-flyway/src/main/resources/db/migration/V2__Add_people.sql rename to framework/flyway/src/main/resources/db/migration/V2__Add_people.sql diff --git a/framework/guava/pom.xml b/framework/guava/pom.xml new file mode 100644 index 00000000..f3d4370d --- /dev/null +++ b/framework/guava/pom.xml @@ -0,0 +1,25 @@ + + + + 4.0.0 + + guava + cn.lastwhisper + 1.0-SNAPSHOT + + + + junit + junit + 4.13 + + + + com.google.guava + guava + 30.1.1-jre + + + \ No newline at end of file diff --git a/framework/guava/src/main/java/cn/lastwhisper/bloomfilter/TestBloomFilter.java b/framework/guava/src/main/java/cn/lastwhisper/bloomfilter/TestBloomFilter.java new file mode 100644 index 00000000..25de3af6 --- /dev/null +++ b/framework/guava/src/main/java/cn/lastwhisper/bloomfilter/TestBloomFilter.java @@ -0,0 +1,23 @@ +package cn.lastwhisper.bloomfilter; + +import com.google.common.hash.BloomFilter; +import com.google.common.hash.Funnel; +import com.google.common.hash.Funnels; + +public class TestBloomFilter { + + public static void main(String[] args) { + Funnel funnel = Funnels.integerFunnel(); + int size = 1000_000; + double errorChance = 0.001; //错误率 + BloomFilter filter = BloomFilter.create(funnel, size, errorChance); + for (int i = 0; i < size; i++) { + filter.put(i); + } + for (int i = 0; i < size; i++) { + if (!filter.mightContain(i)) { + System.out.println("发现不存在的数据 : " + i); + } + } + } +} \ No newline at end of file diff --git a/framework/guava/src/main/java/cn/lastwhisper/cache/TestCache.java b/framework/guava/src/main/java/cn/lastwhisper/cache/TestCache.java new file mode 100644 index 00000000..5d29b051 --- /dev/null +++ b/framework/guava/src/main/java/cn/lastwhisper/cache/TestCache.java @@ -0,0 +1,40 @@ +package cn.lastwhisper.cache; + +import com.google.common.cache.*; +import org.junit.Test; + +import java.util.concurrent.TimeUnit; + +/** + * Guava的Cache + * @author lastwhisper + * @date 2020/6/2 + */ +public class TestCache { + + // https://github.com/zhuzhenke/common-caches + @Test + public void testCacheUse() throws Exception{ + + LoadingCache loadingCache = CacheBuilder.newBuilder() + .expireAfterAccess(10, TimeUnit.SECONDS) + .maximumSize(1000) + .removalListener(new RemovalListener() { + @Override + public void onRemoval(RemovalNotification notification) { + + } + }) + .build(new CacheLoader() { + @Override + public String load(String key) throws Exception { + return key; + } + }); + + System.out.println(loadingCache.get("key")); + + + } + +} diff --git a/framework/guava/src/main/java/cn/lastwhisper/collection/MapTest.java b/framework/guava/src/main/java/cn/lastwhisper/collection/MapTest.java new file mode 100644 index 00000000..8daede52 --- /dev/null +++ b/framework/guava/src/main/java/cn/lastwhisper/collection/MapTest.java @@ -0,0 +1,282 @@ +package cn.lastwhisper.collection; + +import com.google.common.collect.*; +import org.junit.Test; + +import java.util.*; + +/** + * 参考:https://mp.weixin.qq.com/s/LOZ-p6divRjO9ZTcus101A + * + * @author cunchang + * @date 2022/3/17 1:54 PM + */ +public class MapTest { + + /** + *

+ * 案例:记录员工每个月工作的天数 + * 使用hashmap的话,得两个嵌套 + */ + @Test + public void test双键Map() { + // java中的Map只允许有一个key和一个value存在。 + // guava中的Table允许一个value存在两个key。Table中的两个key分别被称为rowKey和columnKey,也就是行和列。 + Table table = HashBasedTable.create(); + //存放元素 + table.put("Hydra", "Jan", 20); + table.put("Hydra", "Feb", 28); + + table.put("Trunks", "Jan", 28); + table.put("Trunks", "Feb", 16); + + //取出元素 + Integer dayCount = table.get("Hydra", "Feb"); + System.out.println("取出元素:" + dayCount); + +// 1、获得key或value的集合 + //rowKey或columnKey的集合 + System.out.println("---rowKey或columnKey的集合"); + Set rowKeys = table.rowKeySet(); + Set columnKeys = table.columnKeySet(); + //value集合 + Collection values = table.values(); + System.out.println("rowKeys:" + rowKeys); + System.out.println("columnKeys:" + columnKeys); + System.out.println("values:" + values); + +// 2、计算key对应的所有value的和 + // 以统计所有rowKey对应的value之和为例: + System.out.println("---统计所有rowKey对应的value之和"); + for (String key : table.rowKeySet()) { + Set> rows = table.row(key).entrySet(); + int total = 0; + for (Map.Entry row : rows) { + total += row.getValue(); + } + System.out.println(key + ": " + total); + } +// 3、转换rowKey和columnKey + // 行和列的转置,直接调用Tables的静态方法transpose + System.out.println("---行和列的转置"); + Table table2 = Tables.transpose(table); + Set> cells = table2.cellSet(); + cells.forEach(cell -> + System.out.println(cell.getRowKey() + "," + cell.getColumnKey() + ":" + cell.getValue()) + ); + +// 4、转为嵌套的Map + // 将数据还原成嵌套Map的那种形式,使用Table的rowMap或columnMap方法就可以实现了 + System.out.println("---转为嵌套的Map"); + Map> rowMap = table.rowMap(); + Map> columnMap = table.columnMap(); + System.out.println("rowMap: " + rowMap); + System.out.println("columnMap: " + columnMap); + } + + /** + * 在普通Map中,如果要想根据value查找对应的key,没什么简便的办法,无论是使用for循环还是迭代器,都需要遍历整个Map。 + */ + @Test + public void test双向Map() { + HashBiMap biMap = HashBiMap.create(); + biMap.put("Hydra", "Programmer"); + biMap.put("Tony", "IronMan"); + biMap.put("Thanos", "Titan"); + //使用key获取value + System.out.println("使用key获取value:" + biMap.get("Tony")); + + BiMap inverse = biMap.inverse(); + //使用value获取key + System.out.println("使用value获取key:" + inverse.get("Titan")); + } + + /** + * 上面我们用inverse方法反转了原来BiMap的键值映射,但是这个反转后的BiMap并不是一个新的对象, + * 它实现了一种视图的关联,所以对反转后的BiMap执行的所有操作会作用于原先的BiMap上。 + */ + @Test + public void test双向Map_坑_反转后操作的影响() { + HashBiMap biMap = HashBiMap.create(); + biMap.put("Hydra", "Programmer"); + biMap.put("Tony", "IronMan"); + biMap.put("Thanos", "Titan"); + BiMap inverse = biMap.inverse(); + + // 原先值为IronMan时对应的键是Tony,虽然没有直接修改,但是现在键变成了Stark + inverse.put("IronMan", "Stark"); + System.out.println(biMap); + } + + @Test + public void test双向Map_坑_value不可重复() { + // 双向的BiMap,key和value都不允许重复 + HashBiMap biMap = HashBiMap.create(); + biMap.put("Tony", "IronMan"); + // java.lang.IllegalArgumentException: value already present: IronMan + biMap.put("Stark", "IronMan"); + } + + @Test + public void test双向Map_坑_value不可重复2() { + // 把新的key映射到已有的value上,使用forcePut方法强制替换掉原有的key + HashBiMap biMap = HashBiMap.create(); + biMap.put("Tony", "IronMan"); + biMap.forcePut("Stark", "IronMan"); + // 由于BiMap的value是不允许重复的,因此它的values方法返回的是没有重复的Set,而不是普通Collection: + Set values = biMap.values(); + } + + /** + * 将一个键映射到多个值 + */ + @Test + public void test多值Map() { + Multimap multimap = ArrayListMultimap.create(); + multimap.put("day", 1); + multimap.put("day", 2); + multimap.put("day", 8); + multimap.put("month", 3); + // {month=[3], day=[1, 2, 8]} + System.out.println(multimap); + + // 1、获取值的集合 + System.out.println("---获取值的集合"); + Collection day = multimap.get("day"); + // 如果在创建时指定为ArrayListMultimap类型,那么get方法将返回一个List: + // 同理,你还可以创建HashMultimap、TreeMultimap等类型的Multimap。 + ArrayListMultimap multimap2 = ArrayListMultimap.create(); + List day2 = multimap2.get("day"); + // Multimap的get方法会返回一个非null的集合,但是这个集合的内容可能是空,看一下下面的例子: + List day22 = multimap2.get("day"); + List year2 = multimap2.get("year"); + System.out.println(day22); + System.out.println(year2); + + } + + /** + * 和BiMap的使用类似,使用get方法返回的集合也不是一个独立的对象, + * 可以理解为集合视图的关联,对这个新集合的操作仍然会作用于原始的Multimap上 + */ + @Test + public void test多值Map_操作get后的集合() { + ArrayListMultimap multimap = ArrayListMultimap.create(); + multimap.put("day", 1); + multimap.put("day", 2); + multimap.put("day", 8); + multimap.put("month", 3); + + List day = multimap.get("day"); + List month = multimap.get("month"); + + System.out.println("before:" + multimap); + day.remove(0);//这个0是下标 + month.add(12); + System.out.println("after:" + multimap); + } + + /** + * 使用asMap方法,可以将Multimap转换为Map的形式, + * 同样这个Map也可以看做一个关联的视图,在这个Map上的操作会作用于原始的Multimap + */ + @Test + public void test多值Map_转换为Map() { + Multimap multimap = ArrayListMultimap.create(); + multimap.put("day", 1); + multimap.put("day", 2); + multimap.put("day", 8); + multimap.put("month", 3); + + Map> map = multimap.asMap(); + for (String key : map.keySet()) { + System.out.println(key + " : " + map.get(key)); + } + map.get("day").add(20); + System.out.println(multimap); + } + + @Test + public void test多值Map_坑_数量问题() { + Multimap multimap = ArrayListMultimap.create(); + multimap.put("day", 1); + multimap.put("day", 2); + multimap.put("day", 8); + multimap.put("month", 3); + + for (Map.Entry entry : multimap.entries()) { + System.out.println(entry.getKey() + "," + entry.getValue()); + } + + // size()方法返回的是所有key到单个value的映射,因此结果为4,entries()方法同理 + System.out.println(multimap.size()); + System.out.println(multimap.entries().size()); + // 但是它的keySet中保存的是不同的key的个数,例如下面这行代码打印的结果就会是2 + System.out.println(multimap.keySet().size()); + } + + public static String getRank(int score) { + if (0 <= score && score < 60) + return "fail"; + else if (60 <= score && score <= 90) + return "satisfactory"; + else if (90 < score && score <= 100) + return "excellent"; + return null; + } + + /** + * 要根据分数对考试成绩进行分类 + * guava中的RangeMap描述了一种从区间到特定值的映射关系,让我们能够以更为优雅的方法来书写代码 + */ + @Test + public void test范围Map() { + RangeMap rangeMap = TreeRangeMap.create(); + rangeMap.put(Range.closedOpen(0, 60), "fail"); + rangeMap.put(Range.closed(60, 90), "satisfactory"); + rangeMap.put(Range.openClosed(90, 100), "excellent"); + + System.out.println(rangeMap.get(59)); + System.out.println(rangeMap.get(60)); + System.out.println(rangeMap.get(90)); + System.out.println(rangeMap.get(91)); + + rangeMap.remove(Range.closed(70, 80)); + System.out.println(rangeMap.get(75)); + } + + /** + * ClassToInstanceMap相对普通Map + * 1、取出对象时省去了复杂的强制类型转换 + * 2、通过泛型保证value要符合key所对应的类型 + */ + @Test + public void test实例Map() { + ClassToInstanceMap instanceMap = MutableClassToInstanceMap.create(); + HashMap hashMap = new HashMap<>(); + TreeMap treeMap = new TreeMap<>(); + ArrayList list = new ArrayList<>(); + + instanceMap.putInstance(HashMap.class, hashMap); + instanceMap.putInstance(TreeMap.class, treeMap); + // HashMap和TreeMap都集成了Map父类,但是如果想放入其他类型,就会编译报错 +// instanceMap.putInstance(ArrayList.class,list); + } + + @Test + public void test实例Map对比普通Map() { + Map map = new HashMap<>(); + + HashMap hashMap = new HashMap<>(); + TreeMap treeMap = new TreeMap<>(); + ArrayList list = new ArrayList<>(); + + map.put(HashMap.class, hashMap); + map.put(TreeMap.class, treeMap); + // 1、类型转换 + treeMap = (TreeMap) map.get(TreeMap.class); + // 2、无法限制只存某些Class + map.put(ArrayList.class, list); + } + +} diff --git a/framework/guava/src/main/java/cn/lastwhisper/limit/TestRateLimiter.java b/framework/guava/src/main/java/cn/lastwhisper/limit/TestRateLimiter.java new file mode 100644 index 00000000..2cf1bb06 --- /dev/null +++ b/framework/guava/src/main/java/cn/lastwhisper/limit/TestRateLimiter.java @@ -0,0 +1,39 @@ +package cn.lastwhisper.limit; + +import com.google.common.util.concurrent.RateLimiter; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Guava的RateLimiter限流基于令牌桶算法 + * @author lastwhisper + */ +public class TestRateLimiter { + + /** + * 单机全局限流器(限制QPS为1)(放入拦截器,对HTTP接口限流) + */ + private static RateLimiter limiter = RateLimiter.create(1.0); + + /** + * 固定10个线程,模拟十个用户并发 + */ + private static ExecutorService pool = Executors.newFixedThreadPool(10); + + static class Task implements Runnable { + @Override + public void run() { + limiter.acquire(); // 对应web项目,就是在业务代码之前执行(拦截器、AOP) + System.out.println(System.currentTimeMillis()); + } + } + + public static void main(String[] args) { + for (int i = 0; i < 50; i++) { + pool.submit(new Task()); + } + } + + +} diff --git a/framework/guava/src/main/java/cn/lastwhisper/limit/TokenBucket.java b/framework/guava/src/main/java/cn/lastwhisper/limit/TokenBucket.java new file mode 100644 index 00000000..3e2632a4 --- /dev/null +++ b/framework/guava/src/main/java/cn/lastwhisper/limit/TokenBucket.java @@ -0,0 +1,39 @@ +package cn.lastwhisper.limit; + +// 因为令牌桶对业务有一定的容忍度 +public class TokenBucket { + + private int bucketNums = 100; // 桶的容量 + private int rate = 1; // 流入速度 + private int nowTokens; // 当前令牌数量 + private long timestamp = getNowTime(); // 时间 + + private long getNowTime() { + return System.currentTimeMillis(); + } + + private int min(int tokens) { + return Math.min(bucketNums, tokens); + } + + public boolean getToken() { + // 记录来拿令牌的时间 + long nowTime = getNowTime(); + // 添加令牌【判断该有多少个令牌】 + nowTokens = nowTokens + (int) ((nowTime - timestamp) * rate); + // 添加以后的令牌数量与桶的容量那个小 + nowTokens = min(nowTokens); + System.out.println("当前令牌数量" + nowTokens); + // 修改拿令牌的时间 + timestamp = nowTime; + // 判断令牌是否足够 + if (nowTokens < 1) { + return false; + } else { + nowTokens -= 1; + return true; + } + } + + +} \ No newline at end of file diff --git a/framework/hutool/pom.xml b/framework/hutool/pom.xml new file mode 100644 index 00000000..11821973 --- /dev/null +++ b/framework/hutool/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + + cn.cunchang + hutool + 1.0-SNAPSHOT + + + 8 + 8 + + + + + + junit + junit + 4.12 + test + + + + cn.hutool + hutool-all + 5.8.0 + + + + \ No newline at end of file diff --git a/framework/hutool/src/main/java/cn/cunchang/IDUtilTest.java b/framework/hutool/src/main/java/cn/cunchang/IDUtilTest.java new file mode 100644 index 00000000..3f2e5a80 --- /dev/null +++ b/framework/hutool/src/main/java/cn/cunchang/IDUtilTest.java @@ -0,0 +1,17 @@ +package cn.cunchang; + +import cn.hutool.core.util.IdUtil; + +/** + * @author cunchang + * @date 2022/5/15 11:43 PM + */ +public class IDUtilTest { + + public static void main(String[] args) { + System.out.println(IdUtil.getSnowflakeNextId()); +// System.out.println(IdUtil.objectId()); + + + } +} diff --git a/framework/hutool/src/main/java/cn/cunchang/ZipUtilTest.java b/framework/hutool/src/main/java/cn/cunchang/ZipUtilTest.java new file mode 100644 index 00000000..06928b9d --- /dev/null +++ b/framework/hutool/src/main/java/cn/cunchang/ZipUtilTest.java @@ -0,0 +1,24 @@ +package cn.cunchang; + +import cn.hutool.core.util.ZipUtil; + +import java.io.File; + +/** + * 解压文件 + * @author cunchang + * @date 2022/5/9 2:51 PM + */ +public class ZipUtilTest { + + public static void main(String[] args) { + //将test.zip解压到e:\\aaa目录下,返回解压到的目录 + File unzip = ZipUtil.unzip("/Users/cunchang/Downloads/1.zip", "/Users/cunchang/Downloads/receipt"); + System.out.println(unzip.getAbsoluteFile()); + String[] filePaths = unzip.list(); + for (String filePath : filePaths) { + System.out.println(unzip.getAbsoluteFile()+"/"+filePath); + } + } + +} diff --git a/framework/pinyin4j/pom.xml b/framework/pinyin4j/pom.xml new file mode 100644 index 00000000..b0b580b2 --- /dev/null +++ b/framework/pinyin4j/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + cn.lastwhisper + pinyin4j + 1.0-SNAPSHOT + + + + + com.belerweb + pinyin4j + 2.5.0 + + + + \ No newline at end of file diff --git a/framework/pinyin4j/src/main/java/cn/lastwhisper/DeCode.java b/framework/pinyin4j/src/main/java/cn/lastwhisper/DeCode.java new file mode 100644 index 00000000..d9ebccd7 --- /dev/null +++ b/framework/pinyin4j/src/main/java/cn/lastwhisper/DeCode.java @@ -0,0 +1,20 @@ +package cn.lastwhisper; + +/** + * + * @author lastwhisper + * @date 2020/6/8 + */ +public class DeCode { + + public static void main(String[] args) { + final String words = "原谅女儿离开父亲 昨日看到急报提示 " + + "阴祸氏突袭数据库 然后立刻离开城门 " + + "发现事情并不单纯 于是就跟随他来此 " + + "如果我没法再找寻 根据这追踪器书信 " + + "一定就会发现原因 "; + String binary = PinYinUtil.word2Tonal(words); + System.out.println(PinYinUtil.binary2Ascii(binary)); + } + +} diff --git a/framework/pinyin4j/src/main/java/cn/lastwhisper/PinYinUtil.java b/framework/pinyin4j/src/main/java/cn/lastwhisper/PinYinUtil.java new file mode 100644 index 00000000..2bdc9d03 --- /dev/null +++ b/framework/pinyin4j/src/main/java/cn/lastwhisper/PinYinUtil.java @@ -0,0 +1,171 @@ +package cn.lastwhisper; + +import net.sourceforge.pinyin4j.PinyinHelper; +import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; +import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat; +import net.sourceforge.pinyin4j.format.HanyuPinyinToneType; +import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType; +import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; + +import static net.sourceforge.pinyin4j.format.HanyuPinyinCaseType.LOWERCASE; +import static net.sourceforge.pinyin4j.format.HanyuPinyinToneType.WITHOUT_TONE; +import static net.sourceforge.pinyin4j.format.HanyuPinyinToneType.WITH_TONE_NUMBER; +import static net.sourceforge.pinyin4j.format.HanyuPinyinVCharType.WITH_V; + +/** + * @author lastwhisper + */ +public class PinYinUtil { + + /** + * @param words 汉字字符串 + */ + public static String words2Pinyin(String words) { + return words2Pinyin(words, getDefaultPinyinFormat()); + } + + /** + * @param words 汉字字符串 + * @param pinyinFormat 汉字转拼音格式化模式 + */ + public static String words2Pinyin(String words, HanyuPinyinOutputFormat pinyinFormat) { + return words2Pinyin(words.toCharArray(), pinyinFormat); + } + + /** + * @param chars 汉字字符数组 + * @param pinyinFormat 汉字转拼音格式化模式 + */ + public static String words2Pinyin(char[] chars, HanyuPinyinOutputFormat pinyinFormat) { + StringBuilder pinyinBuilder = new StringBuilder(); + try { + for (char word : chars) { + //是否为汉字字符 + if (Character.toString(word).matches("[\\u4E00-\\u9FA5]+")) { + // 多音字 + String[] py = PinyinHelper.toHanyuPinyinStringArray(word, pinyinFormat); + pinyinBuilder.append(py[0]); + } else { + pinyinBuilder.append(word); + } + } + } catch (BadHanyuPinyinOutputFormatCombination e) { + e.printStackTrace(); + } + return pinyinBuilder.toString(); + } + + /** + * 小写、音标无声调无音符、v表示ü + * @return net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat + */ + public static HanyuPinyinOutputFormat getDefaultPinyinFormat() { + return getPinyinFormat(LOWERCASE, WITHOUT_TONE, WITH_V); + } + + /** + * 小写、音标有声调无音符、v表示ü + * @return net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat + */ + public static HanyuPinyinOutputFormat getToneNumberPinyinFormat() { + return getPinyinFormat(LOWERCASE, WITH_TONE_NUMBER, WITH_V); + } + + /** + * 获取汉语拼音格式化器 + * @param caseType 大小写 + * @see HanyuPinyinCaseType + * UPPERCASE:大写 (ZHONG) + * LOWERCASE:小写 (zhong) + * @param toneType 音标格式 + * @see HanyuPinyinToneType + * WITHOUT_TONE:无音标 (zhong) + * WITH_TONE_NUMBER:1-4数字表示英标 (zhong4) + * WITH_TONE_MARK:直接用音标符(必须WITH_U_UNICODE否则异常) (zhòng) + * @param charType charType + * @see HanyuPinyinVCharType + * WITH_V:用v表示ü (nv) + * WITH_U_AND_COLON:用"u:"表示ü (nu:) + * WITH_U_UNICODE:直接用ü (nü) + * @return net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat + */ + public static HanyuPinyinOutputFormat getPinyinFormat(HanyuPinyinCaseType caseType, HanyuPinyinToneType toneType, HanyuPinyinVCharType charType) { + HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat(); + format.setCaseType(caseType); + format.setToneType(toneType); + format.setVCharType(charType); + return format; + } + + /** + * 汉字串转声调 + * @param words 字符串 + * @return java.lang.String 声调串 + * 1,2,3,4 + */ + public static String word2ToneNumber(String words) { + String tones = words2Pinyin(words, getToneNumberPinyinFormat()); + StringBuilder toneNumBuilder = new StringBuilder(); + for (int i = 0; i < tones.length(); i++) { + char c = tones.charAt(i); + if (isTonal(c)) { + toneNumBuilder.append(c); + } + } + return toneNumBuilder.toString(); + } + + private static boolean isTonal(char c) { + return isLow(c) || isHeight(c); + } + + private static boolean isLow(char c) { + return c == 49 || c == 50; + } + + private static boolean isHeight(char c) { + return c == 51 || c == 52; + } + + /** + * 汉字串转平仄 + * @param words 字符串 + * @return java.lang.String 平仄 + * 1,2:平、3,4:仄 + * 平:0、仄:1 + */ + public static String word2Tonal(String words) { + String tones = words2Pinyin(words, getToneNumberPinyinFormat()); + StringBuilder tonalNumBuilder = new StringBuilder(); + for (int i = 0; i < tones.length(); i++) { + char c = tones.charAt(i); + if (isLow(c)) { + tonalNumBuilder.append(0); + } else if (isHeight(c)) { + tonalNumBuilder.append(1); + } + } + return tonalNumBuilder.toString(); + } + + /** + * @param binary 二进制串 + * @return java.lang.String 对应的ASCII + */ + public static String binary2Ascii(String binary) { + StringBuilder asciiBuilder = new StringBuilder(); + for (int i = 0; i < binary.length(); i += 8) { + asciiBuilder.append((char) Integer.parseInt(binary.substring(i, i + 8), 2)); + } + return asciiBuilder.toString(); + } + + public static void main(String[] args) { + String words = "原谅女儿离开父亲 昨日看到急报提示 "; + String tonal = word2Tonal(words); + System.out.println(tonal); + String str = binary2Ascii(tonal); + System.out.println(str); + } + +} \ No newline at end of file diff --git a/framework/tika/pom.xml b/framework/tika/pom.xml new file mode 100644 index 00000000..cfba6fe7 --- /dev/null +++ b/framework/tika/pom.xml @@ -0,0 +1,64 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.3.3.RELEASE + + + cn.lastwhisper + tika + 0.0.1-SNAPSHOT + tika + tika demo + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + + + org.apache.tika + tika-core + 1.24.1 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/framework/tika/src/main/java/cn/lastwhisper/TikaApplication.java b/framework/tika/src/main/java/cn/lastwhisper/TikaApplication.java new file mode 100644 index 00000000..2d19c1d7 --- /dev/null +++ b/framework/tika/src/main/java/cn/lastwhisper/TikaApplication.java @@ -0,0 +1,13 @@ +package cn.lastwhisper; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TikaApplication { + + public static void main(String[] args) { + SpringApplication.run(TikaApplication.class, args); + } + +} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/src/main/resources/application.properties b/framework/tika/src/main/resources/application.properties similarity index 100% rename from springboot-integration-examples/springboot-dubbo-tcc-instance/src/main/resources/application.properties rename to framework/tika/src/main/resources/application.properties diff --git a/framework/tika/src/test/java/cn/lastwhisper/TikaApplicationTests.java b/framework/tika/src/test/java/cn/lastwhisper/TikaApplicationTests.java new file mode 100644 index 00000000..f779b7a1 --- /dev/null +++ b/framework/tika/src/test/java/cn/lastwhisper/TikaApplicationTests.java @@ -0,0 +1,15 @@ +package cn.lastwhisper; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class TikaApplicationTests { + + @Test + void contextLoads() { + + + } + +} diff --git a/framework/tika/src/test/java/cn/lastwhisper/TikaTest.java b/framework/tika/src/test/java/cn/lastwhisper/TikaTest.java new file mode 100644 index 00000000..b70bc85b --- /dev/null +++ b/framework/tika/src/test/java/cn/lastwhisper/TikaTest.java @@ -0,0 +1,73 @@ +package cn.lastwhisper; + +import org.apache.tika.Tika; +import org.apache.tika.config.TikaConfig; +import org.apache.tika.detect.Detector; +import org.apache.tika.exception.TikaException; +import org.apache.tika.metadata.HttpHeaders; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.mime.MediaType; +import org.apache.tika.mime.MimeType; +import org.apache.tika.mime.MimeTypes; +import org.apache.tika.parser.AutoDetectParser; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +/** + * @author cunchang + * @date 2020/8/26 下午7:38 + */ +public class TikaTest { + + public static void main(String[] args) throws IOException, TikaException { + + List fileNames = new ArrayList<>(); + fileNames.add("template.xls"); + fileNames.add("mapreduce-osdi04.pdf"); + fileNames.add("测试.docx"); + fileNames.add("测试.xlsx"); + fileNames.add("测试.xlsx"); + fileNames.add("transportation.png"); + fileNames.add("timg.gif"); + fileNames.add("timg"); + + for (String fileName : fileNames) { + InputStream stream = TikaTest.class.getClassLoader().getResourceAsStream(fileName); + System.out.print(fileName+"\t"); + getMimeType(stream); + } + + + + } + + public static void getType(InputStream is) throws TikaException, IOException { + TikaConfig tikaConfig = new TikaConfig(); + + Detector detector = tikaConfig.getDetector(); + Metadata metadata = new Metadata(); + MediaType mediaType = detector.detect(is, metadata); + System.out.println(mediaType.getBaseType()); + System.out.println(mediaType.getSubtype()); + System.out.println("-------------------------------------------------------"); + } + + public static void getMimeType(InputStream inputStream) throws TikaException, IOException { + AutoDetectParser parser = new AutoDetectParser(); + Metadata metadata = new Metadata(); + DefaultHandler handler = new DefaultHandler(); + try { + parser.parse(inputStream, handler, metadata); + } catch (TikaException | SAXException | IOException e) { + e.printStackTrace(); + } + System.out.println(metadata.get(HttpHeaders.CONTENT_TYPE)); + } +} diff --git a/framework/tika/src/test/resources/TikaApplication.java b/framework/tika/src/test/resources/TikaApplication.java new file mode 100644 index 00000000..2d19c1d7 --- /dev/null +++ b/framework/tika/src/test/resources/TikaApplication.java @@ -0,0 +1,13 @@ +package cn.lastwhisper; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TikaApplication { + + public static void main(String[] args) { + SpringApplication.run(TikaApplication.class, args); + } + +} diff --git a/springboot-integration-examples/springboot-duboo-filter/src/main/resources/application.properties b/framework/tika/src/test/resources/application.properties similarity index 100% rename from springboot-integration-examples/springboot-duboo-filter/src/main/resources/application.properties rename to framework/tika/src/test/resources/application.properties diff --git a/framework/tika/src/test/resources/mapreduce-osdi04.pdf b/framework/tika/src/test/resources/mapreduce-osdi04.pdf new file mode 100644 index 00000000..fce88256 Binary files /dev/null and b/framework/tika/src/test/resources/mapreduce-osdi04.pdf differ diff --git a/framework/tika/src/test/resources/office.xlsx b/framework/tika/src/test/resources/office.xlsx new file mode 100644 index 00000000..c6a50d20 Binary files /dev/null and b/framework/tika/src/test/resources/office.xlsx differ diff --git a/framework/tika/src/test/resources/template.xls b/framework/tika/src/test/resources/template.xls new file mode 100644 index 00000000..509416be Binary files /dev/null and b/framework/tika/src/test/resources/template.xls differ diff --git a/framework/tika/src/test/resources/timg b/framework/tika/src/test/resources/timg new file mode 100644 index 00000000..83a692a3 Binary files /dev/null and b/framework/tika/src/test/resources/timg differ diff --git a/framework/tika/src/test/resources/timg.gif b/framework/tika/src/test/resources/timg.gif new file mode 100644 index 00000000..0ccdd16c Binary files /dev/null and b/framework/tika/src/test/resources/timg.gif differ diff --git a/framework/tika/src/test/resources/timg.jpg b/framework/tika/src/test/resources/timg.jpg new file mode 100644 index 00000000..83a692a3 Binary files /dev/null and b/framework/tika/src/test/resources/timg.jpg differ diff --git a/framework/tika/src/test/resources/timg.jpg.zip b/framework/tika/src/test/resources/timg.jpg.zip new file mode 100644 index 00000000..15250d23 Binary files /dev/null and b/framework/tika/src/test/resources/timg.jpg.zip differ diff --git a/framework/tika/src/test/resources/transportation.png b/framework/tika/src/test/resources/transportation.png new file mode 100644 index 00000000..e4521f86 Binary files /dev/null and b/framework/tika/src/test/resources/transportation.png differ diff --git "a/framework/tika/src/test/resources/\346\265\213\350\257\225.docx" "b/framework/tika/src/test/resources/\346\265\213\350\257\225.docx" new file mode 100644 index 00000000..d4021512 Binary files /dev/null and "b/framework/tika/src/test/resources/\346\265\213\350\257\225.docx" differ diff --git "a/framework/tika/src/test/resources/\346\265\213\350\257\225.xlsx" "b/framework/tika/src/test/resources/\346\265\213\350\257\225.xlsx" new file mode 100644 index 00000000..7e62b3d2 Binary files /dev/null and "b/framework/tika/src/test/resources/\346\265\213\350\257\225.xlsx" differ diff --git a/java-advance/README.md b/java-advance/README.md new file mode 100644 index 00000000..4f211e21 --- /dev/null +++ b/java-advance/README.md @@ -0,0 +1,52 @@ +# 进阶 + +- annotation;java注解相关:编译期处理注解、运行时解析并修改注解 +- groovy;Groovy可以被视为Java的一种脚本化改良版。 + +- javaagent:代码注入 + +- javassist:*Javassist*是一个开源的分析、编辑和创建Java字节码的类库 +- network:java实现正向代理 +- proxy:java动态代理 +- spi:服务提供者接口(Service Provider Interface,简写为SPI)是JDK内置的一种服务提供发现机制。 + + + +# annotation + +- **JSR 175: A Metadata Facility for the Java**TM **Programming Language** +- **JSR 269: Pluggable Annotation Processing API** + + + +# spi + +面向对象的设计推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则:如果需要替换组建的一种实现,就需要修改框架的代码。SPI机制正是解决这个问题。 + +Java中SPI机制主要思想是将装配的控制权移到程序之外,是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制,有点类似Spring的IOC机制。在模块化设计中这个机制尤其重要,其核心思想就是解耦。 + +**缺点** + +- 不能按需加载。虽然 ServiceLoader 做了延迟加载,但是只能通过遍历的方式全部获取。如果其中某些实现类很耗时,而且你也不需要加载它,那么就形成了资源浪费 +- 获取某个实现类的方式不够灵活,只能通过迭代器的形式获取 + +> Dubbo SPI 实现方式对以上两点进行了业务优化。 + +# javaagent + +**简介** + +javaagent是一种能够在不影响正常编译的情况下,修改字节码。java作为一种强类型的语言,不通过编译就不能能够进行jar包的生成。而有了javaagent技术,就可以在字节码这个层面对类和方法进行修改。同时,也可以把javaagent理解成一种代码注入的方式。但是这种注入比起spring的aop更加的优美。 + +**主要作用** + +- 可以在加载java文件之前做拦截把字节码做修改 +- 可以在运行期将已经加载的类的字节码做变更,但是这种情况下会有很多的限制,后面会详细说 + 还有其他的一些小众的功能 +- 获取所有已经被加载过的类 +- 获取所有已经被初始化过了的类(执行过了clinit方法,是上面的一个子集) +- 获取某个对象的大小 +- 将某个jar加入到bootstrapclasspath里作为高优先级被bootstrapClassloader加载 +- 将某个jar加入到classpath里供AppClassload去加载 +- 设置某些native方法的前缀,主要在查找native方法的时候做规则匹配 + diff --git a/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok-test/pom.xml b/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok-test/pom.xml new file mode 100644 index 00000000..b6c3074c --- /dev/null +++ b/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok-test/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + cn.cunchang + mylombok-test + 1.0-SNAPSHOT + + + 8 + 8 + + + + + cn.cunchang + mylombok + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok-test/src/main/java/cn/cunchang/Person.java b/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok-test/src/main/java/cn/cunchang/Person.java new file mode 100644 index 00000000..433c3e52 --- /dev/null +++ b/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok-test/src/main/java/cn/cunchang/Person.java @@ -0,0 +1,8 @@ +package cn.cunchang; + +@MyGetter +public class Person { + + private String name; + +} diff --git a/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok/pom.xml b/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok/pom.xml new file mode 100644 index 00000000..86b5ddbd --- /dev/null +++ b/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + cn.cunchang + mylombok + 1.0-SNAPSHOT + + + 8 + 8 + + + + + tools + tools + 1.0 + system + ${java.home}/../lib/tools.jar + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + + -proc:none + + 1.8 + 1.8 + + + + default-compile + + -proc:none + 1.8 + 1.8 + + + + default-testCompile + + 1.8 + 1.8 + + + + + + + + + diff --git a/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok/src/main/java/cn/cunchang/MyGetter.java b/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok/src/main/java/cn/cunchang/MyGetter.java new file mode 100644 index 00000000..1f997898 --- /dev/null +++ b/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok/src/main/java/cn/cunchang/MyGetter.java @@ -0,0 +1,15 @@ +package cn.cunchang; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author cunchang + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.TYPE) +public @interface MyGetter { + +} diff --git a/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok/src/main/java/cn/cunchang/MyGetterProcessor.java b/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok/src/main/java/cn/cunchang/MyGetterProcessor.java new file mode 100644 index 00000000..e3758e43 --- /dev/null +++ b/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok/src/main/java/cn/cunchang/MyGetterProcessor.java @@ -0,0 +1,98 @@ +package cn.cunchang; + +import com.sun.source.tree.Tree; +import com.sun.tools.javac.api.JavacTrees; +import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.code.Type; +import com.sun.tools.javac.processing.JavacProcessingEnvironment; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.tree.TreeTranslator; +import com.sun.tools.javac.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + + +@SupportedSourceVersion(SourceVersion.RELEASE_8) +@SupportedAnnotationTypes("cn.cunchang.MyGetter") +public class MyGetterProcessor extends AbstractProcessor { + + private Messager messager; // 编译时期输入日志的 + private JavacTrees javacTrees; // 提供了待处理的抽象语法树 + private TreeMaker treeMaker; // 封装了创建AST节点的一些方法 + private Names names; // 提供了创建标识符的方法 + + @Override + public synchronized void init(ProcessingEnvironment processingEnv) { + super.init(processingEnv); + this.messager = processingEnv.getMessager(); + this.javacTrees = JavacTrees.instance(processingEnv); + Context context = ((JavacProcessingEnvironment) processingEnv).getContext(); + this.treeMaker = TreeMaker.instance(context); + this.names = Names.instance(context); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + Set elementsAnnotatedWith = roundEnv.getElementsAnnotatedWith(MyGetter.class); + elementsAnnotatedWith.forEach(e -> { + JCTree tree = javacTrees.getTree(e); + tree.accept(new TreeTranslator() { + @Override + public void visitClassDef(JCTree.JCClassDecl jcClassDecl) { + List jcVariableDeclList = List.nil(); + // 在抽象树中找出所有的变量 + for (JCTree jcTree : jcClassDecl.defs) { + if (jcTree.getKind().equals(Tree.Kind.VARIABLE)) { + JCTree.JCVariableDecl jcVariableDecl = (JCTree.JCVariableDecl) jcTree; + jcVariableDeclList = jcVariableDeclList.append(jcVariableDecl); + } + } + // 对于变量进行生成方法的操作 + jcVariableDeclList.forEach(jcVariableDecl -> { + messager.printMessage(Diagnostic.Kind.NOTE, jcVariableDecl.getName() + " has been processed"); + jcClassDecl.defs = jcClassDecl.defs.prepend(makeGetterMethodDecl(jcVariableDecl)); + }); + super.visitClassDef(jcClassDecl); + } + }); + }); + return true; + } + + private JCTree.JCMethodDecl makeGetterMethodDecl(JCTree.JCVariableDecl jcVariableDecl) { + ListBuffer statements = new ListBuffer<>(); + // 生成表达式 例如 this.a = a; + JCTree.JCExpressionStatement aThis = makeAssignment(treeMaker.Select(treeMaker.Ident( + names.fromString("this")), jcVariableDecl.getName()), treeMaker.Ident(jcVariableDecl.getName())); + statements.append(aThis); + JCTree.JCBlock block = treeMaker.Block(0, statements.toList()); + + // 生成入参 + JCTree.JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(Flags.PARAMETER), + jcVariableDecl.getName(), jcVariableDecl.vartype, null); + List parameters = List.of(param); + + // 生成返回对象 + JCTree.JCExpression methodType = treeMaker.Type(new Type.JCVoidType()); + return treeMaker.MethodDef(treeMaker.Modifiers(Flags.PUBLIC), + getNewMethodName(jcVariableDecl.getName()), methodType, List.nil(), + parameters, List.nil(), block, null); + } + + private Name getNewMethodName(Name name) { + String s = name.toString(); + return names.fromString("get" + s.substring(0, 1).toUpperCase() + s.substring(1, name.length())); + } + + private JCTree.JCExpressionStatement makeAssignment(JCTree.JCExpression lhs, JCTree.JCExpression rhs) { + return treeMaker.Exec(treeMaker.Assign(lhs,rhs)); + } +} diff --git a/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok/src/main/resources/META-INF/services/javax.annotation.processing.Processor new file mode 100644 index 00000000..d0e62499 --- /dev/null +++ b/java-advance/annotation/PluggableAnnotationProcessingAPI/mylombok/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -0,0 +1 @@ +cn.cunchang.MyGetterProcessor \ No newline at end of file diff --git a/java-advance/annotation/README.md b/java-advance/annotation/README.md new file mode 100644 index 00000000..11ba12d8 --- /dev/null +++ b/java-advance/annotation/README.md @@ -0,0 +1,24 @@ +# annotation + +JSR 175: A Metadata Facility for the JavaTM Programming Language + + + + + + + +# Pluggable Annotation Processing API + + + +JSR 269: Pluggable Annotation Processing API + +参考:https://juejin.cn/post/6844904106545381384?utm_source=ZHShareTargetIDMore&utm_medium=social&utm_oi=825791253932290048#heading-16 + + + + + + + diff --git a/java-advance/annotation/annatation/pom.xml b/java-advance/annotation/annatation/pom.xml new file mode 100644 index 00000000..d890a7cd --- /dev/null +++ b/java-advance/annotation/annatation/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + + cn.cunchang + annatation + 1.0-SNAPSHOT + + JSR 175: A Metadata Facility for the JavaTM Programming Language + + + 8 + 8 + + + + + junit + junit + 4.13 + + + + \ No newline at end of file diff --git a/java-advance/annotation/annatation/src/main/java/cn/cunchang/AnnotationTest.java b/java-advance/annotation/annatation/src/main/java/cn/cunchang/AnnotationTest.java new file mode 100644 index 00000000..a6eb5ea4 --- /dev/null +++ b/java-advance/annotation/annatation/src/main/java/cn/cunchang/AnnotationTest.java @@ -0,0 +1,85 @@ +package cn.cunchang; + +import cn.cunchang.dynamicvalue.JsonProperty; +import cn.cunchang.syntax.MyAnnotation; +import org.junit.Test; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Arrays; +import java.util.Map; +import java.util.Objects; + +/** + * jdk5新特性:注解 + * + * @author cunchang + */ +public class AnnotationTest { + + @Test + public void test一个什么都有的注解() throws Exception { + Class clazz = Class.forName("cn.cunchang.syntax.UseAnnotation"); + // 类上的注解 + if (clazz.isAnnotationPresent(MyAnnotation.class)) { + MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class); + System.err.println("使用类上的注解"); + printMyAnnotation(annotation); + } + // 方法上的注解 + Method[] methods = clazz.getDeclaredMethods(); + for (Method method : methods) { + MyAnnotation annotation = method.getAnnotation(MyAnnotation.class); + System.err.println("使用方法上的注解"); + printMyAnnotation(annotation); + } + } + + public void printMyAnnotation(MyAnnotation annotation) { + if(Objects.isNull(annotation)){ + return; + } + System.out.println(annotation.color()); + System.out.println(annotation.value()); + System.out.println(Arrays.toString(annotation.arrayAttr())); + System.out.println(annotation.clazz()); + System.out.println(annotation.enumLevel()); + System.out.println(annotation.annotation().value()); + } + + /** + * Changing Annotation Parameters At Runtime + *

+ * https://segmentfault.com/a/1190000011213222 + * + * @throws Exception + */ + @Test + public void test运行期动态修改注解value() throws Exception { + Class clazz = Class.forName("cn.cunchang.dynamicvalue.StudentRsp"); + //获取 StudentRsp 的 name 字段 + Field field = clazz.getDeclaredField("name"); + //获取 name 字段上的 JsonProperty 注解实例 + JsonProperty jsonProperty = field.getAnnotation(JsonProperty.class); + + System.out.println("当前 jsonProperty value:" + jsonProperty.value()); + + //获取 JsonProperty 这个代理实例所持有的 InvocationHandler + InvocationHandler invocationHandler = Proxy.getInvocationHandler(jsonProperty); + // 获取 AnnotationInvocationHandler 的 memberValues 字段 + Field hField = invocationHandler.getClass().getDeclaredField("memberValues"); + // 设置访问权限 + hField.setAccessible(true); + // 获取 memberValues + Map memberValues = (Map) hField.get(invocationHandler); + // 修改 value 属性值 + memberValues.put("value", "beisen_pro_name"); + + // 获取 JsonProperty 的 value 属性值 + System.out.println("当前 jsonProperty value:" + jsonProperty.value()); + + } + +} diff --git a/java-advance/annotation/annatation/src/main/java/cn/cunchang/corejava/buttons3/ButtonFrame.java b/java-advance/annotation/annatation/src/main/java/cn/cunchang/corejava/buttons3/ButtonFrame.java new file mode 100644 index 00000000..782effcd --- /dev/null +++ b/java-advance/annotation/annatation/src/main/java/cn/cunchang/corejava/buttons3/ButtonFrame.java @@ -0,0 +1,59 @@ +package cn.cunchang.corejava.buttons3; + +import java.awt.*; +import javax.swing.*; + +import cn.cunchang.corejava.runtimeAnnotations.ActionListenerFor; +import cn.cunchang.corejava.runtimeAnnotations.ActionListenerInstaller; + +/** + * A frame with a button panel. + * @version 1.00 2004-08-17 + * @author Cay Horstmann + */ +public class ButtonFrame extends JFrame +{ + private static final int DEFAULT_WIDTH = 300; + private static final int DEFAULT_HEIGHT = 200; + + private JPanel panel; + private JButton yellowButton; + private JButton blueButton; + private JButton redButton; + + public ButtonFrame() + { + setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); + + panel = new JPanel(); + add(panel); + + yellowButton = new JButton("Yellow"); + blueButton = new JButton("Blue"); + redButton = new JButton("Red"); + + panel.add(yellowButton); + panel.add(blueButton); + panel.add(redButton); + + ActionListenerInstaller.processAnnotations(this); + } + + @ActionListenerFor(source = "yellowButton") + public void yellowBackground() + { + panel.setBackground(Color.YELLOW); + } + + @ActionListenerFor(source = "blueButton") + public void blueBackground() + { + panel.setBackground(Color.BLUE); + } + + @ActionListenerFor(source = "redButton") + public void redBackground() + { + panel.setBackground(Color.RED); + } +} diff --git a/java-advance/annotation/annatation/src/main/java/cn/cunchang/corejava/buttons3/ButtonTest.java b/java-advance/annotation/annatation/src/main/java/cn/cunchang/corejava/buttons3/ButtonTest.java new file mode 100644 index 00000000..de248322 --- /dev/null +++ b/java-advance/annotation/annatation/src/main/java/cn/cunchang/corejava/buttons3/ButtonTest.java @@ -0,0 +1,23 @@ +package cn.cunchang.corejava.buttons3; + +import java.awt.*; +import javax.swing.*; + +/** + * @version 1.01 2016-05-10 + * @author Cay Horstmann + */ +public class ButtonTest +{ + public static void main(String[] args) + { + EventQueue.invokeLater(() -> + { + + ButtonFrame frame = new ButtonFrame(); + frame.setTitle("ButtonTest"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + }); + } +} \ No newline at end of file diff --git a/java-advance/annotation/annatation/src/main/java/cn/cunchang/corejava/runtimeAnnotations/ActionListenerFor.java b/java-advance/annotation/annatation/src/main/java/cn/cunchang/corejava/runtimeAnnotations/ActionListenerFor.java new file mode 100644 index 00000000..33495d4f --- /dev/null +++ b/java-advance/annotation/annatation/src/main/java/cn/cunchang/corejava/runtimeAnnotations/ActionListenerFor.java @@ -0,0 +1,15 @@ +package cn.cunchang.corejava.runtimeAnnotations; + +import java.lang.annotation.*; + +/** + * @version 1.00 2004-08-17 + * @author Cay Horstmann + */ + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface ActionListenerFor +{ + String source(); +} diff --git a/java-advance/annotation/annatation/src/main/java/cn/cunchang/corejava/runtimeAnnotations/ActionListenerInstaller.java b/java-advance/annotation/annatation/src/main/java/cn/cunchang/corejava/runtimeAnnotations/ActionListenerInstaller.java new file mode 100644 index 00000000..18924fee --- /dev/null +++ b/java-advance/annotation/annatation/src/main/java/cn/cunchang/corejava/runtimeAnnotations/ActionListenerInstaller.java @@ -0,0 +1,62 @@ +package cn.cunchang.corejava.runtimeAnnotations; + +import java.awt.event.*; +import java.lang.reflect.*; + +/** + * @version 1.00 2004-08-17 + * @author Cay Horstmann + */ +public class ActionListenerInstaller +{ + /** + * Processes all ActionListenerFor annotations in the given object. + * @param obj an object whose methods may have ActionListenerFor annotations + */ + public static void processAnnotations(Object obj) + { + try + { + Class cl = obj.getClass(); + // 获取所有方法 + for (Method m : cl.getDeclaredMethods()) + { + ActionListenerFor a = m.getAnnotation(ActionListenerFor.class); + if (a != null) + { + // 获取方法上的注解,ActionListenerFor 里面的 source 值 + Field f = cl.getDeclaredField(a.source()); + f.setAccessible(true); + addListener(f.get(obj), obj, m); + } + } + } + catch (ReflectiveOperationException e) + { + e.printStackTrace(); + } + } + + /** + * Adds an action listener that calls a given method. + * @param source the event source to which an action listener is added + * @param param the implicit parameter of the method that the listener calls + * @param m the method that the listener calls + */ + public static void addListener(Object source, final Object param, final Method m) + throws ReflectiveOperationException + { + InvocationHandler handler = new InvocationHandler() + { + public Object invoke(Object proxy, Method mm, Object[] args) throws Throwable + { + return m.invoke(param); + } + }; + + Object listener = Proxy.newProxyInstance(null, + new Class[] { ActionListener.class }, handler); + Method adder = source.getClass().getMethod("addActionListener", ActionListener.class); + adder.invoke(source, listener); + } +} diff --git a/java-advance/annotation/annatation/src/main/java/cn/cunchang/dynamicvalue/JsonProperty.java b/java-advance/annotation/annatation/src/main/java/cn/cunchang/dynamicvalue/JsonProperty.java new file mode 100644 index 00000000..ee598dc8 --- /dev/null +++ b/java-advance/annotation/annatation/src/main/java/cn/cunchang/dynamicvalue/JsonProperty.java @@ -0,0 +1,15 @@ +package cn.cunchang.dynamicvalue; + + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD}) +public @interface JsonProperty { + + String value(); + +} diff --git a/java-advance/annotation/annatation/src/main/java/cn/cunchang/dynamicvalue/StudentRsp.java b/java-advance/annotation/annatation/src/main/java/cn/cunchang/dynamicvalue/StudentRsp.java new file mode 100644 index 00000000..1a1608a7 --- /dev/null +++ b/java-advance/annotation/annatation/src/main/java/cn/cunchang/dynamicvalue/StudentRsp.java @@ -0,0 +1,17 @@ +package cn.cunchang.dynamicvalue; + +/** + * @author cunchang + * @date 2021/4/19 8:02 下午 + */ +public class StudentRsp { + + /** + * stable beisen_test_name + * real beisen_pro_name + */ + @JsonProperty("beisen_test_name") + public String name; + + +} diff --git a/java-advance/annotation/annatation/src/main/java/cn/cunchang/syntax/Level.java b/java-advance/annotation/annatation/src/main/java/cn/cunchang/syntax/Level.java new file mode 100644 index 00000000..11d359f3 --- /dev/null +++ b/java-advance/annotation/annatation/src/main/java/cn/cunchang/syntax/Level.java @@ -0,0 +1,3 @@ +package cn.cunchang.syntax; + +public enum Level {BAD, INDIFFERENT, GOOD} \ No newline at end of file diff --git a/java-advance/annotation/annatation/src/main/java/cn/cunchang/syntax/MetaAnnotation.java b/java-advance/annotation/annatation/src/main/java/cn/cunchang/syntax/MetaAnnotation.java new file mode 100644 index 00000000..a9efae29 --- /dev/null +++ b/java-advance/annotation/annatation/src/main/java/cn/cunchang/syntax/MetaAnnotation.java @@ -0,0 +1,7 @@ +package cn.cunchang.syntax; + +public @interface MetaAnnotation { + + String value() default "MetaAnnotation default value"; + +} \ No newline at end of file diff --git a/java-advance/annotation/annatation/src/main/java/cn/cunchang/syntax/MyAnnotation.java b/java-advance/annotation/annatation/src/main/java/cn/cunchang/syntax/MyAnnotation.java new file mode 100644 index 00000000..d3ecda43 --- /dev/null +++ b/java-advance/annotation/annatation/src/main/java/cn/cunchang/syntax/MyAnnotation.java @@ -0,0 +1,37 @@ +package cn.cunchang.syntax; + +// 自定义注解 + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +@Retention(RetentionPolicy.RUNTIME)//保留策略 +@Target({ElementType.METHOD, ElementType.TYPE})//作用目标 // 为什么是TYPE,因为Class的父类是Type +public @interface MyAnnotation { + // 八大基本数据类型、String、Class、Enum、注解类型对应的数组类型 + + String color() default "green"; + + String value();//value比较特殊 + + int[] arrayAttr() default {1, 2, 3}; + + Class clazz() default Formatter.class; + + Level enumLevel() default Level.GOOD; + + MetaAnnotation annotation() default @MetaAnnotation("xxx"); + +} + + +interface Formatter { +} + + + + + diff --git a/java-advance/annotation/annatation/src/main/java/cn/cunchang/syntax/UseAnnotation.java b/java-advance/annotation/annatation/src/main/java/cn/cunchang/syntax/UseAnnotation.java new file mode 100644 index 00000000..58e93f6a --- /dev/null +++ b/java-advance/annotation/annatation/src/main/java/cn/cunchang/syntax/UseAnnotation.java @@ -0,0 +1,23 @@ +package cn.cunchang.syntax; + +/** + * @author cunchang + */ + +@MyAnnotation(color = "red", value = "/user/login", + arrayAttr = {4, 5, 6}, enumLevel = Level.INDIFFERENT, + annotation = @MetaAnnotation("yyy"), clazz = Formatter.class) +public class UseAnnotation { + + @MyAnnotation("yyy") + @SuppressWarnings("deprecation") + public static void deprecatedFun() { + sayHello(); + } + + @Deprecated + public static void sayHello() { + System.out.println("被弃用的函数"); + } + +} diff --git a/java-advance/apm/agent/pom.xml b/java-advance/apm/agent/pom.xml deleted file mode 100644 index 271ab03c..00000000 --- a/java-advance/apm/agent/pom.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - apm - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - cn.lastwhisper.monitor - agent - - - - - maven-assembly-plugin - - - - - - - - ${project.name} - ${project.version} - cn.lastwhisper.monitor.agent.AgentMain - false - - - - jar-with-dependencies - - - - - make-assembly - package - - single - - - - - - - - - - - org.javassist - javassist - 3.18.1-GA - - - org.springframework - spring-webmvc - 4.0.4.RELEASE - - - javax.servlet - javax.servlet-api - 3.1.0 - - - junit - junit - 4.12 - - - org.springframework - spring-beans - 4.0.4.RELEASE - - - org.springframework - spring-context - 4.0.4.RELEASE - - - org.springframework - spring-web - 4.0.4.RELEASE - - - mysql - mysql-connector-java - 5.1.30 - - - - \ No newline at end of file diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/AbstractCollects.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/AbstractCollects.java deleted file mode 100644 index f44d6a65..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/AbstractCollects.java +++ /dev/null @@ -1,316 +0,0 @@ -package cn.lastwhisper.monitor.agent; - - -import cn.lastwhisper.monitor.agent.collects.ErrorLog; -import cn.lastwhisper.monitor.agent.common.NetUtils; -import cn.lastwhisper.monitor.agent.json.JsonWriter; - -import java.io.*; -import java.lang.reflect.InvocationTargetException; -import java.math.BigInteger; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLEncoder; -import java.security.MessageDigest; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Created by tommy on 17/7/14. - */ -public abstract class AbstractCollects { - // 统一线程池 - private final static ExecutorService threadService; - - private static final String localIp; - private static long rejectedCount = 0; - - static { - - //采样率:自动、手动调节 - /** - * 核心线程:50 - * 最大线程:200 - * 最大队例:1000 - */ - threadService = new ThreadPoolExecutor(20, - 100, - 20000L, - TimeUnit.MILLISECONDS, - new LinkedBlockingQueue(1000), - new RejectedExecutionHandler() { - @Override - public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { - rejectedCount++; - System.err.println("upload Task rejected from " + - executor.toString() + " rejectedCount:" + rejectedCount); - } - }); - localIp = NetUtils.getLocalHost(); - } - - // 统计信息 - @NotProguard - public static class Statistics { - public String logType; - private Long begin; - private Long end; - private Long userTime; - private String errorMsg; - private String errorType; - private Long createTime; - private String keyId; - private String ip = localIp; - - - public Statistics() { - - } - - public Statistics(Statistics copy) { - this.begin = copy.begin; - this.createTime = copy.createTime; - this.end = copy.end; - this.errorMsg = copy.errorMsg; - this.errorType = copy.errorType; - this.keyId = copy.keyId; - this.ip = copy.ip; - this.logType = copy.logType; - this.userTime = copy.userTime; - } - - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("{"); - if (begin != null) { - sb.append("\"begin\":").append(begin); - } - if (end != null) { - sb.append(", \"end\":").append(end); - } - if (errorMsg != null) { - sb.append(", \"errorMsg\":\"").append(errorMsg).append('\"'); - } - if (errorType != null) { - sb.append(", \"errorType\":\"").append(errorType).append('\"'); - } - if (createTime != null) { - sb.append(", \"createTime\":").append(createTime); - } - if (keyId != null) { - sb.append(", \"key\":\"").append(keyId).append('\"'); - } - if (sb.substring(1, 1).equals(",")) { - sb.delete(1, 2); - } - sb.append('}'); - return sb.toString(); - } - - public String toJsonString() { - final StringBuilder sb = new StringBuilder("{"); - if (begin != null) { - sb.append("\"begin\":").append(begin); - } - if (end != null) { - sb.append(", \"end\":").append(end); - } - if (errorMsg != null) { - sb.append(", \"errorMsg\":\"").append(errorMsg).append('\"'); - } - if (errorType != null) { - sb.append(", \"errorType\":\"").append(errorType).append('\"'); - } - if (createTime != null) { - sb.append(", \"createTime\":").append(createTime); - } - if (sb.substring(1, 2).equals(",")) { - sb.delete(1, 2); - } - sb.append('}'); - return sb.toString(); - } - - } - - @NotProguard - public Statistics begin(String className, String method) { - Statistics s = new Statistics(); - s.begin = System.currentTimeMillis(); - s.createTime = System.currentTimeMillis(); - return s; - } - - @NotProguard - public void end(Statistics stat) { - stat.end = System.currentTimeMillis(); - stat.userTime = stat.end - stat.begin; - sendStatistics(stat); - // System.out.println("代理结束:" + stat.toString()); - } - - @NotProguard - public void error(Statistics stat, Throwable throwable) { - if (stat != null) { - stat.errorMsg = throwable.getMessage(); - stat.errorType = throwable.getClass().getName(); - if (throwable instanceof InvocationTargetException) { - stat.errorType = ((InvocationTargetException) throwable).getTargetException().getClass().getName(); - stat.errorMsg = ((InvocationTargetException) throwable).getTargetException().getMessage(); - } - } - if (throwable != null) { - sendErrorStackByHttp("", throwable); - } - } - - /** - * 发送统计信息 - * - * @param stat - */ - public abstract void sendStatistics(final Statistics stat); - - protected void sendErrorStackByHttp(String errorMsg, Throwable throwable) { - ErrorLog errorLog = new ErrorLog(); - if (throwable instanceof InvocationTargetException) { - errorLog.setErrorType(((InvocationTargetException) throwable).getTargetException().getClass().getName()); - errorLog.setErrorMsg(((InvocationTargetException) throwable).getTargetException().getMessage()); - } else { - errorLog.setErrorType(throwable.getClass().getName()); - errorLog.setErrorMsg(throwable.getMessage()); - } - errorLog.setKeyId(System.getProperty("$bit_key")); - errorLog.setIp(localIp); - errorLog.setLogType("error"); - errorLog.setCreateTime(System.currentTimeMillis()); - // 计算异常堆栈 - { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - PrintStream s = new PrintStream(out); - throwable.printStackTrace(s); - errorLog.setStack(out.toString()); - } - execHttp("errorLog", errorLog); - } - - protected void execHttp(final String type, final Object data) { - Runnable runn = new Runnable() { - public void run() { - try { - String remoteUrl = System.getProperty("$bit_server"); - // remoteUrl += "?"; - String key = System.getProperty("$bit_key"); - String secret = System.getProperty("$bit_secret"); - long currentTime = System.currentTimeMillis(); - // 计算签名 - String sign = secret + key + type + currentTime + secret; - sign = getMD5(sign.toUpperCase()); - String params = ""; - params += "type=" + type; - params += "&sign=" + sign; - params += "&key=" + key; - params += "&time=" + currentTime; - params += "&data=" + URLEncoder.encode(toJson(data), "UTF-8"); - - URL url = new URL(remoteUrl); - PrintWriter out = null; - BufferedReader in = null; - String result = ""; - try { - URL realUrl = new URL(remoteUrl); - // 打开和URL之间的连接 - URLConnection conn = realUrl.openConnection(); - // 设置通用的请求属性 - conn.setRequestProperty("accept", "*/*"); -// conn.setRequestProperty("connection", "Keep-Alive"); - conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - conn.setUseCaches(false); - // 发送POST请求必须设置如下两行 - conn.setDoOutput(true); - conn.setDoInput(true); - conn.setConnectTimeout(5000); - conn.setReadTimeout(5000); - // 获取URLConnection对象对应的输出流 - out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8")); - - // 发送请求参数 - out.print(params); - // flush输出流的缓冲 - out.flush(); - // 定义BufferedReader输入流来读取URL的响应 - in = new BufferedReader( - new InputStreamReader(conn.getInputStream(), "UTF-8")); - String line; - while ((line = in.readLine()) != null) { - result += line; - } - if (!"ok".equals(result)) { - System.err.println("bit apm upload fail :" + result); - } - } catch (Exception e) { - throw new RuntimeException("上传失败", e); -// logger.error("发送 POST 请求出现异常!",e); - } - //使用finally块来关闭输出流、输入流 - finally { - try { - if (out != null) { - out.close(); - } - if (in != null) { - in.close(); - } - } catch (IOException ex) { - ex.printStackTrace(); - } - } - - } catch (IOException e) { - e.printStackTrace(); - } - } - }; - threadService.execute(runn); - } - - protected void sendStatisticByHttp(final Statistics stat, final String type) { - // 通过后台线程发送至监控中心 - stat.keyId = System.getProperty("$bit_key"); - execHttp(type, stat); - } - - public static String getAnnotationValue(String key, String annotationDesc) { - String regex = String.format("value=\\{\".*\"\\}"); - Pattern r = Pattern.compile(regex); - Matcher matcher = r.matcher(annotationDesc); - if (matcher.find()) { - return matcher.group().substring(key.length() + 3, matcher.group().length() - 2); - } - return null; - } - - private static String toJson(Object obj) { - Map item = new HashMap(); - item.put("TYPE", false); - item.put(JsonWriter.SKIP_NULL_FIELDS, true); - String json = JsonWriter.objectToJson(obj, item); - return json; - } - - public static String getMD5(String content) { - try { - // 生成一个MD5加密计算摘要 - MessageDigest md = MessageDigest.getInstance("MD5"); - // 计算md5函数 - md.update(content.getBytes()); - return new BigInteger(1, md.digest()).toString(16); - } catch (Exception e) { - throw new RuntimeException(e); - } - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/AgentLoader.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/AgentLoader.java deleted file mode 100644 index 5a0060e9..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/AgentLoader.java +++ /dev/null @@ -1,113 +0,0 @@ -package cn.lastwhisper.monitor.agent; - -import javassist.*; - -import java.io.IOException; - -/** - * agent 装载器 主要作用 1:构建代理监听环境 2:为目标类载入代理监听 - * @author tommy 276386551@qq.com - */ -public class AgentLoader { - private final String className; - private final ClassLoader loader; - private final CtClass ctclass; - - public AgentLoader(String className, - ClassLoader loader, - CtClass ctclass) { - this.className = className; - this.loader = loader; - this.ctclass = ctclass; - } - - /* - * 插入 监听 method - */ - public void updateMethod(CtMethod method, MethodSrcBuild srcBuild) throws CannotCompileException, NotFoundException { - CtMethod ctmethod = method; - String methodName = method.getName(); - // 重构被代理的方法名称 - - // 基于原方法复制生成代理方法 - CtMethod agentMethod = CtNewMethod.copy(ctmethod, methodName, ctclass, null); - agentMethod.setName(methodName + "$agent"); - ctclass.addMethod(agentMethod); - - // 原方法重置为代理执行 - ctmethod.setBody(srcBuild.buildSrc(ctmethod)); - } - - - /** - * 生成新的class 字节码 , - */ - public byte[] toBytecode() throws IOException, CannotCompileException { - return ctclass.toBytecode(); - } - - - public static class MethodSrcBuild { - private String beginSrc; - private String endSrc; - private String errorSrc; - - - public MethodSrcBuild setBeginSrc(String beginSrc) { - this.beginSrc = beginSrc; - return this; - } - - public MethodSrcBuild setEndSrc(String endSrc) { - this.endSrc = endSrc; - return this; - } - - public MethodSrcBuild setErrorSrc(String errorSrc) { - this.errorSrc = errorSrc; - return this; - } - - public String buildSrc(CtMethod method) { - String result; - try { - String template = method.getReturnType().getName().equals("void") ? voidSource : source; - String bSrc = beginSrc == null ? "" : beginSrc; - String eSrc = errorSrc == null ? "" : errorSrc; - String enSrc = endSrc == null ? "" : endSrc; - String src = String.format(template, bSrc, method.getName(), eSrc, enSrc); - return src; - } catch (NotFoundException e) { - throw new RuntimeException(e); - } - } - - final static String source = "{\n" - + "%s" - + " Object result=null;\n" - + " try {\n" - + " result=($w)%s$agent($$);\n" - + " } catch (Throwable e) {\n" - + "%s" - + " throw e;\n" - + " }finally{\n" - + "%s" - + " }\n" - + " return ($r) result;\n" - + "}\n"; - - final static String voidSource = "{\n" - + "%s" - + " try {\n" - + " %s$agent($$);\n" - + " } catch (Throwable e) {\n" - + "%s" - + " throw e;\n" - + " }finally{\n" - + "%s" - + " }\n" - + "}\n"; - } - - -} \ No newline at end of file diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/AgentMain.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/AgentMain.java deleted file mode 100644 index 93a11f24..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/AgentMain.java +++ /dev/null @@ -1,107 +0,0 @@ -package cn.lastwhisper.monitor.agent; - -import cn.lastwhisper.monitor.agent.common.Assert; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.LoaderClassPath; -import java.lang.instrument.ClassFileTransformer; -import java.lang.instrument.IllegalClassFormatException; -import java.lang.instrument.Instrumentation; -import java.security.ProtectionDomain; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -/** - * Created by tommy on 17/7/14. - */ -public class AgentMain implements ClassFileTransformer { - protected static AgentMain agentMain; - private static Collect[] collects; // 采集器集合 - private Map classPoolMap = new ConcurrentHashMap(); - - // 上传地址 - // 参数: - // pro.key= - // 访问远程服务 获取属性配置 - public static void agentmain(String args, Instrumentation inst) { - - } - - private static final ArrayList keys; - - static { - String paramKesy[] = {"server", "key", "secret"}; - keys = new ArrayList(); - keys.addAll(Arrays.asList(paramKesy)); - } - - // agentArgs中有参数 - // 在应用启动前调用 - public static void premain(String agentArgs, Instrumentation inst) { - if (agentArgs != null) { - String[] paramGroup = agentArgs.split(","); - for (String param : paramGroup) { - String[] keyValue = param.split("="); - if (keys.contains(keyValue[0])) { - System.setProperty("$bit_" + keyValue[0], keyValue[1]); - } - } - } - // 验主验置 - if (System.getProperty("$bit_server") == null) { - System.setProperty("$bit_server", "http://api.ibitedu.com/receive"); - } - Assert.checkNull(System.getProperty("$bit_key"),"param key is not null"); - Assert.checkNull(System.getProperty("$bit_secret"),"param key is not null"); - - - collects = new Collect[]{ - /*SpringServiceCollects.INSTANCE, - JdbcCommonCollects.INSTANCE, - SpringControllerCollects.INSTANCE*/ - }; - agentMain = new AgentMain(); - inst.addTransformer(agentMain); - } - - public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { - if (className == null || loader == null - || loader.getClass().getName().equals("sun.reflect.DelegatingClassLoader") - || loader.getClass().getName().equals("org.apache.catalina.loader.StandardClassLoader") - || loader.getClass().getName().equals("javax.management.remote.rmi.NoCallStackClassLoader") - || loader.getClass().getName().equals("com.alibaba.fastjson.util.ASMClassLoader") - || className.indexOf("$Proxy") != -1 - || className.startsWith("java") - ) { - return null; - } - - if (!classPoolMap.containsKey(loader)) { - ClassPool classPool = new ClassPool(); - classPool.insertClassPath(new LoaderClassPath(loader)); - classPoolMap.put(loader, classPool); - } - ClassPool cp = classPoolMap.get(loader); - try { - className = className.replaceAll("/", "."); - CtClass cclass = cp.get(className); - for (Collect c : collects) { - if (c.isTarget(className, loader, cclass)) { // 仅限定只能转换一次. - byte[] bytes = c.transform(loader, className, classfileBuffer, cclass); - //File f = new File("/Users/tommy/git/bit-monitoring-agent/target/" + cclass.getSimpleName() + ".class"); - //Files.write(f.toPath(), bytes); - System.out.println(String.format("%s bit APM agent insert success", className)); - return bytes; - } - } - } catch (Throwable e) { - new Exception(String.format("%s bit APM agent insert fail", className), e).printStackTrace(); - } - return new byte[0]; - } - - public static void main(String[] args) { - int i=10;System.out.println(i++); - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/Collect.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/Collect.java deleted file mode 100644 index 0c7514af..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/Collect.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.lastwhisper.monitor.agent; - -import javassist.CtClass; - -/** - * 采集接口 - * Created by tommy on 17/7/14. - */ -public interface Collect { - /** - * 判断是否为采集目录 - * - * @param className - * @param loader - * @param ctclass - * @return - */ - public boolean isTarget(String className, ClassLoader loader, - CtClass ctclass); - - /** - * 对目标类进行转 - * @param loader - * @param className - * @param classfileBuffer - * @param ctclass - * @return - * @throws Exception - */ - public byte[] transform(ClassLoader loader, String className, - byte[] classfileBuffer, CtClass ctclass) throws Exception; -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/NotProguard.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/NotProguard.java deleted file mode 100644 index 6ce572b7..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/NotProguard.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.monitor.agent; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Created by tommy on 17/7/24. - */ -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD}) -public @interface NotProguard { -} - - diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/UserServiceImpl.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/UserServiceImpl.java deleted file mode 100644 index ec947d94..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/UserServiceImpl.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.lastwhisper.monitor.agent; - -import org.springframework.stereotype.Service; - -@Service -public class UserServiceImpl { - - public void addName(String name) { - - } - - public String getName() { - return "hanmemei"; - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/collects/ErrorLog.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/collects/ErrorLog.java deleted file mode 100644 index 6a9096e2..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/collects/ErrorLog.java +++ /dev/null @@ -1,74 +0,0 @@ -package cn.lastwhisper.monitor.agent.collects; - - -import cn.lastwhisper.monitor.agent.NotProguard; - -/** - * Created by tommy on 17/7/21. - */ -@NotProguard -public class ErrorLog { - private String logType; - private String stack; - private String errorMsg; - private String errorType; - private String ip; - private String keyId; - private Long createTime; - - public String getErrorMsg() { - return errorMsg; - } - - public void setErrorMsg(String errorMsg) { - this.errorMsg = errorMsg; - } - - public String getErrorType() { - return errorType; - } - - public void setErrorType(String errorType) { - this.errorType = errorType; - } - - public String getIp() { - return ip; - } - - public void setIp(String ip) { - this.ip = ip; - } - - public String getLogType() { - return logType; - } - - public void setLogType(String logType) { - this.logType = logType; - } - - public String getStack() { - return stack; - } - - public void setStack(String stack) { - this.stack = stack; - } - - public String getKeyId() { - return keyId; - } - - public void setKeyId(String keyId) { - this.keyId = keyId; - } - - public Long getCreateTime() { - return createTime; - } - - public void setCreateTime(Long createTime) { - this.createTime = createTime; - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/collects/JdbcCommonCollects.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/collects/JdbcCommonCollects.java deleted file mode 100644 index 31e12f05..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/collects/JdbcCommonCollects.java +++ /dev/null @@ -1,196 +0,0 @@ -package cn.lastwhisper.monitor.agent.collects; - -import cn.lastwhisper.monitor.agent.AbstractCollects; -import cn.lastwhisper.monitor.agent.AgentLoader; -import cn.lastwhisper.monitor.agent.Collect; -import cn.lastwhisper.monitor.agent.NotProguard; -import javassist.CtClass; -import javassist.CtMethod; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.sql.Connection; -import java.sql.PreparedStatement; - -/** - * jdbc 数据采集 - * Created by tommy on 17/7/16. - */ -@NotProguard -public class JdbcCommonCollects extends AbstractCollects implements Collect { - @NotProguard - public static final JdbcCommonCollects INSTANCE = new JdbcCommonCollects(); - - private final static String[] connection_agent_methods = new String[]{"prepareStatement"}; - private final static String[] prepared_statement_methods = new String[]{"execute", "executeUpdate", "executeQuery"}; - private static final String beginSrc; - private static final String endSrc; - private static final String errorSrc; - static { - StringBuilder sbuilder = new StringBuilder(); - // connect - beginSrc = "cn.lastwhisper.monitor.agent.collects.JdbcCommonCollects inst=cn.lastwhisper.monitor.agent.collects.JdbcCommonCollects.INSTANCE;"; - errorSrc = "inst.error(null,e);"; - endSrc = "result=inst.proxyConnection((java.sql.Connection)result);"; - } - - public boolean isTarget(String className, ClassLoader loader, CtClass ctclass) { - if (className.equals("com.mysql.jdbc.NonRegisteringDriver")) { - return true; - } - return false; - } - @NotProguard - @Override - public Statistics begin(String className, String method) { - JdbcStatistics jdbcStat = new JdbcStatistics(super.begin(className, method)); - jdbcStat.logType = "sql"; - return jdbcStat; - } - - @NotProguard - @Override - public void end(Statistics stat) { - JdbcStatistics jdbcStat= (JdbcStatistics) stat; - if (jdbcStat.jdbcUrl != null) { - jdbcStat.databaseName = getDbName(jdbcStat.jdbcUrl); - } - super.end(stat); - } - - @Override - public void sendStatistics(Statistics stat) { - sendStatisticByHttp(stat, "sqlLog"); - } - - @NotProguard - public Connection proxyConnection(final Connection connection) { - Object c = Proxy.newProxyInstance(JdbcCommonCollects.class.getClassLoader() - , new Class[]{Connection.class}, new ConnectionHandler(connection)); - return (Connection) c; - } - - - public PreparedStatement proxyPreparedStatement(final PreparedStatement statement, JdbcStatistics jdbcStat) { - Object c = Proxy.newProxyInstance(JdbcCommonCollects.class.getClassLoader() - , new Class[]{PreparedStatement.class}, new PreparedStatementHandler(statement, jdbcStat)); - return (PreparedStatement) c; - } - - @Override - public byte[] transform(ClassLoader loader, String className, byte[] classfileBuffer, CtClass ctclass) throws Exception { - AgentLoader byteLoader = new AgentLoader(className, loader, ctclass); - CtMethod connectMethod = ctclass.getMethod("connect", "(Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection;"); -// connectMethod.getMethodInfo().getDescriptor(); - AgentLoader.MethodSrcBuild build = new AgentLoader.MethodSrcBuild(); - build.setBeginSrc(beginSrc); - build.setErrorSrc(errorSrc); - build.setEndSrc(endSrc); - byteLoader.updateMethod(connectMethod, build); - return byteLoader.toBytecode(); - } - - - /** - * connection 代理处理 - */ - public class ConnectionHandler implements InvocationHandler { - private final Connection connection; - - private ConnectionHandler(Connection connection) { - this.connection = connection; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - boolean isTargetMethod = false; - for (String agentm : connection_agent_methods) { - if (agentm.equals(method.getName())) { - isTargetMethod = true; - } - } - Object result = null; - JdbcStatistics jdbcStat = null; - try { - if (isTargetMethod) { // 获取PreparedStatement 开始统计 - jdbcStat = (JdbcStatistics) JdbcCommonCollects.this.begin(null, null); - jdbcStat.jdbcUrl = connection.getMetaData().getURL(); - jdbcStat.sql = (String) args[0]; - } - result = method.invoke(connection, args); - // 代理 PreparedStatement - if (isTargetMethod && result instanceof PreparedStatement) { - PreparedStatement ps = (PreparedStatement) result; - result = proxyPreparedStatement(ps, jdbcStat); - } - } catch (Throwable e) { - JdbcCommonCollects.this.error(jdbcStat, e); - JdbcCommonCollects.this.end(jdbcStat); - throw e; - } - return result; - } - } - - /** - * PreparedStatement 代理处理 - */ - public class PreparedStatementHandler implements InvocationHandler { - private final PreparedStatement statement; - private final JdbcStatistics jdbcStat; - - public PreparedStatementHandler(PreparedStatement statement, JdbcStatistics jdbcStat) { - this.statement = statement; - this.jdbcStat = jdbcStat; - } - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - boolean isTargetMethod = false; - for (String agentm : prepared_statement_methods) { - if (agentm.equals(method.getName())) { - isTargetMethod = true; - } - } - Object result = null; - try { - result = method.invoke(statement, args); - } catch (Throwable e) { - if (isTargetMethod) { - JdbcCommonCollects.this.error(jdbcStat, e); - } - throw e; - } finally { - if (isTargetMethod) { - JdbcCommonCollects.this.end(jdbcStat); - } - } - return result; - } - } - - @NotProguard - public static class JdbcStatistics extends Statistics { - // jdbc url - public String jdbcUrl; - // sql 语句 - public String sql; - // 数据库名称 - public String databaseName; - - - public JdbcStatistics(Statistics stat) { - super(stat); - } - } - - private static String getDbName(String url) { - int index = url.indexOf("?"); //$NON-NLS-1$ - if (index != -1) { - String paramString = url.substring(index + 1, url.length()); - url = url.substring(0, index); - } - String dbName = url.substring(url.lastIndexOf("/") + 1); - return dbName; - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/collects/SpringControllerCollects.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/collects/SpringControllerCollects.java deleted file mode 100644 index f46e841c..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/collects/SpringControllerCollects.java +++ /dev/null @@ -1,126 +0,0 @@ -package cn.lastwhisper.monitor.agent.collects; - -import cn.lastwhisper.monitor.agent.AbstractCollects; -import cn.lastwhisper.monitor.agent.AgentLoader; -import cn.lastwhisper.monitor.agent.Collect; -import cn.lastwhisper.monitor.agent.NotProguard; -import javassist.CtClass; -import javassist.CtMethod; -import javassist.Modifier; - -import java.nio.file.Files; - -/** - * Created by tommy on 17/7/16. - */ -@NotProguard -public class SpringControllerCollects extends AbstractCollects implements Collect { - @NotProguard - public static SpringControllerCollects INSTANCE = new SpringControllerCollects(); - private static final String beginSrc; - private static final String endSrc; - private static final String errorSrc; - - private String rootRequestUrl = ""; - - static { - StringBuilder sbuilder = new StringBuilder(); - sbuilder.append("cn.lastwhisper.monitor.agent.collects.SpringControllerCollects instance= "); - sbuilder.append("cn.lastwhisper.monitor.agent.collects.SpringControllerCollects.INSTANCE;\r\n"); - sbuilder.append("cn.lastwhisper.monitor.agent.collects.SpringControllerCollects.WebStatistics statistic =(cn.lastwhisper.monitor.agent.collects.SpringControllerCollects.WebStatistics)instance.begin(\"%s\",\"%s\");"); - sbuilder.append("statistic.urlAddress=\"%s\";"); - beginSrc = sbuilder.toString(); - sbuilder = new StringBuilder(); - sbuilder.append("instance.end(statistic);"); - endSrc = sbuilder.toString(); - sbuilder = new StringBuilder(); - sbuilder.append("instance.error(statistic,e);"); - errorSrc = sbuilder.toString(); - } - - @Override - public boolean isTarget(String className, ClassLoader loader, CtClass ctclass) { - boolean result = false; - try { - for (Object obj : ctclass.getAnnotations()) { - // 通过正则表达示计算出RequestMapping 地址 - if (obj.toString().startsWith("@org.springframework.web.bind.annotation.RequestMapping")) { - rootRequestUrl = getAnnotationValue("value", obj.toString()); - } else if (obj.toString().startsWith("@org.springframework.stereotype.Controller")) { - result = true; - } - } - } catch (ClassNotFoundException e) { - System.err.println(String.format("bit apm run error targetClassName=%s errorMessage=%s",className,e.getClass().getSimpleName()+":"+e.getMessage())); - } - return result; - } - - @NotProguard - @Override - public Statistics begin(String className, String method) { - WebStatistics webStat = new WebStatistics(super.begin(className, method)); - webStat.controlName = className; - webStat.methodName = method; - webStat.logType="web"; - return webStat; - } - - @Override - public void sendStatistics(Statistics stat) { - sendStatisticByHttp(stat,"webLog"); - } - - @Override - public byte[] transform(ClassLoader loader, String className, byte[] classfileBuffer, CtClass ctclass) throws Exception { - AgentLoader byteLoader = new AgentLoader(className, loader, ctclass); - CtMethod[] methods = ctclass.getDeclaredMethods(); - for (CtMethod m : methods) { - String requestUrl; - // 屏蔽非公共方法 - if (!Modifier.isPublic(m.getModifiers())) { - continue; - } - // 屏蔽静态方法 - if (Modifier.isStatic(m.getModifiers())) { - continue; - } - // 屏蔽本地方法 - if (Modifier.isNative(m.getModifiers())) { - continue; - } - // 必须带上 RequestMapping 注解 - if ((requestUrl = getRequestMappingValue(m)) == null) { - continue; - } - - AgentLoader.MethodSrcBuild build = new AgentLoader.MethodSrcBuild(); - build.setBeginSrc(String.format(beginSrc, className, m.getName(), rootRequestUrl + requestUrl)); - build.setEndSrc(endSrc); - build.setErrorSrc(errorSrc); - byteLoader.updateMethod(m, build); - } - return byteLoader.toBytecode(); - } - - - private String getRequestMappingValue(CtMethod m) throws ClassNotFoundException { - for (Object s : m.getAnnotations()) { - if (s.toString().startsWith("@org.springframework.web.bind.annotation.RequestMapping")) { - String val = getAnnotationValue("value", s.toString()); - return val==null?"/":val; - } - } - return null; - } - - @NotProguard - public static class WebStatistics extends Statistics { - public String urlAddress; //url 地址 - public String controlName; //服务名称 - public String methodName;// 方法名称 - public WebStatistics(Statistics s) { - super(s); - } - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/collects/SpringServiceCollects.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/collects/SpringServiceCollects.java deleted file mode 100644 index d55513b2..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/collects/SpringServiceCollects.java +++ /dev/null @@ -1,109 +0,0 @@ -package cn.lastwhisper.monitor.agent.collects; - -import cn.lastwhisper.monitor.agent.AbstractCollects; -import cn.lastwhisper.monitor.agent.AgentLoader; -import cn.lastwhisper.monitor.agent.Collect; -import cn.lastwhisper.monitor.agent.NotProguard; -import javassist.CtClass; -import javassist.CtMethod; -import javassist.Modifier; - -/** - * spring 注解服务收集 - * Created by tommy on 17/7/14. - */ -@NotProguard -public class SpringServiceCollects extends AbstractCollects implements Collect { - private static final String beginSrc; - private static final String endSrc; - private static final String errorSrc; - @NotProguard - public static SpringServiceCollects INSTANCE = new SpringServiceCollects(); - - static { - StringBuilder sbuilder = new StringBuilder(); - sbuilder.append("cn.lastwhisper.monitor.agent.collects.SpringServiceCollects instance= "); - sbuilder.append("cn.lastwhisper.monitor.agent.collects.SpringServiceCollects.INSTANCE;\r\n");//赋值 - sbuilder.append("cn.lastwhisper.monitor.agent.AbstractCollects.Statistics statistic =instance.begin(\"%s\",\"%s\");"); - beginSrc = sbuilder.toString(); - sbuilder = new StringBuilder(); - sbuilder.append("instance.end(statistic);"); - endSrc = sbuilder.toString(); - sbuilder = new StringBuilder(); - sbuilder.append("instance.error(statistic,e);"); - errorSrc = sbuilder.toString(); - } - - @NotProguard - public static class ServiceStatistics extends Statistics { - public String serviceName; //服务名称 - public String methodName;// 方法名称 - - public ServiceStatistics(Statistics s) { - super(s); - } - } - - @Override - public boolean isTarget(String className, ClassLoader loader, CtClass ctclass) { - try { - for (Object obj : ctclass.getAnnotations()) { - if (obj.toString().startsWith("@org.springframework.stereotype.Service")) { - return true; - } - } - } catch (ClassNotFoundException e) { - // 缺少依赖jar,但是不影响 - System.err.println(String.format("bit apm run error targetClassName=%s errorMessage=%s", className, e.getClass().getSimpleName() + ":" + e.getMessage())); - } - return false; - } - - @NotProguard - @Override - public Statistics begin(String className, String method) { - ServiceStatistics serviceStatistics = new ServiceStatistics(super.begin(className, method)); - serviceStatistics.serviceName = className; - serviceStatistics.methodName = method; - serviceStatistics.logType = "service"; - return serviceStatistics; - } - - @Override - public void sendStatistics(Statistics stat) { - sendStatisticByHttp(stat, "serviceLog"); - } - - @Override - public byte[] transform(ClassLoader loader, String className, byte[] classfileBuffer, CtClass ctclass) throws - Exception { - AgentLoader byteLoader = new AgentLoader(className, loader, ctclass); - - CtMethod[] methods = ctclass.getDeclaredMethods(); - for (CtMethod m : methods) { - // 屏蔽非公共方法 - if (!Modifier.isPublic(m.getModifiers())) { - continue; - } - // 屏蔽静态方法 - if (Modifier.isStatic(m.getModifiers())) { - continue; - } - // 屏蔽本地方法 - if (Modifier.isNative(m.getModifiers())) { - continue; - } - - AgentLoader.MethodSrcBuild build = new AgentLoader.MethodSrcBuild(); - build.setBeginSrc(String.format(beginSrc, className, m.getName())); - build.setEndSrc(endSrc); - build.setErrorSrc(errorSrc); - byteLoader.updateMethod(m, build); - } - return byteLoader.toBytecode(); - } - - public static void main(String[] args) { - System.out.println(Math.asin(10 >> 4 / 3)); - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/common/Assert.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/common/Assert.java deleted file mode 100644 index b63fb00a..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/common/Assert.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.lastwhisper.monitor.agent.common; - -/** - * Created by tommy on 17/7/19. - */ -public class Assert { - public static void checkNull(Object obj) { - if (obj == null) { - throw new AssertionError(); - } - } - - public static void checkNull(Object obj, String msg) { - if (obj == null) { - throw new AssertionError(msg); - } - } - -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/common/NetUtils.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/common/NetUtils.java deleted file mode 100644 index 6d5c8051..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/common/NetUtils.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright 1999-2011 Alibaba Group. - * - * Licensed 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.lastwhisper.monitor.agent.common; - - -import java.io.IOException; -import java.net.*; -import java.util.Enumeration; -import java.util.Random; -import java.util.logging.Logger; -import java.util.regex.Pattern; - -/** - * IP and Port Helper for RPC, - * - * @author shawn.qianx - */ - -public class NetUtils { - - private static final Logger logger = Logger.getLogger(NetUtils.class.getName()); - - public static final String LOCALHOST = "127.0.0.1"; - - public static final String ANYHOST = "0.0.0.0"; - - private static final int RND_PORT_START = 30000; - - private static final int RND_PORT_RANGE = 10000; - - private static final Random RANDOM = new Random(System.currentTimeMillis()); - - public static int getRandomPort() { - return RND_PORT_START + RANDOM.nextInt(RND_PORT_RANGE); - } - - public static int getAvailablePort() { - ServerSocket ss = null; - try { - ss = new ServerSocket(); - ss.bind(null); - return ss.getLocalPort(); - } catch (IOException e) { - return getRandomPort(); - } finally { - if (ss != null) { - try { - ss.close(); - } catch (IOException e) { - } - } - } - } - - public static int getAvailablePort(int port) { - if (port <= 0) { - return getAvailablePort(); - } - for(int i = port; i < MAX_PORT; i ++) { - ServerSocket ss = null; - try { - ss = new ServerSocket(i); - return i; - } catch (IOException e) { - // continue - } finally { - if (ss != null) { - try { - ss.close(); - } catch (IOException e) { - } - } - } - } - return port; - } - - private static final int MIN_PORT = 0; - - private static final int MAX_PORT = 65535; - - public static boolean isInvalidPort(int port){ - return port > MIN_PORT || port <= MAX_PORT; - } - - private static final Pattern ADDRESS_PATTERN = Pattern.compile("^\\d{1,3}(\\.\\d{1,3}){3}\\:\\d{1,5}$"); - - public static boolean isValidAddress(String address){ - return ADDRESS_PATTERN.matcher(address).matches(); - } - - private static final Pattern LOCAL_IP_PATTERN = Pattern.compile("127(\\.\\d{1,3}){3}$"); - - public static boolean isLocalHost(String host) { - return host != null - && (LOCAL_IP_PATTERN.matcher(host).matches() - || host.equalsIgnoreCase("localhost")); - } - - public static boolean isAnyHost(String host) { - return "0.0.0.0".equals(host); - } - - public static boolean isInvalidLocalHost(String host) { - return host == null - || host.length() == 0 - || host.equalsIgnoreCase("localhost") - || host.equals("0.0.0.0") - || (LOCAL_IP_PATTERN.matcher(host).matches()); - } - - public static boolean isValidLocalHost(String host) { - return ! isInvalidLocalHost(host); - } - - public static InetSocketAddress getLocalSocketAddress(String host, int port) { - return isInvalidLocalHost(host) ? - new InetSocketAddress(port) : new InetSocketAddress(host, port); - } - - private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); - - private static boolean isValidAddress(InetAddress address) { - if (address == null || address.isLoopbackAddress()) { - return false; - } - String name = address.getHostAddress(); - return (name != null - && ! ANYHOST.equals(name) - && ! LOCALHOST.equals(name) - && IP_PATTERN.matcher(name).matches()); - } - - public static String getLocalHost(){ - InetAddress address = getLocalAddress(); - return address == null ? LOCALHOST : address.getHostAddress(); - } - - /* public static String filterLocalHost(String host) { - if (host == null || host.length() == 0) { - return host; - } - if (host.contains("://")) { - URL u = URL.valueOf(host); - if (NetUtils.isInvalidLocalHost(u.getHost())) { - return u.setHost(NetUtils.getLocalHost()).toFullString(); - } - } else if (host.contains(":")) { - int i = host.lastIndexOf(':'); - if (NetUtils.isInvalidLocalHost(host.substring(0, i))) { - return NetUtils.getLocalHost() + host.substring(i); - } - } else { - if (NetUtils.isInvalidLocalHost(host)) { - return NetUtils.getLocalHost(); - } - } - return host; - }*/ - - private static volatile InetAddress LOCAL_ADDRESS = null; - - /** - * 遍历本地网卡,返回第一个合理的IP。 - * - * @return 本地网卡IP - */ - public static InetAddress getLocalAddress() { - if (LOCAL_ADDRESS != null) - return LOCAL_ADDRESS; - InetAddress localAddress = getLocalAddress0(); - LOCAL_ADDRESS = localAddress; - return localAddress; - } - - public static String getLogHost() { - InetAddress address = LOCAL_ADDRESS; - return address == null ? LOCALHOST : address.getHostAddress(); - } - - private static InetAddress getLocalAddress0() { - InetAddress localAddress = null; - try { - localAddress = InetAddress.getLocalHost(); - if (isValidAddress(localAddress)) { - return localAddress; - } - } catch (Throwable e) { - logger.warning("Failed to retriving ip address, " + e.getMessage()); - } - try { - Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); - if (interfaces != null) { - while (interfaces.hasMoreElements()) { - try { - NetworkInterface network = interfaces.nextElement(); - Enumeration addresses = network.getInetAddresses(); - if (addresses != null) { - while (addresses.hasMoreElements()) { - try { - InetAddress address = addresses.nextElement(); - if (isValidAddress(address)) { - return address; - } - } catch (Throwable e) { - logger.warning("Failed to retriving ip address, " + e.getMessage()); - } - } - } - } catch (Throwable e) { - logger.warning("Failed to retriving ip address, " + e.getMessage()); - } - } - } - } catch (Throwable e) { - logger.warning("Failed to retriving ip address, " + e.getMessage()); - } - logger.severe("Could not get local host ip address, will use 127.0.0.1 instead."); - return localAddress; - } - -// private static final Map hostNameCache = new LRUCache(1000); - - /* public static String getHostName(String address) { - try { - int i = address.indexOf(':'); - if (i > -1) { - address = address.substring(0, i); - } - String hostname = hostNameCache.get(address); - if (hostname != null && hostname.length() > 0) { - return hostname; - } - InetAddress inetAddress = InetAddress.getByName(address); - if (inetAddress != null) { - hostname = inetAddress.getHostName(); - hostNameCache.put(address, hostname); - return hostname; - } - } catch (Throwable e) { - // ignore - } - return address; - }*/ - - /** - * @param hostName - * @return ip address or hostName if UnknownHostException - */ - public static String getIpByHost(String hostName) { - try{ - return InetAddress.getByName(hostName).getHostAddress(); - }catch (UnknownHostException e) { - return hostName; - } - } - - public static String toAddressString(InetSocketAddress address) { - return address.getAddress().getHostAddress() + ":" + address.getPort(); - } - - public static InetSocketAddress toAddress(String address) { - int i = address.indexOf(':'); - String host; - int port; - if (i > -1) { - host = address.substring(0, i); - port = Integer.parseInt(address.substring(i + 1)); - } else { - host = address; - port = 0; - } - return new InetSocketAddress(host, port); - } - - public static String toURL(String protocol, String host, int port, String path) { - StringBuilder sb = new StringBuilder(); - sb.append(protocol).append("://"); - sb.append(host).append(':').append(port); - if( path.charAt(0) != '/' ) - sb.append('/'); - sb.append(path); - return sb.toString(); - } - - public static String getLocalMac() { - // TODO Auto-generated method stub - // 获取网卡,获取地址 - byte[] mac = new byte[0]; - try { - InetAddress ia = getLocalAddress(); - mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress(); - } catch (SocketException e) { - logger.severe("get local mac address fail:"+e.getMessage()); - } - StringBuffer sb = new StringBuffer(""); - for (int i = 0; i < mac.length; i++) { - if (i != 0) { - sb.append("-"); - } - // 字节转换为整数 - int temp = mac[i] & 0xff; - String str = Integer.toHexString(temp); - if (str.length() == 1) { - sb.append("0" + str); - } else { - sb.append(str); - } - } - return sb.toString(); - } -} \ No newline at end of file diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/FastPushbackBufferedReader.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/FastPushbackBufferedReader.java deleted file mode 100644 index c63cb1c5..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/FastPushbackBufferedReader.java +++ /dev/null @@ -1,123 +0,0 @@ -package cn.lastwhisper.monitor.agent.json; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.Reader; - -/** - * This class adds significant performance increase over using the JDK - * PushbackReader. This is due to this class not using synchronization - * as it is not needed. - */ -public class FastPushbackBufferedReader extends BufferedReader implements FastPushbackReader -{ - private final int[] buf = new int[256]; - private int idx = 0; - private int unread = Integer.MAX_VALUE; - protected int line = 1; - protected int col = 0; - - FastPushbackBufferedReader(Reader reader) - { - super(reader); - } - - public String getLastSnippet() - { - StringBuilder s = new StringBuilder(); - for (int i=idx; i < buf.length; i++) - { - if (appendChar(s, i)) - { - break; - } - } - for (int i=0; i < idx; i++) - { - if (appendChar(s, i)) - { - break; - } - } - return s.toString(); - } - - private boolean appendChar(StringBuilder s, int i) - { - try - { - final int snip = buf[i]; - if (snip == 0) - { - return true; - } - s.appendCodePoint(snip); - } - catch (Exception e) - { - return true; - } - return false; - } - - public int read() throws IOException - { - int ch; - if (unread == 0x7fffffff) - { - ch = super.read(); - } - else - { - ch = unread; - unread = 0x7fffffff; - } - - if ((buf[idx++] = ch) == 0x0a) - { - line++; - col = 0; - } - else - { - col++; - } - - if (idx >= buf.length) - { - idx = 0; - } - return ch; - } - - public void unread(int c) throws IOException - { - if ((unread = c) == 0x0a) - { - line--; - } - else - { - col--; - } - - if (idx < 1) - { - idx = buf.length - 1; - } - else - { - idx--; - } - } - - public int getCol() - { - return col; - } - - public int getLine() - { - return line; - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/FastPushbackReader.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/FastPushbackReader.java deleted file mode 100644 index 541b0e1d..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/FastPushbackReader.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.lastwhisper.monitor.agent.json; - -import java.io.Closeable; -import java.io.IOException; - -public interface FastPushbackReader extends Closeable { - - int getCol(); - - int getLine(); - - void unread(int c) throws IOException; - - int read() throws IOException; - - String getLastSnippet(); -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/JsonIoException.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/JsonIoException.java deleted file mode 100644 index 854011da..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/JsonIoException.java +++ /dev/null @@ -1,82 +0,0 @@ -package cn.lastwhisper.monitor.agent.json; - -/** - * Custom RuntimeException subclass that is used as the main exception thrown by - * json-io. - * - * @author John DeRegnaucourt (jdereg@gmail.com) - *
- * Copyright (c) Cedar Software LLC - *

- * Licensed 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. - */ -public class JsonIoException extends RuntimeException -{ - /** - * Constructs a new runtime exception with {@code null} as its - * detail message. The cause is not initialized, and may subsequently be - * initialized by a call to {@link #initCause}. - */ - public JsonIoException() - { - super(); - } - - /** - * Constructs a new runtime exception with the specified detail message. - * The cause is not initialized, and may subsequently be initialized by a - * call to {@link #initCause}. - * - * @param message the detail message. The detail message is saved for - * later retrieval by the {@link #getMessage()} method. - */ - public JsonIoException(String message) - { - super(message); - } - - /** - * Constructs a new runtime exception with the specified detail message and - * cause.

Note that the detail message associated with - * {@code cause} is not automatically incorporated in - * this runtime exception's detail message. - * - * @param message the detail message (which is saved for later retrieval - * by the {@link #getMessage()} method). - * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method). (A null value is - * permitted, and indicates that the cause is nonexistent or - * unknown.) - */ - public JsonIoException(String message, Throwable cause) - { - super(message, cause); - } - - /** - * Constructs a new runtime exception with the specified cause and a - * detail message of (cause==null ? null : cause.toString()) - * (which typically contains the class and detail message of - * cause). This constructor is useful for runtime exceptions - * that are little more than wrappers for other throwables. - * - * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method). (A null value is - * permitted, and indicates that the cause is nonexistent or - * unknown.) - */ - public JsonIoException(Throwable cause) - { - super(cause); - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/JsonObject.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/JsonObject.java deleted file mode 100644 index eaeddbdc..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/JsonObject.java +++ /dev/null @@ -1,339 +0,0 @@ -package cn.lastwhisper.monitor.agent.json; - -import java.lang.reflect.Array; -import java.util.*; - -/** - * This class holds a JSON object in a LinkedHashMap. - * LinkedHashMap used to keep fields in same order as they are - * when reflecting them in Java. Instances of this class hold a - * Map-of-Map representation of a Java object, read from the JSON - * input stream. - * - * @param field name in Map-of-Map - * @param Value - * - * @author John DeRegnaucourt (jdereg@gmail.com) - *
- * Copyright (c) Cedar Software LLC - *

- * Licensed 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.* - */ -public class JsonObject extends LinkedHashMap -{ - static Set primitives = new HashSet(); - static Set primitiveWrappers = new HashSet(); - - Object target; - boolean isMap = false; - String type; - long id = -1; - int line; - int col; - - static - { - primitives.add("boolean"); - primitives.add("byte"); - primitives.add("char"); - primitives.add("double"); - primitives.add("float"); - primitives.add("int"); - primitives.add("long"); - primitives.add("short"); - - primitiveWrappers.add("java.lang.Boolean"); - primitiveWrappers.add("java.lang.Byte"); - primitiveWrappers.add("java.lang.Character"); - primitiveWrappers.add("java.lang.Double"); - primitiveWrappers.add("java.lang.Float"); - primitiveWrappers.add("java.lang.Integer"); - primitiveWrappers.add("java.lang.Long"); - primitiveWrappers.add("java.lang.Short"); - } - - - public long getId() - { - return id; - } - - public boolean hasId() - { - return id != -1; - } - - public void setType(String type) - { - this.type = type; - } - - public String getType() - { - return type; - } - - public Object getTarget() - { - return target; - } - - public void setTarget(Object target) - { - this.target = target; - } - - public Class getTargetClass() - { - return target.getClass(); - } - - public boolean isPrimitive() - { - return primitiveWrappers.contains(type); - } - - public static boolean isPrimitiveWrapper(Class c) - { - return primitiveWrappers.contains(c.getName()); - } - - public Object getPrimitiveValue() - { - if ("boolean".equals(type) || "double".equals(type) || "long".equals(type)) - { - return get("value"); - } - else if ("byte".equals(type)) - { - Number b = (Number) get("value"); - return b.byteValue(); - } - else if ("char".equals(type)) - { - String c = (String) get("value"); - return c.charAt(0); - } - else if ("float".equals(type)) - { - Number f = (Number) get("value"); - return f.floatValue(); - } - else if ("int".equals(type)) - { - Number integer = (Number) get("value"); - return integer.intValue(); - } - else if ("short".equals(type)) - { - Number s = (Number) get("value"); - return s.shortValue(); - } - else - { - throw new JsonIoException("Invalid primitive type, line " + line + ", col " + col); - } - } - - /** - * @return boolean true if this object references another object, false otherwise. - */ - public boolean isReference() - { - return containsKey("@ref"); - } - - public Long getReferenceId() - { - return (Long) get("@ref"); - } - - // Map APIs - public boolean isMap() - { - return isMap || target instanceof Map; - } - - // Collection APIs - public boolean isCollection() - { - if (target instanceof Collection) - { - return true; - } - if (containsKey("@items") && !containsKey("@keys")) - { - return type != null && !type.contains("["); - } - return false; - } - - // Array APIs - public boolean isArray() - { - if (target == null) - { - if (type != null) - { - return type.contains("["); - } - return containsKey("@items") && !containsKey("@keys"); - } - return target.getClass().isArray(); - } - - // Return the array that this JSON object wraps. This is used when there is a Collection class (like ArrayList) - // represented in the JSON. This also occurs if a specified array type is used (not Object[], but Integer[], for - // example). - public Object[] getArray() - { - return (Object[]) get("@items"); - } - - public int getLength() - { - if (isArray()) - { - if (target == null) - { - Object[] items = (Object[]) get("@items"); - return items == null ? 0 : items.length; - } - return Array.getLength(target); - } - if (isCollection() || isMap()) - { - Object[] items = (Object[]) get("@items"); - return items == null ? 0 : items.length; - } - throw new JsonIoException("getLength() called on a non-collection, line " + line + ", col " + col); - } - - public Class getComponentType() - { - return target.getClass().getComponentType(); - } - - void moveBytesToMate() - { - final byte[] bytes = (byte[]) target; - final Object[] items = getArray(); - final int len = items.length; - - for (int i = 0; i < len; i++) - { - bytes[i] = ((Number) items[i]).byteValue(); - } - } - - void moveCharsToMate() - { - Object[] items = getArray(); - if (items == null) - { - target = null; - } - else if (items.length == 0) - { - target = new char[0]; - } - else if (items.length == 1) - { - String s = (String) items[0]; - target = s.toCharArray(); - } - else - { - throw new JsonIoException("char[] should only have one String in the [], found " + items.length + ", line " + line + ", col " + col); - } - } - - public V put(K key, V value) - { - if (key == null) - { - return super.put(null, value); - } - - if (key.equals("@type")) - { - String oldType = type; - type = (String) value; - return (V) oldType; - } - else if (key.equals("@id")) - { - Long oldId = id; - id = (Long) value; - return (V) oldId; - } - else if (("@items".equals(key) && containsKey("@keys")) || ("@keys".equals(key) && containsKey("@items"))) - { - isMap = true; - } - return super.put(key, value); - } - - public void clear() - { - super.clear(); - type = null; - } - - void clearArray() - { - remove("@items"); - } - - /** - * @return int line where this object '{' started in the JSON stream - */ - public int getLine() - { - return line; - } - - /** - * @return int column where this object '{' started in the JSON stream - */ - public int getCol() - { - return col; - } - - public int size() - { - if (containsKey("@items")) - { - Object value = get("@items"); - if (value instanceof Object[]) - { - return ((Object[])value).length; - } - else if (value == null) - { - return 0; - } - else - { - throw new JsonIoException("JsonObject with @items, but no array [] associated to it, line " + line + ", col " + col); - } - } - else if (containsKey("@ref")) - { - return 0; - } - - return super.size(); - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/JsonParser.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/JsonParser.java deleted file mode 100644 index 0f1ab01f..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/JsonParser.java +++ /dev/null @@ -1,537 +0,0 @@ -package cn.lastwhisper.monitor.agent.json; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Parse the JSON input stream supplied by the FastPushbackReader to the constructor. - * The entire JSON input stream will be read until it is emptied: an EOF (-1) is read. - * - * While reading the content, Java Maps (JsonObjects) are used to hold the contents of - * JSON objects { }. Lists are used to hold the contents of JSON arrays. Each object - * that has an @id field will be copied into the supplied 'objectsMap' constructor - * argument. This allows the user of this class to locate any referenced object - * directly. - * - * When this parser completes, the @ref (references to objects identified with @id) - * are stored as a JsonObject with an @ref as the key and the ID value of the object. - * No substitution has yet occurred (substituting the @ref pointers with a Java - * reference to the actual Map (Map containing the @id)). - * - * @author John DeRegnaucourt (jdereg@gmail.com) - *
- * Copyright (c) Cedar Software LLC - *

- * Licensed 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. - */ -class JsonParser -{ - public static final String EMPTY_OBJECT = "~!o~"; // compared with == - private static final String EMPTY_ARRAY = "~!a~"; // compared with == - private static final int STATE_READ_START_OBJECT = 0; - private static final int STATE_READ_FIELD = 1; - private static final int STATE_READ_VALUE = 2; - private static final int STATE_READ_POST_VALUE = 3; - private static final Map stringCache = new HashMap(); - - private final FastPushbackReader input; - private final Map objsRead; - private final StringBuilder strBuf = new StringBuilder(256); - private final StringBuilder hexBuf = new StringBuilder(); - private final StringBuilder numBuf = new StringBuilder(); - private final boolean useMaps; - private final Map typeNameMap; - - static - { - // Save heap memory by re-using common strings (String's immutable) - stringCache.put("", ""); - stringCache.put("true", "true"); - stringCache.put("True", "True"); - stringCache.put("TRUE", "TRUE"); - stringCache.put("false", "false"); - stringCache.put("False", "False"); - stringCache.put("FALSE", "FALSE"); - stringCache.put("null", "null"); - stringCache.put("yes", "yes"); - stringCache.put("Yes", "Yes"); - stringCache.put("YES", "YES"); - stringCache.put("no", "no"); - stringCache.put("No", "No"); - stringCache.put("NO", "NO"); - stringCache.put("on", "on"); - stringCache.put("On", "On"); - stringCache.put("ON", "ON"); - stringCache.put("off", "off"); - stringCache.put("Off", "Off"); - stringCache.put("OFF", "OFF"); - stringCache.put("@id", "@id"); - stringCache.put("@ref", "@ref"); - stringCache.put("@items", "@items"); - stringCache.put("@type", "@type"); - stringCache.put("@keys", "@keys"); - stringCache.put("0", "0"); - stringCache.put("1", "1"); - stringCache.put("2", "2"); - stringCache.put("3", "3"); - stringCache.put("4", "4"); - stringCache.put("5", "5"); - stringCache.put("6", "6"); - stringCache.put("7", "7"); - stringCache.put("8", "8"); - stringCache.put("9", "9"); - } - - JsonParser(FastPushbackReader reader, Map objectsMap, Map args) - { - input = reader; - useMaps = Boolean.TRUE.equals(args.get(JsonReader.USE_MAPS)); - objsRead = objectsMap; - typeNameMap = (Map) args.get(JsonReader.TYPE_NAME_MAP_REVERSE); - } - - private Object readJsonObject() throws IOException - { - boolean done = false; - String field = null; - JsonObject object = new JsonObject(); - int state = STATE_READ_START_OBJECT; - final FastPushbackReader in = input; - - while (!done) - { - int c; - switch (state) - { - case STATE_READ_START_OBJECT: - c = skipWhitespaceRead(); - if (c == '{') - { - object.line = in.getLine(); - object.col = in.getCol(); - c = skipWhitespaceRead(); - if (c == '}') - { // empty object - return EMPTY_OBJECT; - } - in.unread(c); - state = STATE_READ_FIELD; - } - else - { - // The line below is not technically required, however, without it, the tests run - // twice as slow. It is apparently affecting a word, or paragraph boundary where - // the generated code sits, making it much faster. - objsRead.size(); - error("Input is invalid JSON; object does not start with '{', c=" + c); - } - break; - - case STATE_READ_FIELD: - c = skipWhitespaceRead(); - if (c == '"') - { - field = readString(); - c = skipWhitespaceRead(); - if (c != ':') - { - error("Expected ':' between string field and value"); - } - - if (field.startsWith("@")) - { // Expand short-hand meta keys - if (field.equals("@t")) - { - field = stringCache.get("@type"); - } - else if (field.equals("@i")) - { - field = stringCache.get("@id"); - } - else if (field.equals("@r")) - { - field = stringCache.get("@ref"); - } - else if (field.equals("@k")) - { - field = stringCache.get("@keys"); - } - else if (field.equals("@e")) - { - field = stringCache.get("@items"); - } - } - state = STATE_READ_VALUE; - } - else - { - error("Expected quote"); - } - break; - - case STATE_READ_VALUE: - if (field == null) - { // field is null when you have an untyped Object[], so we place - // the JsonArray on the @items field. - field = "@items"; - } - - Object value = readValue(object); - if ("@type".equals(field) && typeNameMap != null) - { - final String substitute = typeNameMap.get(value); - if (substitute != null) - { - value = substitute; - } - } - object.put(field, value); - - // If object is referenced (has @id), then put it in the _objsRead table. - if ("@id".equals(field)) - { - objsRead.put((Long) value, object); - } - state = STATE_READ_POST_VALUE; - break; - - case STATE_READ_POST_VALUE: - c = skipWhitespaceRead(); - if (c == -1) - { - error("EOF reached before closing '}'"); - } - if (c == '}') - { - done = true; - } - else if (c == ',') - { - state = STATE_READ_FIELD; - } - else - { - error("Object not ended with '}'"); - } - break; - } - } - - if (useMaps && object.isPrimitive()) - { - return object.getPrimitiveValue(); - } - - return object; - } - - Object readValue(JsonObject object) throws IOException - { - int c = skipWhitespaceRead(); - if (c == '"') - { - return readString(); - } - else if (c >= '0' && c <= '9' || c == '-') - { - return readNumber(c); - } - switch(c) - { - case '{': - input.unread('{'); - return readJsonObject(); - case '[': - return readArray(object); - case ']': // empty array - input.unread(']'); - return EMPTY_ARRAY; - case 'f': - case 'F': - readToken("false"); - return Boolean.FALSE; - case 'n': - case 'N': - readToken("null"); - return null; - case 't': - case 'T': - readToken("true"); - return Boolean.TRUE; - case -1: - error("EOF reached prematurely"); - } - - return error("Unknown JSON value type"); - } - - /** - * Read a JSON array - */ - private Object readArray(JsonObject object) throws IOException - { - final List array = new ArrayList(); - - while (true) - { - final Object o = readValue(object); - if (o != EMPTY_ARRAY) - { - array.add(o); - } - final int c = skipWhitespaceRead(); - - if (c == ']') - { - break; - } - else if (c != ',') - { - error("Expected ',' or ']' inside array"); - } - } - - return array.toArray(); - } - - /** - * Return the specified token from the reader. If it is not found, - * throw an IOException indicating that. Converting to c to - * (char) c is acceptable because the 'tokens' allowed in a - * JSON input stream (true, false, null) are all ASCII. - */ - private void readToken(String token) throws IOException - { - final int len = token.length(); - - for (int i = 1; i < len; i++) - { - int c = input.read(); - if (c == -1) - { - error("EOF reached while reading token: " + token); - } - c = Character.toLowerCase((char) c); - int loTokenChar = token.charAt(i); - - if (loTokenChar != c) - { - error("Expected token: " + token); - } - } - } - - /** - * Read a JSON number - * - * @param c int a character representing the first digit of the number that - * was already read. - * @return a Number (a Long or a Double) depending on whether the number is - * a decimal number or integer. This choice allows all smaller types (Float, int, short, byte) - * to be represented as well. - * @throws IOException for stream errors or parsing errors. - */ - private Number readNumber(int c) throws IOException - { - final FastPushbackReader in = input; - final StringBuilder number = numBuf; - number.setLength(0); - number.appendCodePoint(c); - boolean isFloat = false; - - while (true) - { - c = in.read(); - if ((c >= '0' && c <= '9') || c == '-' || c == '+') - { - number.appendCodePoint(c); - } - else if (c == '.' || c == 'e' || c == 'E') - { - number.appendCodePoint(c); - isFloat = true; - } - else if (c == -1) - { - break; - } - else - { - in.unread(c); - break; - } - } - - try - { - if (isFloat) - { // Floating point number needed - return Double.parseDouble(number.toString()); - } - else - { - return Long.parseLong(number.toString()); - } - } - catch (Exception e) - { - return (Number) error("Invalid number: " + number, e); - } - } - - private static final int STRING_START = 0; - private static final int STRING_SLASH = 1; - private static final int HEX_DIGITS = 2; - - /** - * Read a JSON string - * This method assumes the initial quote has already been read. - * - * @return String read from JSON input stream. - * @throws IOException for stream errors or parsing errors. - */ - private String readString() throws IOException - { - final StringBuilder str = strBuf; - final StringBuilder hex = hexBuf; - str.setLength(0); - int state = STRING_START; - final FastPushbackReader in = input; - - while (true) - { - final int c = in.read(); - if (c == -1) - { - error("EOF reached while reading JSON string"); - } - - if (state == STRING_START) - { - if (c == '"') - { - break; - } - else if (c == '\\') - { - state = STRING_SLASH; - } - else - { - str.appendCodePoint(c); - } - } - else if (state == STRING_SLASH) - { - switch(c) - { - case '\\': - str.appendCodePoint('\\'); - break; - case '/': - str.appendCodePoint('/'); - break; - case '"': - str.appendCodePoint('"'); - break; - case '\'': - str.appendCodePoint('\''); - break; - case 'b': - str.appendCodePoint('\b'); - break; - case 'f': - str.appendCodePoint('\f'); - break; - case 'n': - str.appendCodePoint('\n'); - break; - case 'r': - str.appendCodePoint('\r'); - break; - case 't': - str.appendCodePoint('\t'); - break; - case 'u': - hex.setLength(0); - state = HEX_DIGITS; - break; - default: - error("Invalid character escape sequence specified: " + c); - } - - if (c != 'u') - { - state = STRING_START; - } - } - else - { - if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) - { - hex.appendCodePoint((char) c); - if (hex.length() == 4) - { - int value = Integer.parseInt(hex.toString(), 16); - str.appendCodePoint(value); - state = STRING_START; - } - } - else - { - error("Expected hexadecimal digits"); - } - } - } - - final String s = str.toString(); - final String translate = stringCache.get(s); - return translate == null ? s : translate; - } - - /** - * Read until non-whitespace character and then return it. - * This saves extra read/pushback. - * - * @return int representing the next non-whitespace character in the stream. - * @throws IOException for stream errors or parsing errors. - */ - private int skipWhitespaceRead() throws IOException - { - FastPushbackReader in = input; - int c; - do - { - c = in.read(); - } while (c == ' ' || c == '\n' || c == '\r' || c == '\t'); - return c; - } - - Object error(String msg) - { - throw new JsonIoException(getMessage(msg)); - } - - Object error(String msg, Exception e) - { - throw new JsonIoException(getMessage(msg), e); - } - - String getMessage(String msg) - { - return msg + "\nline: " + input.getLine()+ ", col: " + input.getCol()+ "\n" + input.getLastSnippet(); - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/JsonReader.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/JsonReader.java deleted file mode 100644 index 8f6484d2..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/JsonReader.java +++ /dev/null @@ -1,827 +0,0 @@ -package cn.lastwhisper.monitor.agent.json; - -import java.io.*; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Timestamp; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -/** - * Read an object graph in JSON format and make it available in Java objects, or - * in a "Map of Maps." (untyped representation). This code handles cyclic references - * and can deserialize any Object graph without requiring a class to be 'Serializeable' - * or have any specific methods on it. It will handle classes with non public constructors. - *

- * Usages: - *
  • - * Call the static method: {@code JsonReader.jsonToJava(String json)}. This will - * return a typed Java object graph.
  • - *
  • - * Call the static method: {@code JsonReader.jsonToMaps(String json)}. This will - * return an untyped object representation of the JSON String as a Map of Maps, where - * the fields are the Map keys, and the field values are the associated Map's values. You can - * call the JsonWriter.objectToJson() method with the returned Map, and it will serialize - * the Graph into the equivalent JSON stream from which it was read. - *
  • - * Instantiate the JsonReader with an InputStream: {@code JsonReader(InputStream in)} and then call - * {@code readObject()}. Cast the return value of readObject() to the Java class that was the root of - * the graph. - *
  • - *
  • - * Instantiate the JsonReader with an InputStream: {@code JsonReader(InputStream in, true)} and then call - * {@code readObject()}. The return value will be a Map of Maps. - *

- * - * @author John DeRegnaucourt (jdereg@gmail.com) - *
- * Copyright (c) Cedar Software LLC - *

- * Licensed 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. - */ -public class JsonReader implements Closeable -{ - /** If set, this maps class ==> CustomReader */ - public static final String CUSTOM_READER_MAP = "CUSTOM_READERS"; - /** If set, this indicates that no custom reader should be used for the specified class ==> CustomReader */ - public static final String NOT_CUSTOM_READER_MAP = "NOT_CUSTOM_READERS"; - /** If set, the read-in JSON will be turned into a Map of Maps (JsonObject) representation */ - public static final String USE_MAPS = "USE_MAPS"; - /** What to do when an object is found and 'type' cannot be determined. */ - public static final String UNKNOWN_OBJECT = "UNKNOWN_OBJECT"; - /** Will fail JSON parsing if 'type' class defined but is not on classpath. */ - public static final String FAIL_ON_UNKNOWN_TYPE = "FAIL_ON_UNKNOWN_TYPE"; - /** Pointer to 'this' (automatically placed in the Map) */ - public static final String JSON_READER = "JSON_READER"; - /** Pointer to the current ObjectResolver (automatically placed in the Map) */ - public static final String OBJECT_RESOLVER = "OBJECT_RESOLVER"; - /** If set, this map will be used when writing @type values - allows short-hand abbreviations type names */ - public static final String TYPE_NAME_MAP = "TYPE_NAME_MAP"; - /** If set, this object will be called when a field is present in the JSON but missing from the corresponding class */ - public static final String MISSING_FIELD_HANDLER = "MISSING_FIELD_HANDLER"; - /** If set, use the specified ClassLoader */ - public static final String CLASSLOADER = "CLASSLOADER"; - /** This map is the reverse of the TYPE_NAME_MAP (value ==> key) */ - static final String TYPE_NAME_MAP_REVERSE = "TYPE_NAME_MAP_REVERSE"; - - private static Map BASE_READERS; - protected final Map readers = new HashMap(BASE_READERS); - protected MissingFieldHandler missingFieldHandler; - protected final Set notCustom = new HashSet(); - private static final Map factory = new ConcurrentHashMap(); - private final Map objsRead = new HashMap(); - private final FastPushbackReader input; - /** _args is using ThreadLocal so that static inner classes can have access to them */ - private final Map args = new HashMap(); - - static - { - Factory colFactory = new CollectionFactory(); - assignInstantiator(Collection.class, colFactory); - assignInstantiator(List.class, colFactory); - assignInstantiator(Set.class, colFactory); - assignInstantiator(SortedSet.class, colFactory); - - Factory mapFactory = new MapFactory(); - assignInstantiator(Map.class, mapFactory); - assignInstantiator(SortedMap.class, mapFactory); - - Map temp = new HashMap(); - temp.put(String.class, new Readers.StringReader()); - temp.put(Date.class, new Readers.DateReader()); - temp.put(AtomicBoolean.class, new Readers.AtomicBooleanReader()); - temp.put(AtomicInteger.class, new Readers.AtomicIntegerReader()); - temp.put(AtomicLong.class, new Readers.AtomicLongReader()); - temp.put(BigInteger.class, new Readers.BigIntegerReader()); - temp.put(BigDecimal.class, new Readers.BigDecimalReader()); - temp.put(java.sql.Date.class, new Readers.SqlDateReader()); - temp.put(Timestamp.class, new Readers.TimestampReader()); - temp.put(Calendar.class, new Readers.CalendarReader()); - temp.put(TimeZone.class, new Readers.TimeZoneReader()); - temp.put(Locale.class, new Readers.LocaleReader()); - temp.put(Class.class, new Readers.ClassReader()); - temp.put(StringBuilder.class, new Readers.StringBuilderReader()); - temp.put(StringBuffer.class, new Readers.StringBufferReader()); - BASE_READERS = temp; - } - - /** - * Common ancestor for ClassFactory and ClassFactoryEx. - */ - public interface Factory - { - } - - /** - * Subclass this interface and create a class that will return a new instance of the - * passed in Class (c). Your subclass will be called when json-io encounters an - * the new to instantiate an instance of (c). - * - * Make json-io aware that it needs to call your class by calling the public - * JsonReader.assignInstantiator() API. - */ - public interface ClassFactory extends Factory - { - Object newInstance(Class c); - } - - /** - * Subclass this interface and create a class that will return a new instance of the - * passed in Class (c). Your subclass will be called when json-io encounters an - * the new to instantiate an instance of (c). The 'args' Map passed in will - * contain a 'jsonObj' key that holds the JsonObject (Map) representing the - * object being converted. If you need values from the fields of this object - * in order to instantiate your class, you can grab them from the JsonObject (Map). - * - * Make json-io aware that it needs to call your class by calling the public - * JsonReader.assignInstantiator() API. - */ - public interface ClassFactoryEx extends Factory - { - Object newInstance(Class c, Map args); - } - - /** - * Used to react to fields missing when reading an object. This method will be called after all deserialization has - * occured to allow all ref to be resolved. - *

- * Used in conjunction with {@link JsonReader#MISSING_FIELD_HANDLER}. - */ - public interface MissingFieldHandler - { - - /** - * Notify that a field is missing.
- * Warning : not every type can be deserialized upon missing fields. Arrays and Object type that do not have - * serialized @type definition will be ignored. - * - * @param object the object that contains the missing field - * @param fieldName name of the field to be replaced - * @param value current value of the field - */ - void fieldMissing(Object object, String fieldName, Object value); - - } - - /** - * Common ancestor for JsonClassReader and JsonClassReaderEx. - */ - public interface JsonClassReaderBase { } - - /** - * Implement this interface to add a custom JSON reader. - */ - public interface JsonClassReader extends JsonClassReaderBase - { - /** - * @param jOb Object being read. Could be a fundamental JSON type (String, long, boolean, double, null, or JsonObject) - * @param stack Deque of objects that have been read (Map of Maps view). - * @return Object you wish to convert the jOb value into. - */ - Object read(Object jOb, Deque> stack); - } - - /** - * Implement this interface to add a custom JSON reader. - */ - public interface JsonClassReaderEx extends JsonClassReaderBase - { - /** - * @param jOb Object being read. Could be a fundamental JSON type (String, long, boolean, double, null, or JsonObject) - * @param stack Deque of objects that have been read (Map of Maps view). - * @param args Map of argument settings that were passed to JsonReader when instantiated. - * @return Java Object you wish to convert the the passed in jOb into. - */ - Object read(Object jOb, Deque> stack, Map args); - - /** - * Allow custom readers to have access to the JsonReader - */ - class Support - { - /** - * Call this method to get an instance of the JsonReader (if needed) inside your custom reader. - * @param args Map that was passed to your read(jOb, stack, args) method. - * @return JsonReader instance - */ - public static JsonReader getReader(Map args) - { - return (JsonReader) args.get(JSON_READER); - } - } - } - - /** - * Use to create new instances of collection interfaces (needed for empty collections) - */ - public static class CollectionFactory implements ClassFactory - { - public Object newInstance(Class c) - { - if (List.class.isAssignableFrom(c)) - { - return new ArrayList(); - } - else if (SortedSet.class.isAssignableFrom(c)) - { - return new TreeSet(); - } - else if (Set.class.isAssignableFrom(c)) - { - return new LinkedHashSet(); - } - else if (Collection.class.isAssignableFrom(c)) - { - return new ArrayList(); - } - throw new JsonIoException("CollectionFactory handed Class for which it was not expecting: " + c.getName()); - } - } - - /** - * Use to create new instances of Map interfaces (needed for empty Maps). Used - * internally to handle Map, SortedMap when they are within parameterized types. - */ - public static class MapFactory implements ClassFactory - { - /** - * @param c Map interface that was requested for instantiation. - * @return a concrete Map type. - */ - public Object newInstance(Class c) - { - if (SortedMap.class.isAssignableFrom(c)) - { - return new TreeMap(); - } - else if (Map.class.isAssignableFrom(c)) - { - return new LinkedHashMap(); - } - throw new JsonIoException("MapFactory handed Class for which it was not expecting: " + c.getName()); - } - } - - /** - * For difficult to instantiate classes, you can add your own ClassFactory - * or ClassFactoryEx which will be called when the passed in class 'c' is - * encountered. Your ClassFactory will be called with newInstance(c) and - * your factory is expected to return a new instance of 'c'. - * - * This API is an 'escape hatch' to allow ANY object to be instantiated by JsonReader - * and is useful when you encounter a class that JsonReader cannot instantiate using its - * internal exhausting attempts (trying all constructors, varying arguments to them, etc.) - * @param n Class name to assign an ClassFactory to - * @param f ClassFactory that will create 'c' instances - */ - public static void assignInstantiator(String n, Factory f) - { - factory.put(n, f); - } - - /** - * Assign instantiated by Class. Falls back to JsonReader.assignInstantiator(String, Factory) - * @param c Class to assign an ClassFactory to - * @param f ClassFactory that will create 'c' instances - */ - public static void assignInstantiator(Class c, Factory f) - { - assignInstantiator(c.getName(), f); - } - - /** - * Call this method to add a custom JSON reader to json-io. It will - * associate the Class 'c' to the reader you pass in. The readers are - * found with isAssignableFrom(). If this is too broad, causing too - * many classes to be associated to the custom reader, you can indicate - * that json-io should not use a custom reader for a particular class, - * by calling the addNotCustomReader() method. - * @param c Class to assign a custom JSON reader to - * @param reader The JsonClassReader which will read the custom JSON format of 'c' - */ - public void addReader(Class c, JsonClassReaderBase reader) - { - readers.put(c, reader); - } - - /** - * Call this method to add a custom JSON reader to json-io. It will - * associate the Class 'c' to the reader you pass in. The readers are - * found with isAssignableFrom(). If this is too broad, causing too - * many classes to be associated to the custom reader, you can indicate - * that json-io should not use a custom reader for a particular class, - * by calling the addNotCustomReader() method. This method will add - * the customer reader such that it will be there permanently, for the - * life of the JVM (static). - * @param c Class to assign a custom JSON reader to - * @param reader The JsonClassReader which will read the custom JSON format of 'c' - */ - public static void addReaderPermanent(Class c, JsonClassReaderBase reader) - { - BASE_READERS.put(c, reader); - } - - /** - * Force json-io to use it's internal generic approach to writing the - * passed in class, even if a Custom JSON reader is specified for its - * parent class. - * @param c Class to which to force no custom JSON reading to occur. - * Normally, this is not needed, however, if a reader is assigned to a - * parent class of 'c', then calling this method on 'c' will prevent - * any custom reader from processing class 'c' - */ - public void addNotCustomReader(Class c) - { - notCustom.add(c); - } - - MissingFieldHandler getMissingFieldHandler() - { - return missingFieldHandler; - } - - public void setMissingFieldHandler(MissingFieldHandler handler) - { - missingFieldHandler = handler; - } - - /** - * @return The arguments used to configure the JsonReader. These are thread local. - */ - public Map getArgs() - { - return args; - } - - /** - * Convert the passed in JSON string into a Java object graph. - * - * @param json String JSON input - * @return Java object graph matching JSON input - */ - public static Object jsonToJava(String json) - { - return jsonToJava(json, null); - } - - /** - * Convert the passed in JSON string into a Java object graph. - * - * @param json String JSON input - * @param optionalArgs Map of optional parameters to control parsing. See readme file for details. - * @return Java object graph matching JSON input - */ - public static Object jsonToJava(String json, Map optionalArgs) - { - if (optionalArgs == null) - { - optionalArgs = new HashMap(); - optionalArgs.put(USE_MAPS, false); - } - if (!optionalArgs.containsKey(USE_MAPS)) - { - optionalArgs.put(USE_MAPS, false); - } - JsonReader jr = new JsonReader(json, optionalArgs); - Object obj = jr.readObject(); - jr.close(); - return obj; - } - - /** - * Convert the passed in JSON string into a Java object graph. - * - * @param inputStream InputStream containing JSON input - * @param optionalArgs Map of optional parameters to control parsing. See readme file for details. - * @return Java object graph matching JSON input - */ - public static Object jsonToJava(InputStream inputStream, Map optionalArgs) - { - if (optionalArgs == null) - { - optionalArgs = new HashMap(); - optionalArgs.put(USE_MAPS, false); - } - if (!optionalArgs.containsKey(USE_MAPS)) - { - optionalArgs.put(USE_MAPS, false); - } - JsonReader jr = new JsonReader(inputStream, optionalArgs); - Object obj = jr.readObject(); - jr.close(); - return obj; - } - - /** - * Map args = ["USE_MAPS": true] - * Use JsonReader.jsonToJava(String json, args) - * Note that the return type will match the JSON type (array, object, string, long, boolean, or null). - * No longer recommended: Use jsonToJava with USE_MAPS:true - * @param json String of JSON content - * @return Map representing JSON content. Each object is represented by a Map. - */ - public static Map jsonToMaps(String json) - { - return jsonToMaps(json, null); - } - - /** - * Map args = ["USE_MAPS": true] - * Use JsonReader.jsonToJava(String json, args) - * Note that the return type will match the JSON type (array, object, string, long, boolean, or null). - * No longer recommended: Use jsonToJava with USE_MAPS:true - * @param json String of JSON content - * @param optionalArgs Map of optional arguments to control customization. See readme file for - * details on these options. - * @return Map where each Map representa an object in the JSON input. - */ - public static Map jsonToMaps(String json, Map optionalArgs) - { - try - { - if (optionalArgs == null) - { - optionalArgs = new HashMap(); - } - optionalArgs.put(USE_MAPS, true); - ByteArrayInputStream ba = new ByteArrayInputStream(json.getBytes("UTF-8")); - JsonReader jr = new JsonReader(ba, optionalArgs); - Object ret = jr.readObject(); - jr.close(); - - return adjustOutputMap(ret); - } - catch (UnsupportedEncodingException e) - { - throw new JsonIoException("Could not convert JSON to Maps because your JVM does not support UTF-8", e); - } - } - - /** - * Map args = ["USE_MAPS": true] - * Use JsonReader.jsonToJava(inputStream, args) - * Note that the return type will match the JSON type (array, object, string, long, boolean, or null). - * No longer recommended: Use jsonToJava with USE_MAPS:true - * @param inputStream containing JSON content - * @param optionalArgs Map of optional arguments to control customization. See readme file for - * details on these options. - * @return Map containing the content from the JSON input. Each Map represents an object from the input. - */ - public static Map jsonToMaps(InputStream inputStream, Map optionalArgs) - { - if (optionalArgs == null) - { - optionalArgs = new HashMap(); - } - optionalArgs.put(USE_MAPS, true); - JsonReader jr = new JsonReader(inputStream, optionalArgs); - Object ret = jr.readObject(); - jr.close(); - - return adjustOutputMap(ret); - } - - private static Map adjustOutputMap(Object ret) - { - if (ret instanceof Map) - { - return (Map) ret; - } - - if (ret != null && ret.getClass().isArray()) - { - JsonObject retMap = new JsonObject(); - retMap.put("@items", ret); - return retMap; - } - JsonObject retMap = new JsonObject(); - retMap.put("@items", new Object[]{ret}); - return retMap; - } - - public JsonReader() - { - input = null; - getArgs().put(USE_MAPS, false); - getArgs().put(CLASSLOADER, JsonReader.class.getClassLoader()); - } - - public JsonReader(InputStream inp) - { - this(inp, false); - } - - /** - * Use this constructor if you already have a JsonObject graph and want to parse it into - * Java objects by calling jsonReader.jsonObjectsToJava(rootJsonObject) after constructing - * the JsonReader. - * @param optionalArgs Map of optional arguments for the JsonReader. - */ - public JsonReader(Map optionalArgs) - { - this(new ByteArrayInputStream(new byte[]{}), optionalArgs); - } - - // This method is needed to get around the fact that 'this()' has to be the first method of a constructor. - static Map makeArgMap(Map args, boolean useMaps) - { - args.put(USE_MAPS, useMaps); - return args; - } - - public JsonReader(InputStream inp, boolean useMaps) - { - this(inp, makeArgMap(new HashMap(), useMaps)); - } - - public JsonReader(InputStream inp, Map optionalArgs) - { - initializeFromArgs(optionalArgs); - - try - { - input = new FastPushbackBufferedReader(new InputStreamReader(inp, "UTF-8")); - } - catch (UnsupportedEncodingException e) - { - throw new JsonIoException("Your JVM does not support UTF-8. Get a better JVM.", e); - } - } - - public JsonReader(String inp, Map optionalArgs) - { - initializeFromArgs(optionalArgs); - try - { - byte[] bytes = inp.getBytes("UTF-8"); - input = new FastPushbackBufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes), "UTF-8")); - } - catch (UnsupportedEncodingException e) - { - throw new JsonIoException("Could not convert JSON to Maps because your JVM does not support UTF-8", e); - } - } - - public JsonReader(byte[] inp, Map optionalArgs) - { - initializeFromArgs(optionalArgs); - try - { - input = new FastPushbackBufferedReader(new InputStreamReader(new ByteArrayInputStream(inp), "UTF-8")); - } - catch (UnsupportedEncodingException e) - { - throw new JsonIoException("Could not convert JSON to Maps because your JVM does not support UTF-8", e); - } - } - - private void initializeFromArgs(Map optionalArgs) - { - if (optionalArgs == null) - { - optionalArgs = new HashMap(); - } - Map args = getArgs(); - args.putAll(optionalArgs); - args.put(JSON_READER, this); - if (!args.containsKey(CLASSLOADER)) - { - args.put(CLASSLOADER, JsonReader.class.getClassLoader()); - } - Map typeNames = (Map) args.get(TYPE_NAME_MAP); - - if (typeNames != null) - { // Reverse the Map (this allows the users to only have a Map from type to short-hand name, - // and not keep a 2nd map from short-hand name to type. - Map typeNameMap = new HashMap(); - for (Map.Entry entry : typeNames.entrySet()) - { - typeNameMap.put(entry.getValue(), entry.getKey()); - } - args.put(TYPE_NAME_MAP_REVERSE, typeNameMap); // replace with our reversed Map. - } - - setMissingFieldHandler((MissingFieldHandler) args.get(MISSING_FIELD_HANDLER)); - - Map customReaders = (Map) args.get(CUSTOM_READER_MAP); - if (customReaders != null) - { - for (Map.Entry entry : customReaders.entrySet()) - { - addReader(entry.getKey(), entry.getValue()); - } - } - - Iterable notCustomReaders = (Iterable) args.get(NOT_CUSTOM_READER_MAP); - if (notCustomReaders != null) - { - for (Class c : notCustomReaders) - { - addNotCustomReader(c); - } - } - } - - public Map getObjectsRead() - { - return objsRead; - } - - public Object getRefTarget(JsonObject jObj) - { - if (!jObj.isReference()) - { - return jObj; - } - - Long id = jObj.getReferenceId(); - JsonObject target = objsRead.get(id); - if (target == null) - { - throw new IllegalStateException("The JSON input had an @ref to an object that does not exist."); - } - return getRefTarget(target); - } - - /** - * Read JSON input from the stream that was set up in the constructor, turning it into - * Java Maps (JsonObject's). Then, if requested, the JsonObjects can be converted - * into Java instances. - * - * @return Java Object graph constructed from InputStream supplying - * JSON serialized content. - */ - public Object readObject() - { - JsonParser parser = new JsonParser(input, objsRead, getArgs()); - JsonObject root = new JsonObject(); - Object o; - try - { - o = parser.readValue(root); - if (o == JsonParser.EMPTY_OBJECT) - { - return new JsonObject(); - } - } - catch (JsonIoException e) - { - throw e; - } - catch (Exception e) - { - throw new JsonIoException("error parsing JSON value", e); - } - - Object graph; - if (o instanceof Object[]) - { - root.setType(Object[].class.getName()); - root.setTarget(o); - root.put("@items", o); - graph = convertParsedMapsToJava(root); - } - else - { - graph = o instanceof JsonObject ? convertParsedMapsToJava((JsonObject) o) : o; - } - - // Allow a complete 'Map' return (Javascript style) - if (useMaps()) - { - return o; - } - return graph; - } - - /** - * Convert a root JsonObject that represents parsed JSON, into - * an actual Java object. - * @param root JsonObject instance that was the root object from the - * JSON input that was parsed in an earlier call to JsonReader. - * @return a typed Java instance that was serialized into JSON. - */ - public Object jsonObjectsToJava(JsonObject root) - { - getArgs().put(USE_MAPS, false); - return convertParsedMapsToJava(root); - } - - protected boolean useMaps() - { - return Boolean.TRUE.equals(getArgs().get(USE_MAPS)); - } - - /** - * @return ClassLoader to be used by Custom Writers - */ - ClassLoader getClassLoader() - { - return (ClassLoader) args.get(CLASSLOADER); - } - - /** - * This method converts a root Map, (which contains nested Maps - * and so forth representing a Java Object graph), to a Java - * object instance. The root map came from using the JsonReader - * to parse a JSON graph (using the API that puts the graph - * into Maps, not the typed representation). - * @param root JsonObject instance that was the root object from the - * JSON input that was parsed in an earlier call to JsonReader. - * @return a typed Java instance that was serialized into JSON. - */ - protected Object convertParsedMapsToJava(JsonObject root) - { - try - { - Resolver resolver = useMaps() ? new MapResolver(this) : new ObjectResolver(this, (ClassLoader)args.get(CLASSLOADER)); - resolver.createJavaObjectInstance(Object.class, root); - Object graph = resolver.convertMapsToObjects((JsonObject) root); - resolver.cleanup(); - readers.clear(); - return graph; - } - catch (Exception e) - { - try - { - close(); - } - catch (Exception ignored) - { // Exception handled in close() - } - if (e instanceof JsonIoException) - { - throw (JsonIoException)e; - } - throw new JsonIoException(getErrorMessage(e.getMessage()), e); - } - } - - public static Object newInstance(Class c) - { - if (factory.containsKey(c.getName())) - { - ClassFactory cf = (ClassFactory) factory.get(c.getName()); - return cf.newInstance(c); - } - return MetaUtils.newInstance(c); - } - - public static Object newInstance(Class c, JsonObject jsonObject) - { - if (factory.containsKey(c.getName())) - { - Factory cf = factory.get(c.getName()); - if (cf instanceof ClassFactoryEx) - { - Map args = new HashMap(); - args.put("jsonObj", jsonObject); - return ((ClassFactoryEx)cf).newInstance(c, args); - } - if (cf instanceof ClassFactory) - { - return ((ClassFactory)cf).newInstance(c); - } - throw new JsonIoException("Unknown instantiator (Factory) class. Must subclass ClassFactoryEx or ClassFactory, found: " + cf.getClass().getName()); - } - return MetaUtils.newInstance(c); - } - - public void close() - { - try - { - if (input != null) - { - input.close(); - } - } - catch (Exception e) - { - throw new JsonIoException("Unable to close input", e); - } - } - - private String getErrorMessage(String msg) - { - if (input != null) - { - return msg + "\nLast read: " + input.getLastSnippet() + "\nline: " + input.getLine() + ", col: " + input.getCol(); - } - return msg; - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/JsonWriter.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/JsonWriter.java deleted file mode 100644 index 2c0dfa24..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/JsonWriter.java +++ /dev/null @@ -1,2400 +0,0 @@ -package cn.lastwhisper.monitor.agent.json; - -import java.io.*; -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Timestamp; -import java.util.*; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -/** - * Output a Java object graph in JSON format. This code handles cyclic - * references and can serialize any Object graph without requiring a class - * to be 'Serializeable' or have any specific methods on it. - *

  • - * Call the static method: {@code JsonWriter.objectToJson(employee)}. This will - * convert the passed in 'employee' instance into a JSON String.
  • - *
  • Using streams: - *
         JsonWriter writer = new JsonWriter(stream);
    - *     writer.write(employee);
    - *     writer.close();
    - * This will write the 'employee' object to the passed in OutputStream. - *
- *

That's it. This can be used as a debugging tool. Output an object - * graph using the above code. Use the JsonWriter PRETTY_PRINT option to - * format the the JSON to be human readable. - *
- *

This will output any object graph deeply (or null). Object references are - * properly handled. For example, if you had A->B, B->C, and C->A, then - * A will be serialized with a B object in it, B will be serialized with a C - * object in it, and then C will be serialized with a reference to A (ref), not a - * redefinition of A.

- *
- * - * @author John DeRegnaucourt (jdereg@gmail.com) - *
- * Copyright (c) Cedar Software LLC - *

- * Licensed 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. - */ -public class JsonWriter implements Closeable, Flushable -{ - /** If set, this maps class ==> CustomWriter */ - public static final String CUSTOM_WRITER_MAP = "CUSTOM_WRITERS"; - /** If set, this maps class ==> CustomWriter */ - public static final String NOT_CUSTOM_WRITER_MAP = "NOT_CUSTOM_WRITERS"; - /** Set the date format to use within the JSON output */ - public static final String DATE_FORMAT = "DATE_FORMAT"; - /** Constant for use as DATE_FORMAT value */ - public static final String ISO_DATE_FORMAT = "yyyy-MM-dd"; - /** Constant for use as DATE_FORMAT value */ - public static final String ISO_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss"; - /** Force @type always */ - public static final String TYPE = "TYPE"; - /** Force nicely formatted JSON output */ - public static final String PRETTY_PRINT = "PRETTY_PRINT"; - /** Set value to a Map> which will be used to control which fields on a class are output */ - public static final String FIELD_SPECIFIERS = "FIELD_SPECIFIERS"; - /** Set value to a Map> which will be used to control which fields on a class are not output. Black list has always priority to FIELD_SPECIFIERS */ - public static final String FIELD_NAME_BLACK_LIST = "FIELD_NAME_BLACK_LIST"; - /** same as above only internal for storing Field instances instead of strings. This avoid the initial argument content to be modified. */ - private static final String FIELD_BLACK_LIST = "FIELD_BLACK_LIST"; - /** If set, indicates that private variables of ENUMs are not to be serialized */ - public static final String ENUM_PUBLIC_ONLY = "ENUM_PUBLIC_ONLY"; - /** If set, longs are written in quotes (Javascript safe) */ - public static final String WRITE_LONGS_AS_STRINGS = "WLAS"; - /** If set, this map will be used when writing @type values - allows short-hand abbreviations type names */ - public static final String TYPE_NAME_MAP = "TYPE_NAME_MAP"; - /** If set, then @type -> @t, @keys -> @k, @items -> @i */ - public static final String SHORT_META_KEYS = "SHORT_META_KEYS"; - /** If set, null fields are not written */ - public static final String SKIP_NULL_FIELDS = "SKIP_NULL"; - /** If set, use the specified ClassLoader */ - public static final String CLASSLOADER = "CLASSLOADER"; - - private static Map BASE_WRITERS; - private final Map writers = new HashMap(BASE_WRITERS); // Add customer writers (these make common classes more succinct) - private final Map writerCache = new HashMap(); - private final Set notCustom = new HashSet(); - private static final Object[] byteStrings = new Object[256]; - private static final String NEW_LINE = System.getProperty("line.separator"); - private static final Long ZERO = 0L; - private static final NullClass nullWriter = new NullClass(); - private final Map objVisited = new IdentityHashMap(); - private final Map objsReferenced = new IdentityHashMap(); - private final Writer out; - private Map typeNameMap = null; - private boolean shortMetaKeys = false; - private boolean neverShowType = false; - private boolean alwaysShowType = false; - private boolean isPrettyPrint = false; - private boolean isEnumPublicOnly = false; - private boolean writeLongsAsStrings = false; - private boolean skipNullFields = false; - private long identity = 1; - private int depth = 0; - /** _args is using ThreadLocal so that static inner classes can have access to them */ - final Map args = new HashMap(); - - static - { - for (short i = -128; i <= 127; i++) - { - char[] chars = Integer.toString(i).toCharArray(); - byteStrings[i + 128] = chars; - } - - Map temp = new HashMap(); - temp.put(String.class, new Writers.JsonStringWriter()); - temp.put(Date.class, new Writers.DateWriter()); - temp.put(AtomicBoolean.class, new Writers.AtomicBooleanWriter()); - temp.put(AtomicInteger.class, new Writers.AtomicIntegerWriter()); - temp.put(AtomicLong.class, new Writers.AtomicLongWriter()); - temp.put(BigInteger.class, new Writers.BigIntegerWriter()); - temp.put(BigDecimal.class, new Writers.BigDecimalWriter()); - temp.put(java.sql.Date.class, new Writers.DateWriter()); - temp.put(Timestamp.class, new Writers.TimestampWriter()); - temp.put(Calendar.class, new Writers.CalendarWriter()); - temp.put(TimeZone.class, new Writers.TimeZoneWriter()); - temp.put(Locale.class, new Writers.LocaleWriter()); - temp.put(Class.class, new Writers.ClassWriter()); - temp.put(StringBuilder.class, new Writers.StringBuilderWriter()); - temp.put(StringBuffer.class, new Writers.StringBufferWriter()); - BASE_WRITERS = temp; - } - - /** - * Common ancestor for JsonClassWriter and JsonClassWriterEx. - */ - public interface JsonClassWriterBase - { } - - /** - * Implement this interface to customize the JSON output for a given class. - */ - public interface JsonClassWriter extends JsonClassWriterBase - { - /** - * When write() is called, it is expected that subclasses will write the appropriate JSON - * to the passed in Writer. - * @param o Object to be written in JSON format. - * @param showType boolean indicating whether to show @type. - * @param output Writer destination to where the actual JSON is written. - * @throws IOException if thrown by the writer. Will be caught at a higher level and wrapped in JsonIoException. - */ - void write(Object o, boolean showType, Writer output) throws IOException; - - /** - * @return boolean true if the class being written has a primitive (non-object) form. - */ - boolean hasPrimitiveForm(); - - /** - * This method will be called to write the item in primitive form (if the response to hasPrimitiveForm() - * was true). - * @param o Object to be written - * @param output Writer destination to where the actual JSON is written. - * @throws IOException if thrown by the writer. Will be caught at a higher level and wrapped in JsonIoException. - */ - void writePrimitiveForm(Object o, Writer output) throws IOException; - } - - /** - * Implement this interface to customize the JSON output for a given class. - */ - public interface JsonClassWriterEx extends JsonClassWriterBase - { - String JSON_WRITER = "JSON_WRITER"; - - /** - * When write() is called, it is expected that subclasses will write the appropriate JSON - * to the passed in Writer. - * @param o Object to be written in JSON format. - * @param showType boolean indicating whether to show @type. - * @param output Writer destination to where the actual JSON is written. - * @param args Map of 'settings' arguments initially passed into the JsonWriter. - * @throws IOException if thrown by the writer. Will be caught at a higher level and wrapped in JsonIoException. - */ - void write(Object o, boolean showType, Writer output, Map args) throws IOException; - - /** - * If access to the JsonWriter is needed, JsonClassWriter's can access it by accessing Support.getWriter(args). - * The args are the same arguments passed into the write(o, showType, args) method of JsonClassWriterEx. - */ - class Support - { - /** - * This method will return the JsonWriter instance performing the overall work. - * @param args Map of settings initially passed to JsonWriter. - * @return JsonWriter instance performing the work. - */ - public static JsonWriter getWriter(Map args) - { - return (JsonWriter) args.get(JSON_WRITER); - } - } - } - - /** - * Provide access to subclasses. - * @return Map containing all objects that were referenced within input object graph. - */ - public Map getObjectsReferenced() - { - return objsReferenced; - } - - /** - * Provide access to subclasses. - * @return Map containing all objects that were visited within input object graph - */ - public Map getObjectsVisited() - { - return objVisited; - } - - /** - * Used internally to substitute type names. For example, 'java.util.ArrayList, could have a substitute - * type name of 'alist'. Set substitute type names using the TYPE_NAME_MAP option. - * @param typeName String name of type to substitute. - * @return String substituted name, or null if there is no substitute. - */ - protected String getSubstituteTypeNameIfExists(String typeName) - { - if (typeNameMap == null) - { - return null; - } - return typeNameMap.get(typeName); - } - - /** - * Used internally to substitute type names. For example, 'java.util.ArrayList, could have a substitute - * type name of 'alist'. Set substitute type names using the TYPE_NAME_MAP option. - * @param typeName String name of type to substitute. - * @return String substituted type name. - */ - protected String getSubstituteTypeName(String typeName) - { - if (typeNameMap == null) - { - return typeName; - } - String shortName = typeNameMap.get(typeName); - return shortName == null ? typeName : shortName; - } - - /** - * @see JsonWriter#objectToJson(Object, Map) - * @param item Object (root) to serialized to JSON String. - * @return String of JSON format representing complete object graph rooted by item. - */ - public static String objectToJson(Object item) - { - return objectToJson(item, null); - } - - /** - * Convert a Java Object to a JSON String. - * - * @param item Object to convert to a JSON String. - * @param optionalArgs (optional) Map of extra arguments indicating how dates are formatted, - * what fields are written out (optional). For Date parameters, use the public static - * DATE_TIME key, and then use the ISO_DATE or ISO_DATE_TIME indicators. Or you can specify - * your own custom SimpleDateFormat String, or you can associate a SimpleDateFormat object, - * in which case it will be used. This setting is for both java.util.Date and java.sql.Date. - * If the DATE_FORMAT key is not used, then dates will be formatted as longs. This long can - * be turned back into a date by using 'new Date(longValue)'. - * @return String containing JSON representation of passed in object root. - */ - public static String objectToJson(Object item, Map optionalArgs) - { - try - { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - JsonWriter writer = new JsonWriter(stream, optionalArgs); - writer.write(item); - writer.close(); - return new String(stream.toByteArray(), "UTF-8"); - } - catch (Exception e) - { - throw new JsonIoException("Unable to convert object to JSON", e); - } - } - - /** - * Format the passed in JSON string in a nice, human readable format. - * @param json String input JSON - * @return String containing equivalent JSON, formatted nicely for human readability. - */ - public static String formatJson(String json) - { - return formatJson(json, null, null); - } - - /** - * Format the passed in JSON string in a nice, human readable format. - * @param json String input JSON - * @param readingArgs (optional) Map of extra arguments for parsing json. Can be null. - * @param writingArgs (optional) Map of extra arguments for writing out json. Can be null. - * @return String containing equivalent JSON, formatted nicely for human readability. - */ - public static String formatJson(String json, Map readingArgs, Map writingArgs) - { - Map args = new HashMap(); - if (readingArgs != null) - { - args.putAll(readingArgs); - } - args.put(JsonReader.USE_MAPS, true); - Object obj = JsonReader.jsonToJava(json, args); - args.clear(); - if (writingArgs != null) - { - args.putAll(writingArgs); - } - args.put(PRETTY_PRINT, true); - return objectToJson(obj, args); - } - - /** - * @see JsonWriter#JsonWriter(OutputStream, Map) - * @param out OutputStream to which the JSON will be written. - */ - public JsonWriter(OutputStream out) - { - this(out, null); - } - - /** - * @param out OutputStream to which the JSON output will be written. - * @param optionalArgs (optional) Map of extra arguments indicating how dates are formatted, - * what fields are written out (optional). For Date parameters, use the public static - * DATE_TIME key, and then use the ISO_DATE or ISO_DATE_TIME indicators. Or you can specify - * your own custom SimpleDateFormat String, or you can associate a SimpleDateFormat object, - * in which case it will be used. This setting is for both java.util.Date and java.sql.Date. - * If the DATE_FORMAT key is not used, then dates will be formatted as longs. This long can - * be turned back into a date by using 'new Date(longValue)'. - */ - public JsonWriter(OutputStream out, Map optionalArgs) - { - if (optionalArgs == null) - { - optionalArgs = new HashMap(); - } - args.putAll(optionalArgs); - args.put(JsonClassWriterEx.JSON_WRITER, this); - typeNameMap = (Map) args.get(TYPE_NAME_MAP); - shortMetaKeys = isTrue(args.get(SHORT_META_KEYS)); - alwaysShowType = isTrue(args.get(TYPE)); - neverShowType = Boolean.FALSE.equals(args.get(TYPE)) || "false".equals(args.get(TYPE)); - isPrettyPrint = isTrue(args.get(PRETTY_PRINT)); - isEnumPublicOnly = isTrue(args.get(ENUM_PUBLIC_ONLY)); - writeLongsAsStrings = isTrue(args.get(WRITE_LONGS_AS_STRINGS)); - writeLongsAsStrings = isTrue(args.get(WRITE_LONGS_AS_STRINGS)); - skipNullFields = isTrue(args.get(SKIP_NULL_FIELDS)); - if (!args.containsKey(CLASSLOADER)) - { - args.put(CLASSLOADER, JsonWriter.class.getClassLoader()); - } - - Map customWriters = (Map) args.get(CUSTOM_WRITER_MAP); - if (customWriters != null) - { - for (Entry entry : customWriters.entrySet()) - { - addWriter(entry.getKey(), entry.getValue()); - } - } - - Collection notCustomClasses = (Collection) args.get(NOT_CUSTOM_WRITER_MAP); - if (notCustomClasses != null) - { - for (Class c : notCustomClasses) - { - addNotCustomWriter(c); - } - } - - if (optionalArgs.containsKey(FIELD_SPECIFIERS)) - { // Convert String field names to Java Field instances (makes it easier for user to set this up) - Map> specifiers = (Map>) args.get(FIELD_SPECIFIERS); - Map> copy = new HashMap>(); - for (Entry> entry : specifiers.entrySet()) - { - Class c = entry.getKey(); - List fields = entry.getValue(); - List newList = new ArrayList(fields.size()); - - Map classFields = MetaUtils.getDeepDeclaredFields(c); - - for (String field : fields) - { - Field f = classFields.get(field); - if (f == null) - { - throw new JsonIoException("Unable to locate field: " + field + " on class: " + c.getName() + ". Make sure the fields in the FIELD_SPECIFIERS map existing on the associated class."); - } - newList.add(f); - } - copy.put(c, newList); - } - args.put(FIELD_SPECIFIERS, copy); - } - else - { // Ensure that at least an empty Map is in the FIELD_SPECIFIERS entry - args.put(FIELD_SPECIFIERS, new HashMap()); - } - if (optionalArgs.containsKey(FIELD_NAME_BLACK_LIST)) - { // Convert String field names to Java Field instances (makes it easier for user to set this up) - Map> blackList = (Map>) args.get(FIELD_NAME_BLACK_LIST); - Map> copy = new HashMap>(); - for (Entry> entry : blackList.entrySet()) - { - Class c = entry.getKey(); - List fields = entry.getValue(); - List newList = new ArrayList(fields.size()); - - Map classFields = MetaUtils.getDeepDeclaredFields(c); - - for (String field : fields) - { - Field f = classFields.get(field); - if (f == null) - { - throw new JsonIoException("Unable to locate field: " + field + " on class: " + c.getName() + ". Make sure the fields in the FIELD_NAME_BLACK_LIST map existing on the associated class."); - } - newList.add(f); - } - copy.put(c, newList); - } - args.put(FIELD_BLACK_LIST, copy); - } - else - { // Ensure that at least an empty Map is in the FIELD_SPECIFIERS entry - args.put(FIELD_BLACK_LIST, new HashMap()); - } - - try - { - this.out = new BufferedWriter(new OutputStreamWriter(out, "UTF-8")); - } - catch (UnsupportedEncodingException e) - { - throw new JsonIoException("UTF-8 not supported on your JVM. Unable to convert object to JSON.", e); - } - } - - /** - * @return ClassLoader to be used by Custom Writers - */ - ClassLoader getClassLoader() - { - return (ClassLoader) args.get(CLASSLOADER); - } - - /** - * @param setting Object setting value from JsonWriter args map. - * @return boolean true if the value is (boolean) true, Boolean.TRUE, "true" (any case), or non-zero if a Number. - */ - static boolean isTrue(Object setting) - { - if (setting instanceof Boolean) - { - return Boolean.TRUE.equals(setting); - } - else if (setting instanceof String) - { - return "true".equalsIgnoreCase((String) setting); - } - else if (setting instanceof Number) - { - return ((Number)setting).intValue() != 0; - } - - return false; - } - - /** - * Tab the output left (less indented) - * @throws IOException - */ - public void tabIn() throws IOException - { - tab(out, 1); - } - - /** - * Add newline (\n) to output - * @throws IOException - */ - public void newLine() throws IOException - { - tab(out, 0); - } - - /** - * Tab the output right (more indented) - * @throws IOException - */ - public void tabOut() throws IOException - { - tab(out, -1); - } - - /** - * tab the JSON output by the given number of characters specified by delta. - * @param output Writer being used for JSON outpt. - * @param delta int number of characters to tab. - * @throws IOException - */ - private void tab(Writer output, int delta) throws IOException - { - if (!isPrettyPrint) - { - return; - } - output.write(NEW_LINE); - depth += delta; - for (int i=0; i < depth; i++) - { - output.write(" "); - } - } - - /** - * Write the passed in object (o) to the JSON output stream, if and only if, there is a custom - * writer associated to the Class of object (o). - * @param o Object to be (potentially written) - * @param showType boolean indicating whether or not to show @type. - * @param output Writer where the actual JSON is being written to. - * @return boolean true if written, false is there is no custom writer for the passed in object. - */ - public boolean writeIfMatching(Object o, boolean showType, Writer output) - { - if (neverShowType) - { - showType = false; - } - Class c = o.getClass(); - if (notCustom.contains(c)) - { - return false; - } - - try - { - return writeCustom(c, o, showType, output); - } - catch (IOException e) - { - throw new JsonIoException("Unable to write custom formatted object:", e); - } - } - - /** - * Write the passed in array element to the JSON output, if any only if, there is a customer writer - * for the class of the instance 'o'. - * @param arrayComponentClass Class type of the array - * @param o Object instance to write - * @param showType boolean indicating whether or not @type should be output. - * @param output Writer to write the JSON to (if there is a custom writer for o's Class). - * @return true if the array element was written, false otherwise. - */ - public boolean writeArrayElementIfMatching(Class arrayComponentClass, Object o, boolean showType, Writer output) - { - if (!o.getClass().isAssignableFrom(arrayComponentClass) || notCustom.contains(o.getClass())) - { - return false; - } - - try - { - return writeCustom(arrayComponentClass, o, showType, output); - } - catch (IOException e) - { - throw new JsonIoException("Unable to write custom formatted object as array element:", e); - } - } - - /** - * Perform the actual custom writing for an array element that has a custom writer. - * @param arrayComponentClass Class type of the array - * @param o Object instance to write - * @param showType boolean indicating whether or not @type should be output. - * @param output Writer to write the JSON to (if there is a custom writer for o's Class). - * @return true if the array element was written, false otherwise. - */ - protected boolean writeCustom(Class arrayComponentClass, Object o, boolean showType, Writer output) throws IOException - { - if (neverShowType) - { - showType = false; - } - JsonClassWriterBase closestWriter = getCustomWriter(arrayComponentClass); - - if (closestWriter == null) - { - return false; - } - - if (writeOptionalReference(o)) - { - return true; - } - - boolean referenced = objsReferenced.containsKey(o); - - if (closestWriter instanceof JsonClassWriter) - { - JsonClassWriter writer = (JsonClassWriter) closestWriter; - if (writer.hasPrimitiveForm()) - { - if ((!referenced && !showType) || closestWriter instanceof Writers.JsonStringWriter) - { - if (writer instanceof Writers.DateWriter) - { - ((Writers.DateWriter)writer).writePrimitiveForm(o, output, args); - } - else - { - writer.writePrimitiveForm(o, output); - } - return true; - } - } - } - - output.write('{'); - tabIn(); - if (referenced) - { - writeId(getId(o)); - if (showType) - { - output.write(','); - newLine(); - } - } - - if (showType) - { - writeType(o, output); - } - - if (referenced || showType) - { - output.write(','); - newLine(); - } - - if (closestWriter instanceof JsonClassWriterEx) - { - ((JsonClassWriterEx)closestWriter).write(o, showType || referenced, output, args); - } - else - { - ((JsonClassWriter)closestWriter).write(o, showType || referenced, output); - } - tabOut(); - output.write('}'); - return true; - } - - /** - * Dummy place-holder class exists only because ConcurrentHashMap cannot contain a - * null value. Instead, singleton instance of this class is placed where null values - * are needed. - */ - static final class NullClass implements JsonClassWriterBase { } - - /** - * Fetch the customer writer for the passed in Class. If it is cached (already associated to the - * passed in Class), return the same instance, otherwise, make a call to get the custom writer - * and store that result. - * @param c Class of object for which fetch a custom writer - * @return JsonClassWriter/JsonClassWriterEx for the custom class (if one exists), null otherwise. - */ - private JsonClassWriterBase getCustomWriter(Class c) - { - JsonClassWriterBase writer = writerCache.get(c); - if (writer == null) - { - writer = forceGetCustomWriter(c); - writerCache.put(c, writer); - } - return writer == nullWriter ? null : writer; - } - - /** - * Fetch the customer writer for the passed in Class. This method always fetches the custom writer, doing - * the complicated inheritance distance checking. This method is only called when a cache miss has happened. - * A sentinal 'nullWriter' is returned when no custom writer is found. This prevents future cache misses - * from re-attempting to find custom writers for classes that do not have a custom writer. - * @param c Class of object for which fetch a custom writer - * @return JsonClassWriter/JsonClassWriterEx for the custom class (if one exists), nullWriter otherwise. - */ - private JsonClassWriterBase forceGetCustomWriter(Class c) - { - JsonClassWriterBase closestWriter = nullWriter; - int minDistance = Integer.MAX_VALUE; - - for (Entry entry : writers.entrySet()) - { - Class clz = entry.getKey(); - if (clz == c) - { - return entry.getValue(); - } - int distance = MetaUtils.getDistance(clz, c); - if (distance < minDistance) - { - minDistance = distance; - closestWriter = entry.getValue(); - } - } - return closestWriter; - } - - /** - * Add a custom writer which will manage writing objects of the - * passed in Class in JSON format. The custom writer will be - * called for objects of the passed in class, including subclasses. - * If this is not desired, call addNotCustomWriter(c) which will - * force objects of the passed in Class to be written by the standard - * JSON writer. - * @param c Class to associate a custom JSON writer too - * @param writer JsonClassWriterBase which implements the appropriate - * subclass of JsonClassWriterBase (JsonClassWriter or JsonClassWriterEx). - */ - public void addWriter(Class c, JsonClassWriterBase writer) - { - writers.put(c, writer); - } - - /** - * Add a permanent Customer Writer (Lifetime of JVM) - * @param c Class to associate a custom JSON writer too - * @param writer JsonClassWriterBase which implements the appropriate - * subclass of JsonClassWriterBase (JsonClassWriter or JsonClassWriterEx). - */ - public static void addWriterPermanent(Class c, JsonClassWriterBase writer) - { - BASE_WRITERS.put(c, writer); - } - - /** - * For no custom writing to occur for the passed in Class. - * @param c Class which should NOT have any custom writer associated to it. Use this - * to prevent a custom writer from being used due to inheritance. - */ - public void addNotCustomWriter(Class c) - { - notCustom.add(c); - } - - /** - * Write the passed in Java object in JSON format. - * @param obj Object any Java Object or JsonObject. - */ - public void write(Object obj) - { - traceReferences(obj); - objVisited.clear(); - try - { - writeImpl(obj, true); - } - catch (Exception e) - { - throw new JsonIoException("Error writing object to JSON:", e); - } - flush(); - objVisited.clear(); - objsReferenced.clear(); - } - - /** - * Walk object graph and visit each instance, following each field, each Collection, Map and so on. - * Tracks visited to handle cycles and to determine if an item is referenced elsewhere. If an - * object is never referenced more than once, no @id field needs to be emitted for it. - * @param root Object to be deeply traced. The objVisited and objsReferenced Maps will be written to - * during the trace. - */ - protected void traceReferences(Object root) - { - if (root == null) - { - return; - } - Map> fieldSpecifiers = (Map) args.get(FIELD_SPECIFIERS); - final Deque stack = new ArrayDeque(); - stack.addFirst(root); - final Map visited = objVisited; - final Map referenced = objsReferenced; - - while (!stack.isEmpty()) - { - final Object obj = stack.removeFirst(); - - if (!MetaUtils.isLogicalPrimitive(obj.getClass())) - { - Long id = visited.get(obj); - if (id != null) - { // Only write an object once. - if (id == ZERO) - { // 2nd time this object has been seen, so give it a unique ID and mark it referenced - id = identity++; - visited.put(obj, id); - referenced.put(obj, id); - } - continue; - } - else - { // Initially, mark an object with 0 as the ID, in case it is never referenced, - // we don't waste the memory to store a Long instance that is never used. - visited.put(obj, ZERO); - } - } - - final Class clazz = obj.getClass(); - - if (clazz.isArray()) - { - if (!MetaUtils.isLogicalPrimitive(clazz.getComponentType())) - { // Speed up: do not traceReferences of primitives, they cannot reference anything - final int len = Array.getLength(obj); - - for (int i = 0; i < len; i++) - { - final Object o = Array.get(obj, i); - if (o != null) - { // Slight perf gain (null is legal) - stack.addFirst(o); - } - } - } - } - else if (Map.class.isAssignableFrom(clazz)) - { // Speed up - logically walk maps, as opposed to following their internal structure. - Map map = (Map) obj; - for (final Object item : map.entrySet()) - { - final Entry entry = (Entry) item; - if (entry.getValue() != null) - { - stack.addFirst(entry.getValue()); - } - if (entry.getKey() != null) - { - stack.addFirst(entry.getKey()); - } - } - } - else if (Collection.class.isAssignableFrom(clazz)) - { - for (final Object item : (Collection)obj) - { - if (item != null) - { - stack.addFirst(item); - } - } - } - else - { // Speed up: do not traceReferences of primitives, they cannot reference anything - if (!MetaUtils.isLogicalPrimitive(obj.getClass())) - { - traceFields(stack, obj, fieldSpecifiers); - } - } - } - } - - /** - * Reach-ability trace to visit all objects within the graph to be written. - * This API will handle any object, using either reflection APIs or by - * consulting a specified FIELD_SPECIFIERS map if provided. - * @param stack Deque used to manage descent into graph (rather than using Java stack.) This allows for - * much larger graph processing. - * @param obj Object root of graph - * @param fieldSpecifiers Map of optional field specifiers, which are used to override the field list returned by - * the JDK reflection operations. This allows a subset of the actual fields on an object to be serialized. - */ - protected void traceFields(final Deque stack, final Object obj, final Map> fieldSpecifiers) - { - // If caller has special Field specifier for a given class - // then use it, otherwise use reflection. - Collection fields = getFieldsUsingSpecifier(obj.getClass(), fieldSpecifiers); - Collection fieldsBySpec = fields; - if (fields == null) - { // Trace fields using reflection - fields = MetaUtils.getDeepDeclaredFields(obj.getClass()).values(); - } - for (final Field field : fields) - { - if ((field.getModifiers() & Modifier.TRANSIENT) != 0) - { - if (fieldsBySpec == null || !fieldsBySpec.contains(field)) - { // Skip tracing transient fields EXCEPT when the field is listed explicitly by using the fieldSpecifiers Map. - // In that case, the field must be traced, even though it is transient. - continue; - } - } - try - { - final Object o = field.get(obj); - if (o != null && !MetaUtils.isLogicalPrimitive(o.getClass())) - { // Trace through objects that can reference other objects - stack.addFirst(o); - } - } - catch (Exception ignored) { } - } - } - - private static List getFieldsUsingSpecifier(final Class classBeingWritten, final Map> fieldSpecifiers) - { - final Iterator>> i = fieldSpecifiers.entrySet().iterator(); - int minDistance = Integer.MAX_VALUE; - List fields = null; - - while (i.hasNext()) - { - final Entry> entry = i.next(); - final Class c = entry.getKey(); - - if (c == classBeingWritten) - { - return entry.getValue(); - } - - int distance = MetaUtils.getDistance(c, classBeingWritten); - - if (distance < minDistance) - { - minDistance = distance; - fields = entry.getValue(); - } - } - - return fields; - } - - private boolean writeOptionalReference(Object obj) throws IOException - { - if (obj == null) - { - return false; - } - - if (MetaUtils.isLogicalPrimitive(obj.getClass())) - { - return false; - } - - final Writer output = this.out; - if (objVisited.containsKey(obj)) - { // Only write (define) an object once in the JSON stream, otherwise emit a @ref - String id = getId(obj); - if (id == null) - { // Test for null because of Weak/Soft references being gc'd during serialization. - return false; - } - output.write(shortMetaKeys ? "{\"@r\":" : "{\"@ref\":"); - output.write(id); - output.write('}'); - return true; - } - - // Mark the object as visited by putting it in the Map (this map is re-used / clear()'d after walk()). - objVisited.put(obj, null); - return false; - } - - /** - * Main entry point (mostly used internally, but may be called from a Custom JSON writer). - * This method will write out whatever object type it is given, including JsonObject's. - * It will handle null, detecting if a custom writer should be called, array, array of - * JsonObject, Map, Map of JsonObjects, Collection, Collection of JsonObject, any regular - * object, or a JsonObject representing a regular object. - * @param obj Object to be written - * @param showType if set to true, the @type tag will be output. If false, it will be - * dropped. - * @throws IOException if one occurs on the underlying output stream. - */ - public void writeImpl(Object obj, boolean showType) throws IOException - { - writeImpl(obj, showType, true, true); - } - - /** - * Main entry point (mostly used internally, but may be called from a Custom JSON writer). - * This method will write out whatever object type it is given, including JsonObject's. - * It will handle null, detecting if a custom writer should be called, array, array of - * JsonObject, Map, Map of JsonObjects, Collection, Collection of JsonObject, any regular - * object, or a JsonObject representing a regular object. - * @param obj Object to be written - * @param showType if set to true, the @type tag will be output. If false, it will be - * @param allowRef if set to true, @ref will be used, otherwise 2+ occurrence will be - * output as full object. - * @param allowCustom if set to true, the object being called will allowed to be checked for a matching - * custom writer to be used. This does not affect subobjects, just the top-level 'obj' - * being passed in. - * @throws IOException if one occurs on the underlying output stream. - */ - public void writeImpl(Object obj, boolean showType, boolean allowRef, boolean allowCustom) throws IOException - { - if (neverShowType) - { - showType = false; - } - if (obj == null) - { - out.write("null"); - return; - } - - if (allowCustom && writeIfMatching(obj, showType, out)) - { - return; - } - - if (allowRef && writeOptionalReference(obj)) - { - return; - } - - if (obj.getClass().isArray()) - { - writeArray(obj, showType); - } - else if (obj instanceof Collection) - { - writeCollection((Collection) obj, showType); - } - else if (obj instanceof JsonObject) - { // symmetric support for writing Map of Maps representation back as equivalent JSON format. - JsonObject jObj = (JsonObject) obj; - if (jObj.isArray()) - { - writeJsonObjectArray(jObj, showType); - } - else if (jObj.isCollection()) - { - writeJsonObjectCollection(jObj, showType); - } - else if (jObj.isMap()) - { - if (!writeJsonObjectMapWithStringKeys(jObj, showType)) - { - writeJsonObjectMap(jObj, showType); - } - } - else - { - writeJsonObjectObject(jObj, showType); - } - } - else if (obj instanceof Map) - { - if (!writeMapWithStringKeys((Map) obj, showType)) - { - writeMap((Map) obj, showType); - } - } - else - { - writeObject(obj, showType, false); - } - } - - private void writeId(final String id) throws IOException - { - out.write(shortMetaKeys ? "\"@i\":" : "\"@id\":"); - out.write(id == null ? "0" : id); - } - - private void writeType(Object obj, Writer output) throws IOException - { - if (neverShowType) - { - return; - } - output.write(shortMetaKeys ? "\"@t\":\"" : "\"@type\":\""); - final Class c = obj.getClass(); - String typeName = c.getName(); - String shortName = getSubstituteTypeNameIfExists(typeName); - - if (shortName != null) - { - output.write(shortName); - output.write('"'); - return; - } - - String s = c.getName(); - if (s.equals("java.lang.Boolean")) - { - output.write("boolean"); - } - else if (s.equals("java.lang.Byte")) - { - output.write("byte"); - } - else if (s.equals("java.lang.Character")) - { - output.write("char"); - } - else if (s.equals("java.lang.Class")) - { - output.write("class"); - } - else if (s.equals("java.lang.Double")) - { - output.write("double"); - } - else if (s.equals("java.lang.Float")) - { - output.write("float"); - } - else if (s.equals("java.lang.Integer")) - { - output.write("int"); - } - else if (s.equals("java.lang.Long")) - { - output.write("long"); - } - else if (s.equals("java.lang.Short")) - { - output.write("short"); - } - else if (s.equals("java.lang.String")) - { - output.write("string"); - } - else if (s.equals("java.util.Date")) - { - output.write("date"); - } - else - { - output.write(c.getName()); - } - - output.write('"'); - } - - private void writePrimitive(final Object obj, boolean showType) throws IOException - { - if (neverShowType) - { - showType = false; - } - if (obj instanceof Character) - { - writeJsonUtf8String(String.valueOf(obj), out); - } - else - { - if (obj instanceof Long && writeLongsAsStrings) - { - if (showType) - { - out.write(shortMetaKeys ? "{\"@t\":\"" : "{\"@type\":\""); - out.write(getSubstituteTypeName("long")); - out.write("\",\"value\":\""); - out.write(obj.toString()); - out.write("\"}"); - } - else - { - out.write('"'); - out.write(obj.toString()); - out.write('"'); - } - } - else if (obj instanceof Double && (Double.isNaN((Double) obj) || Double.isInfinite((Double) obj))) - { - out.write("null"); - } - else if (obj instanceof Float && (Float.isNaN((Float) obj) || Float.isInfinite((Float) obj))) - { - out.write("null"); - } - else - { - out.write(obj.toString()); - } - } - } - - private void writeArray(final Object array, boolean showType) throws IOException - { - if (neverShowType) - { - showType = false; - } - Class arrayType = array.getClass(); - int len = Array.getLength(array); - boolean referenced = objsReferenced.containsKey(array); -// boolean typeWritten = showType && !(Object[].class == arrayType); // causes IDE warning in NetBeans 7/4 Java 1.7 - boolean typeWritten = showType && !(arrayType.equals(Object[].class)); - - final Writer output = this.out; // performance opt: place in final local for quicker access - if (typeWritten || referenced) - { - output.write('{'); - tabIn(); - } - - if (referenced) - { - writeId(getId(array)); - output.write(','); - newLine(); - } - - if (typeWritten) - { - writeType(array, output); - output.write(','); - newLine(); - } - - if (len == 0) - { - if (typeWritten || referenced) - { - output.write(shortMetaKeys ? "\"@e\":[]" : "\"@items\":[]"); - tabOut(); - output.write('}'); - } - else - { - output.write("[]"); - } - return; - } - - if (typeWritten || referenced) - { - output.write(shortMetaKeys ? "\"@i\":[" : "\"@items\":["); - } - else - { - output.write('['); - } - tabIn(); - - final int lenMinus1 = len - 1; - - // Intentionally processing each primitive array type in separate - // custom loop for speed. All of them could be handled using - // reflective Array.get() but it is slower. I chose speed over code length. - if (byte[].class == arrayType) - { - writeByteArray((byte[]) array, lenMinus1); - } - else if (char[].class == arrayType) - { - writeJsonUtf8String(new String((char[]) array), output); - } - else if (short[].class == arrayType) - { - writeShortArray((short[]) array, lenMinus1); - } - else if (int[].class == arrayType) - { - writeIntArray((int[]) array, lenMinus1); - } - else if (long[].class == arrayType) - { - writeLongArray((long[]) array, lenMinus1); - } - else if (float[].class == arrayType) - { - writeFloatArray((float[]) array, lenMinus1); - } - else if (double[].class == arrayType) - { - writeDoubleArray((double[]) array, lenMinus1); - } - else if (boolean[].class == arrayType) - { - writeBooleanArray((boolean[]) array, lenMinus1); - } - else - { - final Class componentClass = array.getClass().getComponentType(); - final boolean isPrimitiveArray = MetaUtils.isPrimitive(componentClass); - - for (int i = 0; i < len; i++) - { - final Object value = Array.get(array, i); - - if (value == null) - { - output.write("null"); - } - else if (writeArrayElementIfMatching(componentClass, value, false, output)) { } - else if (isPrimitiveArray || value instanceof Boolean || value instanceof Long || value instanceof Double) - { - writePrimitive(value, value.getClass() != componentClass); - } - else if (neverShowType && MetaUtils.isPrimitive(value.getClass())) - { // When neverShowType specified, do not allow primitives to show up as {"value":6} for example. - writePrimitive(value, false); - } - else - { // Specific Class-type arrays - only force type when - // the instance is derived from array base class. - boolean forceType = !(value.getClass() == componentClass); - writeImpl(value, forceType || alwaysShowType); - } - - if (i != lenMinus1) - { - output.write(','); - newLine(); - } - } - } - - tabOut(); - output.write(']'); - if (typeWritten || referenced) - { - tabOut(); - output.write('}'); - } - } - - private void writeBooleanArray(boolean[] booleans, int lenMinus1) throws IOException - { - final Writer output = this.out; - for (int i = 0; i < lenMinus1; i++) - { - output.write(booleans[i] ? "true," : "false,"); - } - output.write(Boolean.toString(booleans[lenMinus1])); - } - - private void writeDoubleArray(double[] doubles, int lenMinus1) throws IOException - { - final Writer output = this.out; - for (int i = 0; i < lenMinus1; i++) - { - output.write(doubleToString(doubles[i])); - output.write(','); - } - output.write(doubleToString(doubles[lenMinus1])); - } - - private void writeFloatArray(float[] floats, int lenMinus1) throws IOException - { - final Writer output = this.out; - for (int i = 0; i < lenMinus1; i++) - { - output.write(floatToString(floats[i])); - output.write(','); - } - output.write(floatToString(floats[lenMinus1])); - } - - private String doubleToString(double d) - { - return (Double.isNaN(d) || Double.isInfinite(d)) ? "null" : Double.toString(d); - } - - private String floatToString(float d) - { - return (Float.isNaN(d) || Float.isInfinite(d)) ? "null" : Float.toString(d); - } - - private void writeLongArray(long[] longs, int lenMinus1) throws IOException - { - final Writer output = this.out; - if (writeLongsAsStrings) - { - for (int i = 0; i < lenMinus1; i++) - { - output.write('"'); - output.write(Long.toString(longs[i])); - output.write('"'); - output.write(','); - } - output.write('"'); - output.write(Long.toString(longs[lenMinus1])); - output.write('"'); - } - else - { - for (int i = 0; i < lenMinus1; i++) - { - output.write(Long.toString(longs[i])); - output.write(','); - } - output.write(Long.toString(longs[lenMinus1])); - } - } - - private void writeIntArray(int[] ints, int lenMinus1) throws IOException - { - final Writer output = this.out; - for (int i = 0; i < lenMinus1; i++) - { - output.write(Integer.toString(ints[i])); - output.write(','); - } - output.write(Integer.toString(ints[lenMinus1])); - } - - private void writeShortArray(short[] shorts, int lenMinus1) throws IOException - { - final Writer output = this.out; - for (int i = 0; i < lenMinus1; i++) - { - output.write(Integer.toString(shorts[i])); - output.write(','); - } - output.write(Integer.toString(shorts[lenMinus1])); - } - - private void writeByteArray(byte[] bytes, int lenMinus1) throws IOException - { - final Writer output = this.out; - final Object[] byteStrs = byteStrings; - for (int i = 0; i < lenMinus1; i++) - { - output.write((char[]) byteStrs[bytes[i] + 128]); - output.write(','); - } - output.write((char[]) byteStrs[bytes[lenMinus1] + 128]); - } - - private void writeCollection(Collection col, boolean showType) throws IOException - { - if (neverShowType) - { - showType = false; - } - final Writer output = this.out; - boolean referenced = objsReferenced.containsKey(col); - boolean isEmpty = col.isEmpty(); - - if (referenced || showType) - { - output.write('{'); - tabIn(); - } - else if (isEmpty) - { - output.write('['); - } - - writeIdAndTypeIfNeeded(col, showType, referenced); - - if (isEmpty) - { - if (referenced || showType) - { - tabOut(); - output.write('}'); - } - else - { - output.write(']'); - } - return; - } - - beginCollection(showType, referenced); - Iterator i = col.iterator(); - - writeElements(output, i); - - tabOut(); - output.write(']'); - if (showType || referenced) - { // Finished object, as it was output as an object if @id or @type was output - tabOut(); - output.write("}"); - } - } - - private void writeElements(Writer output, Iterator i) throws IOException - { - while (i.hasNext()) - { - writeCollectionElement(i.next()); - - if (i.hasNext()) - { - output.write(','); - newLine(); - } - } - } - - private void writeIdAndTypeIfNeeded(Object col, boolean showType, boolean referenced) throws IOException - { - if (neverShowType) - { - showType = false; - } - if (referenced) - { - writeId(getId(col)); - } - - if (showType) - { - if (referenced) - { - out.write(','); - newLine(); - } - writeType(col, out); - } - } - - private void beginCollection(boolean showType, boolean referenced) throws IOException - { - if (showType || referenced) - { - out.write(','); - newLine(); - out.write(shortMetaKeys ? "\"@e\":[" : "\"@items\":["); - } - else - { - out.write('['); - } - tabIn(); - } - - private void writeJsonObjectArray(JsonObject jObj, boolean showType) throws IOException - { - if (neverShowType) - { - showType = false; - } - int len = jObj.getLength(); - String type = jObj.type; - Class arrayClass; - - if (type == null || Object[].class.getName().equals(type)) - { - arrayClass = Object[].class; - } - else - { - arrayClass = MetaUtils.classForName(type, getClassLoader()); - } - - final Writer output = this.out; - final boolean isObjectArray = Object[].class == arrayClass; - final Class componentClass = arrayClass.getComponentType(); - boolean referenced = objsReferenced.containsKey(jObj) && jObj.hasId(); - boolean typeWritten = showType && !isObjectArray; - - if (typeWritten || referenced) - { - output.write('{'); - tabIn(); - } - - if (referenced) - { - writeId(Long.toString(jObj.id)); - output.write(','); - newLine(); - } - - if (typeWritten) - { - output.write(shortMetaKeys ? "\"@t\":\"" : "\"@type\":\""); - output.write(getSubstituteTypeName(arrayClass.getName())); - output.write("\","); - newLine(); - } - - if (len == 0) - { - if (typeWritten || referenced) - { - output.write(shortMetaKeys ? "\"@e\":[]" : "\"@items\":[]"); - tabOut(); - output.write("}"); - } - else - { - output.write("[]"); - } - return; - } - - if (typeWritten || referenced) - { - output.write(shortMetaKeys ? "\"@e\":[" : "\"@items\":["); - } - else - { - output.write('['); - } - tabIn(); - - Object[] items = (Object[]) jObj.get("@items"); - final int lenMinus1 = len - 1; - - for (int i = 0; i < len; i++) - { - final Object value = items[i]; - - if (value == null) - { - output.write("null"); - } - else if (Character.class == componentClass || char.class == componentClass) - { - writeJsonUtf8String((String) value, output); - } - else if (value instanceof Boolean || value instanceof Long || value instanceof Double) - { - writePrimitive(value, value.getClass() != componentClass); - } - else if (neverShowType && MetaUtils.isPrimitive(value.getClass())) - { - writePrimitive(value, false); - } - else if (value instanceof String) - { // Have to specially treat String because it could be referenced, but we still want inline (no @type, value:) - writeJsonUtf8String((String) value, output); - } - else if (writeArrayElementIfMatching(componentClass, value, false, output)) { } - else - { // Specific Class-type arrays - only force type when - // the instance is derived from array base class. - boolean forceType = !(value.getClass() == componentClass); - writeImpl(value, forceType || alwaysShowType); - } - - if (i != lenMinus1) - { - output.write(','); - newLine(); - } - } - - tabOut(); - output.write(']'); - if (typeWritten || referenced) - { - tabOut(); - output.write('}'); - } - } - - private void writeJsonObjectCollection(JsonObject jObj, boolean showType) throws IOException - { - if (neverShowType) - { - showType = false; - } - String type = jObj.type; - Class colClass = MetaUtils.classForName(type, getClassLoader()); - boolean referenced = objsReferenced.containsKey(jObj) && jObj.hasId(); - final Writer output = this.out; - int len = jObj.getLength(); - - if (referenced || showType || len == 0) - { - output.write('{'); - tabIn(); - } - - if (referenced) - { - writeId(String.valueOf(jObj.id)); - } - - if (showType) - { - if (referenced) - { - output.write(','); - newLine(); - } - output.write(shortMetaKeys ? "\"@t\":\"" : "\"@type\":\""); - output.write(getSubstituteTypeName(colClass.getName())); - output.write('"'); - } - - if (len == 0) - { - tabOut(); - output.write('}'); - return; - } - - beginCollection(showType, referenced); - - Object[] items = (Object[]) jObj.get("@items"); - final int itemsLen = items.length; - final int itemsLenMinus1 = itemsLen - 1; - - for (int i=0; i < itemsLen; i++) - { - writeCollectionElement(items[i]); - - if (i != itemsLenMinus1) - { - output.write(','); - newLine(); - } - } - - tabOut(); - output.write("]"); - if (showType || referenced) - { - tabOut(); - output.write('}'); - } - } - - private void writeJsonObjectMap(JsonObject jObj, boolean showType) throws IOException - { - if (neverShowType) - { - showType = false; - } - boolean referenced = objsReferenced.containsKey(jObj) && jObj.hasId(); - final Writer output = this.out; - - output.write('{'); - tabIn(); - if (referenced) - { - writeId(String.valueOf(jObj.getId())); - } - - if (showType) - { - if (referenced) - { - output.write(','); - newLine(); - } - String type = jObj.getType(); - if (type != null) - { - Class mapClass = MetaUtils.classForName(type, getClassLoader()); - output.write(shortMetaKeys ? "\"@t\":\"" : "\"@type\":\""); - output.write(getSubstituteTypeName(mapClass.getName())); - output.write('"'); - } - else - { // type not displayed - showType = false; - } - } - - if (jObj.isEmpty()) - { // Empty - tabOut(); - output.write('}'); - return; - } - - if (showType) - { - output.write(','); - newLine(); - } - - output.write(shortMetaKeys ? "\"@k\":[" : "\"@keys\":["); - tabIn(); - Iterator i = jObj.keySet().iterator(); - - writeElements(output, i); - - tabOut(); - output.write("],"); - newLine(); - output.write(shortMetaKeys ? "\"@e\":[" : "\"@items\":["); - tabIn(); - i =jObj.values().iterator(); - - writeElements(output, i); - - tabOut(); - output.write(']'); - tabOut(); - output.write('}'); - } - - - private boolean writeJsonObjectMapWithStringKeys(JsonObject jObj, boolean showType) throws IOException - { - if (neverShowType) - { - showType = false; - } - - if (!ensureJsonPrimitiveKeys(jObj)) - { - return false; - } - - boolean referenced = objsReferenced.containsKey(jObj) && jObj.hasId(); - final Writer output = this.out; - output.write('{'); - tabIn(); - - if (referenced) - { - writeId(String.valueOf(jObj.getId())); - } - - if (showType) - { - if(referenced) - { - output.write(','); - newLine(); - } - String type = jObj.getType(); - if (type != null) - { - Class mapClass = MetaUtils.classForName(type, getClassLoader()); - output.write(shortMetaKeys ? "\"@t\":\"" : "\"@type\":\""); - output.write(getSubstituteTypeName(mapClass.getName())); - output.write('"'); - } - else - { // type not displayed - showType = false; - } - } - - if (jObj.isEmpty()) - { // Empty - tabOut(); - output.write('}'); - return true; - } - - if (showType) - { - output.write(','); - newLine(); - } - - return writeMapBody(jObj.entrySet().iterator()); - } - - /** - * Write fields of an Object (JsonObject) - */ - private void writeJsonObjectObject(JsonObject jObj, boolean showType) throws IOException - { - if (neverShowType) - { - showType = false; - } - final Writer output = this.out; - boolean referenced = objsReferenced.containsKey(jObj) && jObj.hasId(); - showType = showType && jObj.type != null; - Class type = null; - - output.write('{'); - tabIn(); - if (referenced) - { - writeId(String.valueOf(jObj.id)); - } - - if (showType) - { - if (referenced) - { - output.write(','); - newLine(); - } - output.write(shortMetaKeys ? "\"@t\":\"" : "\"@type\":\""); - output.write(getSubstituteTypeName(jObj.type)); - output.write('"'); - try { type = MetaUtils.classForName(jObj.type, getClassLoader()); } catch(Exception ignored) { type = null; } - } - - if (jObj.isEmpty()) - { - tabOut(); - output.write('}'); - return; - } - - if (showType || referenced) - { - output.write(','); - newLine(); - } - - Iterator> i = jObj.entrySet().iterator(); - boolean first = true; - - while (i.hasNext()) - { - Entryentry = i.next(); - if (skipNullFields && entry.getValue() == null) - { - continue; - } - - if (!first) - { - output.write(','); - newLine(); - } - first = false; - final String fieldName = entry.getKey(); - output.write('"'); - output.write(fieldName); - output.write("\":"); - Object value = entry.getValue(); - - if (value == null) - { - output.write("null"); - } - else if (neverShowType && MetaUtils.isPrimitive(value.getClass())) - { - writePrimitive(value, false); - } - else if (value instanceof BigDecimal || value instanceof BigInteger) - { - writeImpl(value, !doesValueTypeMatchFieldType(type, fieldName, value)); - } - else if (value instanceof Number || value instanceof Boolean) - { - output.write(value.toString()); - } - else if (value instanceof String) - { - writeJsonUtf8String((String) value, output); - } - else if (value instanceof Character) - { - writeJsonUtf8String(String.valueOf(value), output); - } - else - { - writeImpl(value, !doesValueTypeMatchFieldType(type, fieldName, value)); - } - } - tabOut(); - output.write('}'); - } - - private static boolean doesValueTypeMatchFieldType(Class type, String fieldName, Object value) - { - if (type != null) - { - Map classFields = MetaUtils.getDeepDeclaredFields(type); - Field field = classFields.get(fieldName); - return field != null && (value.getClass() == field.getType()); - } - return false; - } - - private void writeMap(Map map, boolean showType) throws IOException - { - if (neverShowType) - { - showType = false; - } - final Writer output = this.out; - boolean referenced = objsReferenced.containsKey(map); - - output.write('{'); - tabIn(); - if (referenced) - { - writeId(getId(map)); - } - - if (showType) - { - if (referenced) - { - output.write(','); - newLine(); - } - writeType(map, output); - } - - if (map.isEmpty()) - { - tabOut(); - output.write('}'); - return; - } - - if (showType || referenced) - { - output.write(','); - newLine(); - } - - output.write(shortMetaKeys ? "\"@k\":[" : "\"@keys\":["); - tabIn(); - Iterator i = map.keySet().iterator(); - - writeElements(output, i); - - tabOut(); - output.write("],"); - newLine(); - output.write(shortMetaKeys ? "\"@e\":[" : "\"@items\":["); - tabIn(); - i = map.values().iterator(); - - writeElements(output, i); - - tabOut(); - output.write(']'); - tabOut(); - output.write('}'); - } - - - private boolean writeMapWithStringKeys(Map map, boolean showType) throws IOException - { - if (neverShowType) - { - showType = false; - } - if (!ensureJsonPrimitiveKeys(map)) - { - return false; - } - - boolean referenced = objsReferenced.containsKey(map); - - out.write('{'); - tabIn(); - writeIdAndTypeIfNeeded(map, showType, referenced); - - if (map.isEmpty()) - { - tabOut(); - out.write('}'); - return true; - } - - if (showType || referenced) - { - out.write(','); - newLine(); - } - - return writeMapBody(map.entrySet().iterator()); - } - - private boolean writeMapBody(final Iterator i) throws IOException - { - final Writer output = out; - while (i.hasNext()) - { - Entry att2value = (Entry) i.next(); - writeJsonUtf8String((String)att2value.getKey(), output); - output.write(":"); - - writeCollectionElement(att2value.getValue()); - - if (i.hasNext()) - { - output.write(','); - newLine(); - } - } - - tabOut(); - output.write('}'); - return true; - } - - /** - * Ensure that all keys within the Map are String instances - * @param map Map to inspect that all keys are primitive. This allows the output JSON - * to be optimized into {"key1":value1, "key2": value2} format if all the - * keys of the Map are Strings. If not, then a Map is written as two - * arrays, an @keys array and an @items array. This allows support for Maps - * with non-String keys. - */ - public static boolean ensureJsonPrimitiveKeys(Map map) - { - for (Object o : map.keySet()) - { - if (!(o instanceof String)) - { - return false; - } - } - return true; - } - - /** - * Write an element that is contained in some type of Collection or Map. - * @param o Collection element to output in JSON format. - * @throws IOException if an error occurs writing to the output stream. - */ - private void writeCollectionElement(Object o) throws IOException - { - if (o == null) - { - out.write("null"); - } - else if (o instanceof Boolean || o instanceof Double) - { - writePrimitive(o, false); - } - else if (o instanceof Long) - { - writePrimitive(o, writeLongsAsStrings); - } - else if (o instanceof String) - { // Never do an @ref to a String (they are treated as logical primitives and intern'ed on read) - writeJsonUtf8String((String) o, out); - } - else if (neverShowType && MetaUtils.isPrimitive(o.getClass())) - { // If neverShowType, then force primitives (and primitive wrappers) - // to be output with toString() - prevents {"value":6} for example - writePrimitive(o, false); - } - else - { - writeImpl(o, true); - } - } - - /** - * @param obj Object to be written in JSON format - * @param showType boolean true means show the "@type" field, false - * eliminates it. Many times the type can be dropped because it can be - * inferred from the field or array type. - * @param bodyOnly write only the body of the object - * @throws IOException if an error occurs writing to the output stream. - */ - public void writeObject(final Object obj, boolean showType, boolean bodyOnly) throws IOException - { - if (neverShowType) - { - showType = false; - } - final boolean referenced = objsReferenced.containsKey(obj); - if (!bodyOnly) - { - out.write('{'); - tabIn(); - if (referenced) - { - writeId(getId(obj)); - } - - if (referenced && showType) - { - out.write(','); - newLine(); - } - - if (showType) - { - writeType(obj, out); - } - } - - boolean first = !showType; - if (referenced && !showType) - { - first = false; - } - - final Map> fieldSpecifiers = (Map) args.get(FIELD_SPECIFIERS); - final List fieldBlackListForClass = getFieldsUsingSpecifier(obj.getClass(), (Map) args.get(FIELD_BLACK_LIST)); - final List externallySpecifiedFields = getFieldsUsingSpecifier(obj.getClass(), fieldSpecifiers); - if (externallySpecifiedFields != null) - { - for (Field field : externallySpecifiedFields) - { //output field if not on the blacklist - if (fieldBlackListForClass == null || !fieldBlackListForClass.contains(field)){ - // Not currently supporting overwritten field names in hierarchy when using external field specifier - first = writeField(obj, first, field.getName(), field, true); - }//else field is black listed. - } - } - else - { // Reflectively use fields, skipping transient and static fields - final Map classFields = MetaUtils.getDeepDeclaredFields(obj.getClass()); - for (Entry entry : classFields.entrySet()) - { - final String fieldName = entry.getKey(); - final Field field = entry.getValue(); - //output field if not on the blacklist - if (fieldBlackListForClass == null || !fieldBlackListForClass.contains(field)){ - first = writeField(obj, first, fieldName, field, false); - }//else field is black listed. - } - } - - if (!bodyOnly) - { - tabOut(); - out.write('}'); - } - } - - private boolean writeField(Object obj, boolean first, String fieldName, Field field, boolean allowTransient) throws IOException - { - if (!allowTransient && (field.getModifiers() & Modifier.TRANSIENT) != 0) - { // Do not write transient fields - return first; - } - - int modifiers = field.getModifiers(); - if (Enum.class.isAssignableFrom(field.getDeclaringClass())) - { - if (!"name".equals(field.getName())) - { - if (!Modifier.isPublic(modifiers) && isEnumPublicOnly) - { - return first; - } - if ("ordinal".equals(field.getName()) || "internal".equals(field.getName())) - { - return first; - } - } - } - - Object o; - try - { - o = field.get(obj); - } - catch (Exception ignored) - { - o = null; - } - - if (skipNullFields && o == null) - { // If skip null, skip field and return the same status on first field written indicator - return first; - } - - if (!first) - { - out.write(','); - newLine(); - } - - writeJsonUtf8String(fieldName, out); - out.write(':'); - - - if (o == null) - { // don't quote null - out.write("null"); - return false; - } - - Class type = field.getType(); - boolean forceType = o.getClass() != type; // If types are not exactly the same, write "@type" field - - //When no type is written we can check the Object itself not the declaration - if (MetaUtils.isPrimitive(type) || (neverShowType && MetaUtils.isPrimitive(o.getClass()))) - { - writePrimitive(o, false); - } - else - { - writeImpl(o, forceType || alwaysShowType, true, true); - } - return false; - } - - /** - * Write out special characters "\b, \f, \t, \n, \r", as such, backslash as \\ - * quote as \" and values less than an ASCII space (20hex) as "\\u00xx" format, - * characters in the range of ASCII space to a '~' as ASCII, and anything higher in UTF-8. - * - * @param s String to be written in UTF-8 format on the output stream. - * @param output Writer to which the UTF-8 string will be written to - * @throws IOException if an error occurs writing to the output stream. - */ - public static void writeJsonUtf8String(String s, final Writer output) throws IOException - { - output.write('\"'); - final int len = s.length(); - - for (int i = 0; i < len; i++) - { - char c = s.charAt(i); - - if (c < ' ') - { // Anything less than ASCII space, write either in \\u00xx form, or the special \t, \n, etc. form - switch (c) - { - case '\b': - output.write("\\b"); - break; - case '\f': - output.write("\\f"); - break; - case '\n': - output.write("\\n"); - break; - case '\r': - output.write("\\r"); - break; - case '\t': - output.write("\\t"); - break; - default: - output.write(String.format("\\u%04X", (int)c)); - break; - } - } - else if (c == '\\' || c == '"') - { - output.write('\\'); - output.write(c); - } - else - { // Anything else - write in UTF-8 form (multi-byte encoded) (OutputStreamWriter is UTF-8) - output.write(c); - } - } - output.write('\"'); - } - - public void flush() - { - try - { - if (out != null) - { - out.flush(); - } - } - catch (Exception ignored) { } - } - - public void close() - { - try - { - out.close(); - } - catch (Exception ignore) { } - writerCache.clear(); - writers.clear(); - } - - private String getId(Object o) - { - if (o instanceof JsonObject) - { - long id = ((JsonObject) o).id; - if (id != -1) - { - return String.valueOf(id); - } - } - Long id = objsReferenced.get(o); - return id == null ? null : Long.toString(id); - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/MapResolver.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/MapResolver.java deleted file mode 100644 index ded6a2a1..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/MapResolver.java +++ /dev/null @@ -1,217 +0,0 @@ -package cn.lastwhisper.monitor.agent.json; - -import java.lang.reflect.Field; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Deque; -import java.util.List; -import java.util.Map; - -/** - *

The MapResolver converts the raw Maps created from the JsonParser to higher - * quality Maps representing the implied object graph. It does this by replacing - * @ref values with the Map indicated by the @id key with the same value. - *

- * This approach 'wires' the original object graph. During the resolution process, - * if 'peer' classes can be found for given Maps (for example, an @type entry is - * available which indicates the class that would have been associated to the Map, - * then the associated class is consulted to help 'improve' the quality of the primitive - * values within the map fields. For example, if the peer class indicated that a field - * was of type 'short', and the Map had a long value (JSON only returns long's for integer - * types), then the long would be converted to a short. - *

- * The final Map representation is a very high-quality graph that represents the original - * JSON graph. It can be passed as input to JsonWriter, and the JsonWriter will write - * out the equivalent JSON to what was originally read. This technique allows json-io to - * be used on a machine that does not have any of the Java classes from the original graph, - * read it in a JSON graph (any JSON graph), return the equivalent maps, allow mutations of - * those maps, and finally this graph can be written out. - *

- * @author John DeRegnaucourt (jdereg@gmail.com) - *
- * Copyright (c) Cedar Software LLC - *

- * Licensed 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. - */ -public class MapResolver extends Resolver -{ - protected MapResolver(JsonReader reader) - { - super(reader); - } - - protected Object readIfMatching(Object o, Class compType, Deque> stack) - { - // No custom reader support for maps - return null; - } - - /** - * Walk the JsonObject fields and perform necessary substitutions so that all references matched up. - * This code patches @ref and @id pairings up, in the 'Map of Map' mode. Where the JSON may contain - * an @id of an object which can have more than one @ref to it, this code will make sure that each - * @ref (value side of the Map associated to a given field name) will be pointer to the appropriate Map - * instance. - * @param stack Stack (Deque) used for graph traversal. - * @param jsonObj a Map-of-Map representation of the current object being examined (containing all fields). - */ - public void traverseFields(final Deque> stack, final JsonObject jsonObj) - { - final Object target = jsonObj.target; - for (Map.Entry e : jsonObj.entrySet()) - { - final String fieldName = e.getKey(); - final Field field = (target != null) ? MetaUtils.getField(target.getClass(), fieldName) : null; - final Object rhs = e.getValue(); - - if (rhs == null) - { - jsonObj.put(fieldName, null); - } - else if (rhs == JsonParser.EMPTY_OBJECT) - { - jsonObj.put(fieldName, new JsonObject()); - } - else if (rhs.getClass().isArray()) - { // RHS is an array - // Trace the contents of the array (so references inside the array and into the array work) - JsonObject jsonArray = new JsonObject(); - jsonArray.put("@items", rhs); - stack.addFirst(jsonArray); - - // Assign the array directly to the Map key (field name) - jsonObj.put(fieldName, rhs); - } - else if (rhs instanceof JsonObject) - { - JsonObject jObj = (JsonObject) rhs; - if (field != null && JsonObject.isPrimitiveWrapper(field.getType())) - { - jObj.put("value", MetaUtils.newPrimitiveWrapper(field.getType(), jObj.get("value"))); - continue; - } - Long refId = jObj.getReferenceId(); - - if (refId != null) - { // Correct field references - JsonObject refObject = getReferencedObj(refId); - jsonObj.put(fieldName, refObject); // Update Map-of-Maps reference - } - else - { - stack.addFirst(jObj); - } - } - else if (field != null) - { // The code below is 'upgrading' the RHS values in the passed in JsonObject Map - // by using the @type class name (when specified and exists), to coerce the vanilla - // JSON values into the proper types defined by the class listed in @type. This is - // a cool feature of json-io, that even when reading a map-of-maps JSON file, it will - // improve the final types of values in the maps RHS, to be of the field type that - // was optionally specified in @type. - final Class fieldType = field.getType(); - if (MetaUtils.isPrimitive(fieldType)) - { - jsonObj.put(fieldName, MetaUtils.newPrimitiveWrapper(fieldType, rhs)); - } - else if (BigDecimal.class == fieldType) - { - jsonObj.put(fieldName, Readers.bigDecimalFrom(rhs)); - } - else if (BigInteger.class == fieldType) - { - jsonObj.put(fieldName, Readers.bigIntegerFrom(rhs)); - } - else if (rhs instanceof String) - { - if (fieldType != String.class && fieldType != StringBuilder.class && fieldType != StringBuffer.class) - { - if ("".equals(((String)rhs).trim())) - { // Allow "" to null out a non-String field on the inbound JSON - jsonObj.put(fieldName, null); - } - } - } - } - } - jsonObj.target = null; // don't waste space (used for typed return, not for Map return) - } - - /** - * Process java.util.Collection and it's derivatives. Collections are written specially - * so that the serialization does not expose the Collection's internal structure, for - * example a TreeSet. All entries are processed, except unresolved references, which - * are filled in later. For an indexable collection, the unresolved references are set - * back into the proper element location. For non-indexable collections (Sets), the - * unresolved references are added via .add(). - * @param stack a Stack (Deque) used to support graph traversal. - * @param jsonObj a Map-of-Map representation of the JSON input stream. - */ - protected void traverseCollection(final Deque> stack, final JsonObject jsonObj) - { - final Object[] items = jsonObj.getArray(); - if (items == null || items.length == 0) - { - return; - } - - int idx = 0; - final List copy = new ArrayList(items.length); - - for (Object element : items) - { - if (element == JsonParser.EMPTY_OBJECT) - { - copy.add(new JsonObject()); - continue; - } - - copy.add(element); - - if (element instanceof Object[]) - { // array element inside Collection - JsonObject jsonObject = new JsonObject(); - jsonObject.put("@items", element); - stack.addFirst(jsonObject); - } - else if (element instanceof JsonObject) - { - JsonObject jsonObject = (JsonObject) element; - Long refId = jsonObject.getReferenceId(); - - if (refId != null) - { // connect reference - JsonObject refObject = getReferencedObj(refId); - copy.set(idx, refObject); - } - else - { - stack.addFirst(jsonObject); - } - } - idx++; - } - jsonObj.target = null; // don't waste space (used for typed return, not generic Map return) - - for (int i=0; i < items.length; i++) - { - items[i] = copy.get(i); - } - } - - protected void traverseArray(Deque> stack, JsonObject jsonObj) - { - traverseCollection(stack, jsonObj); - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/MetaUtils.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/MetaUtils.java deleted file mode 100644 index 5acf3eeb..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/MetaUtils.java +++ /dev/null @@ -1,1039 +0,0 @@ -package cn.lastwhisper.monitor.agent.json; - -import java.lang.reflect.*; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.net.MalformedURLException; -import java.net.URL; -import java.sql.Timestamp; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static java.lang.reflect.Modifier.*; - -/** - * This utility class has the methods mostly related to reflection related code. - * - * @author John DeRegnaucourt (jdereg@gmail.com) - *
- * Copyright (c) Cedar Software LLC - *

- * Licensed 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.* - */ -public class MetaUtils -{ - private MetaUtils () {} - - private static final Map> classMetaCache = new ConcurrentHashMap>(); - private static final Set prims = new HashSet(); - private static final Map nameToClass = new HashMap(); - private static final Byte[] byteCache = new Byte[256]; - private static final Character[] charCache = new Character[128]; - private static final Pattern extraQuotes = Pattern.compile("([\"]*)([^\"]*)([\"]*)"); - private static final Class[] emptyClassArray = new Class[]{}; - private static final ConcurrentMap constructors = new ConcurrentHashMap(); - private static final Collection unmodifiableCollection = Collections.unmodifiableCollection(new ArrayList()); - private static final Collection unmodifiableSet = Collections.unmodifiableSet(new HashSet()); - private static final Collection unmodifiableSortedSet = Collections.unmodifiableSortedSet(new TreeSet()); - private static final Map unmodifiableMap = Collections.unmodifiableMap(new HashMap()); - private static final Map unmodifiableSortedMap = Collections.unmodifiableSortedMap(new TreeMap()); - static final ThreadLocal dateFormat = new ThreadLocal() - { - public SimpleDateFormat initialValue() - { - return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); - } - }; - private static boolean useUnsafe = false; - private static Unsafe unsafe; - static Exception loadClassException; - - /** - * Globally turn on (or off) the 'unsafe' option of Class construction. The unsafe option - * is used when all constructors have been tried and the Java class could not be instantiated. - * @param state boolean true = on, false = off. - */ - public static void setUseUnsafe(boolean state) - { - useUnsafe = state; - if (state) - { - try - { - unsafe = new Unsafe(); - } - catch (InvocationTargetException e) - { - useUnsafe = false; - } - } - } - - static - { - prims.add(Byte.class); - prims.add(Integer.class); - prims.add(Long.class); - prims.add(Double.class); - prims.add(Character.class); - prims.add(Float.class); - prims.add(Boolean.class); - prims.add(Short.class); - - nameToClass.put("string", String.class); - nameToClass.put("boolean", boolean.class); - nameToClass.put("char", char.class); - nameToClass.put("byte", byte.class); - nameToClass.put("short", short.class); - nameToClass.put("int", int.class); - nameToClass.put("long", long.class); - nameToClass.put("float", float.class); - nameToClass.put("double", double.class); - nameToClass.put("date", Date.class); - nameToClass.put("class", Class.class); - - // Save memory by re-using all byte instances (Bytes are immutable) - for (int i = 0; i < byteCache.length; i++) - { - byteCache[i] = (byte) (i - 128); - } - - // Save memory by re-using common Characters (Characters are immutable) - for (int i = 0; i < charCache.length; i++) - { - charCache[i] = (char) i; - } - } - - /** - * Return an instance of of the Java Field class corresponding to the passed in field name. - * @param c class containing the field / field name - * @param field String name of a field on the class. - * @return Field instance if the field with the corresponding name is found, null otherwise. - */ - public static Field getField(Class c, String field) - { - return getDeepDeclaredFields(c).get(field); - } - - /** - * @param c Class instance - * @return ClassMeta which contains fields of class. The results are cached internally for performance - * when called again with same Class. - */ - public static Map getDeepDeclaredFields(Class c) - { - Map classFields = classMetaCache.get(c); - if (classFields != null) - { - return classFields; - } - - classFields = new LinkedHashMap(); - Class curr = c; - - while (curr != null) - { - try - { - final Field[] local = curr.getDeclaredFields(); - - for (Field field : local) - { - if ((field.getModifiers() & Modifier.STATIC) == 0) - { // speed up: do not process static fields. - if ("metaClass".equals(field.getName()) && "groovy.lang.MetaClass".equals(field.getType().getName())) - { // Skip Groovy metaClass field if present - continue; - } - - if (!field.isAccessible()) - { - try - { - field.setAccessible(true); - } - catch (Exception ignored) { } - } - if (classFields.containsKey(field.getName())) - { - classFields.put(curr.getName() + '.' + field.getName(), field); - } - else - { - classFields.put(field.getName(), field); - } - } - } - } - catch (ThreadDeath t) - { - throw t; - } - catch (Throwable ignored) { } - - curr = curr.getSuperclass(); - } - - classMetaCache.put(c, classFields); - return classFields; - } - - /** - * @param a Class source class - * @param b Class target class - * @return inheritance distance between two classes, or Integer.MAX_VALUE if they are not related. Each - * step upward in the inheritance from one class to the next (calling class.getSuperclass()) is counted - * as 1. This can be a lot of computational effort, therefore the results of this determination should be cached. - */ - public static int getDistance(Class a, Class b) - { - if (a.isInterface()) - { - return getDistanceToInterface(a, b); - } - Class curr = b; - int distance = 0; - - while (curr != a) - { - distance++; - curr = curr.getSuperclass(); - if (curr == null) - { - return Integer.MAX_VALUE; - } - } - - return distance; - } - - /** - * @return int distance between two passed in classes. This method performs an exhaustive - * walk up the inheritance chain to compute the distance. This can be a lot of - * computational effort, therefore the results of this determination should be cached internally. - */ - static int getDistanceToInterface(Class to, Class from) - { - Set> possibleCandidates = new LinkedHashSet>(); - - Class[] interfaces = from.getInterfaces(); - // is the interface direct inherited or via interfaces extends interface? - for (Class interfase : interfaces) - { - if (to.equals(interfase)) - { - return 1; - } - // because of multi-inheritance from interfaces - if (to.isAssignableFrom(interfase)) - { - possibleCandidates.add(interfase); - } - } - - // it is also possible, that the interface is included in superclasses - if (from.getSuperclass() != null && to.isAssignableFrom(from.getSuperclass())) - { - possibleCandidates.add(from.getSuperclass()); - } - - int minimum = Integer.MAX_VALUE; - for (Class candidate : possibleCandidates) - { - // Could do that in a non recursive way later - int distance = getDistanceToInterface(to, candidate); - if (distance < minimum) - { - minimum = ++distance; - } - } - return minimum; - } - - /** - * @param c Class to test - * @return boolean true if the passed in class is a Java primitive, false otherwise. The Wrapper classes - * Integer, Long, Boolean, etc. are considered primitives by this method. - */ - public static boolean isPrimitive(Class c) - { - return c.isPrimitive() || prims.contains(c); - } - - /** - * @param c Class to test - * @return boolean true if the passed in class is a 'logical' primitive. A logical primitive is defined - * as all Java primitives, the primitive wrapper classes, String, Number, and Class. The reason these are - * considered 'logical' primitives is that they are immutable and therefore can be written without references - * in JSON content (making the JSON more readable - less @id / @ref), without breaking the semantics (shape) - * of the object graph being written. - */ - public static boolean isLogicalPrimitive(Class c) - { - return c.isPrimitive() || - prims.contains(c) || - String.class.isAssignableFrom(c) || - Number.class.isAssignableFrom(c) || - Date.class.isAssignableFrom(c) || - c.isEnum() || - c.equals(Class.class); - } - - /** - * Given the passed in String class name, return the named JVM class. - * @param name String name of a JVM class. - * @param classLoader ClassLoader to use when searching for JVM classes. - * @param failOnClassLoadingError If named class is not loadable off classpath: true will raise JsonIoException, - * false will return default LinkedHashMap. - * @return Class the named JVM class. - * @throws JsonIoException if named Class is invalid or not loadable via the classLoader and failOnClassLoadingError is - * true - */ - static Class classForName(String name, ClassLoader classLoader, boolean failOnClassLoadingError) - { - if (name == null || name.isEmpty()) - { - throw new JsonIoException("Class name cannot be null or empty."); - } - Class c = nameToClass.get(name); - try - { - loadClassException = null; - return c == null ? loadClass(name, classLoader) : c; - } - catch (Exception e) - { - // Remember why in case later we have a problem - loadClassException = e; - if(failOnClassLoadingError) { - throw new JsonIoException("Unable to create class: " + name, e); - } - return LinkedHashMap.class; - } - } - - - /** - * Given the passed in String class name, return the named JVM class. - * @param name String name of a JVM class. - * @param classLoader ClassLoader to use when searching for JVM classes. - * @return Class the named JVM class. - * @throws JsonIoException if named Class is invalid. - */ - static Class classForName(String name, ClassLoader classLoader) - { - return classForName(name, classLoader, false); - } - - /** - * loadClass() provided by: Thomas Margreiter - */ - private static Class loadClass(String name, ClassLoader classLoader) throws ClassNotFoundException - { - String className = name; - boolean arrayType = false; - Class primitiveArray = null; - - while (className.startsWith("[")) - { - arrayType = true; - if (className.endsWith(";")) - { - className = className.substring(0, className.length() - 1); - } - if (className.equals("[B")) - { - primitiveArray = byte[].class; - } - else if (className.equals("[S")) - { - primitiveArray = short[].class; - } - else if (className.equals("[I")) - { - primitiveArray = int[].class; - } - else if (className.equals("[J")) - { - primitiveArray = long[].class; - } - else if (className.equals("[F")) - { - primitiveArray = float[].class; - } - else if (className.equals("[D")) - { - primitiveArray = double[].class; - } - else if (className.equals("[Z")) - { - primitiveArray = boolean[].class; - } - else if (className.equals("[C")) - { - primitiveArray = char[].class; - } - int startpos = className.startsWith("[L") ? 2 : 1; - className = className.substring(startpos); - } - Class currentClass = null; - if (null == primitiveArray) - { - currentClass = classLoader.loadClass(className); - } - - if (arrayType) - { - currentClass = (null != primitiveArray) ? primitiveArray : Array.newInstance(currentClass, 0).getClass(); - while (name.startsWith("[[")) - { - currentClass = Array.newInstance(currentClass, 0).getClass(); - name = name.substring(1); - } - } - return currentClass; - } - - /** - * This is a performance optimization. The lowest 128 characters are re-used. - * - * @param c char to match to a Character. - * @return a Character that matches the passed in char. If the value is - * less than 127, then the same Character instances are re-used. - */ - static Character valueOf(char c) - { - return c <= 127 ? charCache[(int) c] : c; - } - - /** - * Strip leading and trailing double quotes from the passed in String. - */ - static String removeLeadingAndTrailingQuotes(String s) - { - Matcher m = extraQuotes.matcher(s); - if (m.find()) - { - s = m.group(2); - } - return s; - } - - /** - *

C language malloc() for Java - *

- * Create a new instance of the passed in Class. This method will make a valiant effort to instantiate - * the passed in Class, including calling all of its constructors until successful. The order they - * are tried are public with the fewest arguments first to private with the most arguments. If, after - * exhausting all constructors, then it will attempt using the 'unsafe allocate' from Sun. This step is - * optional - by default it will use this if on a Sun (Oracle) JVM unless MetaUtil.setUseUnsafe(false) is called. - *

- * This method will handle common interfaces, such as Collection, Map, etc. which commonly show up in - * parameterized types. Any other interface passed to this method will cause a JsonIoException to be thrown. - *

- * To improve performance, when called a 2nd time for the same Class, the constructor that was successfully - * used to construct the instance will be retrieved from an internal cache. - *

- * @param c Class to instantiate - * @return an instance of the instantiated class. This instance is intended to have its fields 'stuffed' by - * direct assignment, not called via setter methods. - * @throws JsonIoException if it cannot instantiate the passed in class. - */ - public static Object newInstance(Class c) - { - if (unmodifiableSortedMap.getClass().isAssignableFrom(c)) - { - return new TreeMap(); - } - if (unmodifiableMap.getClass().isAssignableFrom(c)) - { - return new LinkedHashMap(); - } - if (unmodifiableSortedSet.getClass().isAssignableFrom(c)) - { - return new TreeSet(); - } - if (unmodifiableSet.getClass().isAssignableFrom(c)) - { - return new LinkedHashSet(); - } - if (unmodifiableCollection.getClass().isAssignableFrom(c)) - { - return new ArrayList(); - } - - if (c.isInterface()) - { - throw new JsonIoException("Cannot instantiate unknown interface: " + c.getName()); - } - - // Constructor not cached, go find a constructor - Object[] constructorInfo = constructors.get(c); - if (constructorInfo != null) - { // Constructor was cached - Constructor constructor = (Constructor) constructorInfo[0]; - - if (constructor == null && useUnsafe) - { // null constructor --> set to null when object instantiated with unsafe.allocateInstance() - try - { - return unsafe.allocateInstance(c); - } - catch (Exception e) - { - // Should never happen, as the code that fetched the constructor was able to instantiate it once already - throw new JsonIoException("Could not instantiate " + c.getName(), e); - } - } - - if (constructor == null) - { - throw new JsonIoException("No constructor found to instantiate " + c.getName()); - } - - Boolean useNull = (Boolean) constructorInfo[1]; - Class[] paramTypes = constructor.getParameterTypes(); - if (paramTypes == null || paramTypes.length == 0) - { - try - { - return constructor.newInstance(); - } - catch (Exception e) - { // Should never happen, as the code that fetched the constructor was able to instantiate it once already - throw new JsonIoException("Could not instantiate " + c.getName(), e); - } - } - Object[] values = fillArgs(paramTypes, useNull); - try - { - return constructor.newInstance(values); - } - catch (Exception e) - { // Should never happen, as the code that fetched the constructor was able to instantiate it once already - throw new JsonIoException("Could not instantiate " + c.getName(), e); - } - } - - Object[] ret = newInstanceEx(c); - constructors.put(c, new Object[]{ret[1], ret[2]}); - return ret[0]; - } - - /** - * Returns an array with the following: - *
    - *
  1. object instance
  2. - *
  3. constructor
  4. - *
  5. a Boolean, true if all constructor arguments are to be "null"
  6. - *
- */ - static Object[] newInstanceEx(Class c) - { - try - { - Constructor constructor = c.getConstructor(emptyClassArray); - if (constructor != null) - { - return new Object[] {constructor.newInstance(), constructor, true}; - } - // No empty arg constructor - return tryOtherConstruction(c); - } - catch (Exception e) - { - // OK, this class does not have a public no-arg constructor. Instantiate with - // first constructor found, filling in constructor values with null or - // defaults for primitives. - return tryOtherConstruction(c); - } - } - - /** - * Brute force attempt to locate a constructor to construct the passed in Class. This involves trying all - * constructors, public, protected, package-private, and private. It will try with null arguments as well - * as it will make a 2nd attempt with populated values for some known types (Collection classes, Dates, Strings, - * primitive wrappers, TimeZone, Calendar). - * @param c Class to instantiate - * @return an Object[] containing three (3) elements. Position 0 is the instance of the class, position 1 - * is the constructor used, and position 2 indicates whether fillArgs was called with useNull or !useNull. - */ - static Object[] tryOtherConstruction(Class c) - { - Constructor[] constructors = c.getDeclaredConstructors(); - if (constructors.length == 0) - { - throw new JsonIoException("Cannot instantiate '" + c.getName() + "' - Primitive, interface, array[] or void"); - } - - // Sort constructors - public, protected, private, package-private - List constructorList = Arrays.asList(constructors); - Collections.sort(constructorList, new Comparator() - { - public int compare(Constructor c1, Constructor c2) - { - int c1Vis = c1.getModifiers(); - int c2Vis = c2.getModifiers(); - - if (c1Vis == c2Vis) - { // both are public, protected, private, etc. Compare by arguments. - return compareConstructors(c1, c2); - } - - if (isPublic(c1Vis) != isPublic(c2Vis)) - { // favor 'public' as first - return isPublic(c1Vis) ? -1 : 1; - } - - if (isProtected(c1Vis) != isProtected(c2Vis)) - { // favor protected 2nd - return isProtected(c1Vis) ? -1 : 1; - } - - if (isPrivate(c1Vis) != isPrivate(c2Vis)) - { // favor private last - return isPrivate(c1Vis) ? 1 : -1; - } - - return 0; - } - }); - - // Try each constructor (public, protected, private, package-private) with null values for non-primitives. - for (Constructor constructor : constructorList) - { - constructor.setAccessible(true); - Class[] argTypes = constructor.getParameterTypes(); - Object[] values = fillArgs(argTypes, true); - try - { - return new Object[] {constructor.newInstance(values), constructor, true}; - } - catch (Exception ignored) - { } - } - - // Try each constructor (public, protected, private, package-private) with non-null values for non-primitives. - for (Constructor constructor : constructorList) - { - constructor.setAccessible(true); - Class[] argTypes = constructor.getParameterTypes(); - Object[] values = fillArgs(argTypes, false); - try - { - return new Object[] {constructor.newInstance(values), constructor, false}; - } - catch (Exception ignored) - { } - } - - // Try instantiation via unsafe - // This may result in heapdumps for e.g. ConcurrentHashMap or can cause problems when the class is not initialized - // Thats why we try ordinary constructors first - if (useUnsafe) - { - try - { - return new Object[]{unsafe.allocateInstance(c), null, null}; - } - catch (Exception ignored) - { } - } - - throw new JsonIoException("Could not instantiate " + c.getName() + " using any constructor"); - } - - /** - * When two constructors have the same access type (both public, both private, etc.) - * then compare constructors by parameter length (fewer params comes before more params). - * If parameter count is the same, then compare by parameter Class names. If those are equal, - * which should never happen, then the constructurs are equal. - */ - private static int compareConstructors(Constructor c1, Constructor c2) - { - Class[] c1ParamTypes = c1.getParameterTypes(); - Class[] c2ParamTypes = c2.getParameterTypes(); - if (c1ParamTypes.length != c2ParamTypes.length) - { // negative value if c1 has less (less parameters will be chosen ahead of more), positive value otherwise. - return c1ParamTypes.length - c2ParamTypes.length; - } - - // Has same number of parameters.s - int len = c1ParamTypes.length; - for (int i=0; i < len; i++) - { - Class class1 = c1ParamTypes[i]; - Class class2 = c2ParamTypes[i]; - int compare = class1.getName().compareTo(class2.getName()); - if (compare != 0) - { - return compare; - } - } - - return 0; - } - - /** - * Return an Object[] of instance values that can be passed into a given Constructor. This method - * will return an array of nulls if useNull is true, otherwise it will return sensible values for - * primitive classes, and null for non-known primitive / primitive wrappers. This class is used - * when attempting to call constructors on Java objects to get them instantiated, since there is no - * 'malloc' in Java. - */ - static Object[] fillArgs(Class[] argTypes, boolean useNull) - { - final Object[] values = new Object[argTypes.length]; - for (int i = 0; i < argTypes.length; i++) - { - final Class argType = argTypes[i]; - if (isPrimitive(argType)) - { - values[i] = newPrimitiveWrapper(argType, null); - } - else if (useNull) - { - values[i] = null; - } - else - { - if (argType == String.class) - { - values[i] = ""; - } - else if (argType == Date.class) - { - values[i] = new Date(); - } - else if (List.class.isAssignableFrom(argType)) - { - values[i] = new ArrayList(); - } - else if (SortedSet.class.isAssignableFrom(argType)) - { - values[i] = new TreeSet(); - } - else if (Set.class.isAssignableFrom(argType)) - { - values[i] = new LinkedHashSet(); - } - else if (SortedMap.class.isAssignableFrom(argType)) - { - values[i] = new TreeMap(); - } - else if (Map.class.isAssignableFrom(argType)) - { - values[i] = new LinkedHashMap(); - } - else if (Collection.class.isAssignableFrom(argType)) - { - values[i] = new ArrayList(); - } - else if (Calendar.class.isAssignableFrom(argType)) - { - values[i] = Calendar.getInstance(); - } - else if (TimeZone.class.isAssignableFrom(argType)) - { - values[i] = TimeZone.getDefault(); - } - else if (argType == BigInteger.class) - { - values[i] = BigInteger.TEN; - } - else if (argType == BigDecimal.class) - { - values[i] = BigDecimal.TEN; - } - else if (argType == StringBuilder.class) - { - values[i] = new StringBuilder(); - } - else if (argType == StringBuffer.class) - { - values[i] = new StringBuffer(); - } - else if (argType == Locale.class) - { - values[i] = Locale.FRANCE; // overwritten - } - else if (argType == Class.class) - { - values[i] = String.class; - } - else if (argType == Timestamp.class) - { - values[i] = new Timestamp(System.currentTimeMillis()); - } - else if (argType == java.sql.Date.class) - { - values[i] = new java.sql.Date(System.currentTimeMillis()); - } - else if (argType == URL.class) - { - try - { - values[i] = new URL("http://localhost"); // overwritten - } - catch (MalformedURLException e) - { - values[i] = null; - } - } - else if (argType == Object.class) - { - values[i] = new Object(); - } - else - { - values[i] = null; - } - } - } - - return values; - } - - /** - * @return a new primitive wrapper instance for the given class, using the - * rhs parameter as a hint. For example, newPrimitiveWrapper(long.class, "45") - * will return 45L. However, if null is passed for the rhs, then the value 0L - * would be returned in this case. For boolean, it would return false if null - * was passed in. This method is similar to the GitHub project java-util's - * Converter.convert() API. - */ - static Object newPrimitiveWrapper(Class c, Object rhs) - { - try - { - if (c == boolean.class || c == Boolean.class) - { - if (rhs instanceof String) - { - rhs = removeLeadingAndTrailingQuotes((String) rhs); - if ("".equals(rhs)) - { - rhs = "false"; - } - return Boolean.parseBoolean((String) rhs); - } - return rhs != null ? rhs : Boolean.FALSE; - } - else if (c == byte.class || c == Byte.class) - { - if (rhs instanceof String) - { - rhs = removeLeadingAndTrailingQuotes((String) rhs); - if ("".equals(rhs)) - { - rhs = "0"; - } - return Byte.parseByte((String) rhs); - } - return rhs != null ? byteCache[((Number) rhs).byteValue() + 128] : (byte) 0; - } - else if (c == char.class || c == Character.class) - { - if (rhs == null) - { - return '\u0000'; - } - if (rhs instanceof String) - { - rhs = removeLeadingAndTrailingQuotes((String) rhs); - if ("".equals(rhs)) - { - rhs = "\u0000"; - } - return ((CharSequence) rhs).charAt(0); - } - if (rhs instanceof Character) - { - return rhs; - } - // Let it throw exception - } - else if (c == double.class || c == Double.class) - { - if (rhs instanceof String) - { - rhs = removeLeadingAndTrailingQuotes((String) rhs); - if ("".equals(rhs)) - { - rhs = "0.0"; - } - return Double.parseDouble((String) rhs); - } - return rhs != null ? ((Number) rhs).doubleValue() : 0.0d; - } - else if (c == float.class || c == Float.class) - { - if (rhs instanceof String) - { - rhs = removeLeadingAndTrailingQuotes((String) rhs); - if ("".equals(rhs)) - { - rhs = "0.0f"; - } - return Float.parseFloat((String) rhs); - } - return rhs != null ? ((Number) rhs).floatValue() : 0.0f; - } - else if (c == int.class || c == Integer.class) - { - if (rhs instanceof String) - { - rhs = removeLeadingAndTrailingQuotes((String) rhs); - if ("".equals(rhs)) - { - rhs = "0"; - } - return Integer.parseInt((String) rhs); - } - return rhs != null ? ((Number) rhs).intValue() : 0; - } - else if (c == long.class || c == Long.class) - { - if (rhs instanceof String) - { - rhs = removeLeadingAndTrailingQuotes((String) rhs); - if ("".equals(rhs)) - { - rhs = "0"; - } - return Long.parseLong((String) rhs); - } - return rhs != null ? ((Number) rhs).longValue() : 0L; - } - else if (c == short.class|| c == Short.class) - { - if (rhs instanceof String) - { - rhs = removeLeadingAndTrailingQuotes((String) rhs); - if ("".equals(rhs)) - { - rhs = "0"; - } - return Short.parseShort((String) rhs); - } - return rhs != null ? ((Number) rhs).shortValue() : (short) 0; - } - } - catch (Exception e) - { - String className = c == null ? "null" : c.getName(); - throw new JsonIoException("Error creating primitive wrapper instance for Class: " + className, e); - } - - throw new JsonIoException("Class '" + c.getName() + "' does not have primitive wrapper."); - } - - /** - * Format a nice looking method signature for logging output - */ - public static String getLogMessage(String methodName, Object[] args) - { - return getLogMessage(methodName, args, 50); - } - - public static String getLogMessage(String methodName, Object[] args, int argCharLen) - { - StringBuilder sb = new StringBuilder(); - sb.append(methodName); - sb.append('('); - for (Object arg : args) - { - sb.append(getJsonStringToMaxLength(arg, argCharLen)); - sb.append(" "); - } - String result = sb.toString().trim(); - return result + ')'; - } - - private static String getJsonStringToMaxLength(Object obj, int argCharLen) - { - Map args = new HashMap(); - args.put(JsonWriter.TYPE, false); - args.put(JsonWriter.SHORT_META_KEYS, true); - String arg = JsonWriter.objectToJson(obj, args); - if (arg.length() > argCharLen) - { - arg = arg.substring(0, argCharLen) + "..."; - } - return arg; - } - - /** - * Wrapper for unsafe, decouples direct usage of sun.misc.* package. - * @author Kai Hufenback - */ - static final class Unsafe - { - private final Object sunUnsafe; - private final Method allocateInstance; - - /** - * Constructs unsafe object, acting as a wrapper. - * @throws InvocationTargetException - */ - public Unsafe() throws InvocationTargetException - { - try - { - Constructor unsafeConstructor = classForName("sun.misc.Unsafe", MetaUtils.class.getClassLoader()).getDeclaredConstructor(); - unsafeConstructor.setAccessible(true); - sunUnsafe = unsafeConstructor.newInstance(); - allocateInstance = sunUnsafe.getClass().getMethod("allocateInstance", Class.class); - allocateInstance.setAccessible(true); - } - catch(Exception e) - { - throw new InvocationTargetException(e); - } - } - - /** - * Creates an object without invoking constructor or initializing variables. - * Be careful using this with JDK objects, like URL or ConcurrentHashMap this may bring your VM into troubles. - * @param clazz to instantiate - * @return allocated Object - */ - public Object allocateInstance(Class clazz) - { - try - { - return allocateInstance.invoke(sunUnsafe, clazz); - } - catch (IllegalAccessException e ) - { - String name = clazz == null ? "null" : clazz.getName(); - throw new JsonIoException("Unable to create instance of class: " + name, e); - } - catch (IllegalArgumentException e) - { - String name = clazz == null ? "null" : clazz.getName(); - throw new JsonIoException("Unable to create instance of class: " + name, e); - } - catch (InvocationTargetException e) - { - String name = clazz == null ? "null" : clazz.getName(); - throw new JsonIoException("Unable to create instance of class: " + name, e.getCause() != null ? e.getCause() : e); - } - } - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/ObjectResolver.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/ObjectResolver.java deleted file mode 100644 index 279771cc..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/ObjectResolver.java +++ /dev/null @@ -1,842 +0,0 @@ -package cn.lastwhisper.monitor.agent.json; - -import java.lang.reflect.*; -import java.util.*; - -/** - *

The ObjectResolver converts the raw Maps created from the JsonParser to Java - * objects (a graph of Java instances). The Maps have an optional type entry associated - * to them to indicate what Java peer instance to create. The reason type is optional - * is because it can be inferred in a couple instances. A non-primitive field that - * points to an object that is of the same type of the field, does not require the - * '@type' because it can be inferred from the field. This is not always the case. - * For example, if a Person field points to an Employee object (where Employee is a - * subclass of Person), then the resolver cannot create an instance of the field type - * (Person) because this is not the proper type. (It had an Employee record with more - * fields in this example). In this case, the writer recognizes that the instance type - * and field type are not the same and therefore it writes the @type. - *

- * A similar case as above occurs with specific array types. If there is a Person[] - * containing Person and Employee instances, then the Person instances will not have - * the '@type' but the employee instances will (because they are more derived than Person). - *

- * The resolver 'wires' the original object graph. It does this by replacing - * '@ref' values in the Maps with pointers (on the field of the associated instance of the - * Map) to the object that has the same ID. If the object has not yet been read, then - * an UnresolvedReference is created. These are back-patched at the end of the resolution - * process. UnresolvedReference keeps track of what field or array element the actual value - * should be stored within, and then locates the object (by id), and updates the appropriate - * value. - *

- * @author John DeRegnaucourt (jdereg@gmail.com) - *
- * Copyright (c) Cedar Software LLC - *

- * Licensed 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. - */ -public class ObjectResolver extends Resolver -{ - private final ClassLoader classLoader; - protected JsonReader.MissingFieldHandler missingFieldHandler; - - /** - * Constructor - * @param reader JsonReader instance being used - * @param classLoader ClassLoader that was set in the passed in 'options' arguments to JsonReader. - */ - protected ObjectResolver(JsonReader reader, ClassLoader classLoader) - { - super(reader); - this.classLoader = classLoader; - missingFieldHandler = reader.getMissingFieldHandler(); - } - - /** - * Walk the Java object fields and copy them from the JSON object to the Java object, performing - * any necessary conversions on primitives, or deep traversals for field assignments to other objects, - * arrays, Collections, or Maps. - * @param stack Stack (Deque) used for graph traversal. - * @param jsonObj a Map-of-Map representation of the current object being examined (containing all fields). - */ - public void traverseFields(final Deque> stack, final JsonObject jsonObj) - { - final Object javaMate = jsonObj.target; - final Iterator> i = jsonObj.entrySet().iterator(); - final Class cls = javaMate.getClass(); - - while (i.hasNext()) - { - Map.Entry e = i.next(); - String key = e.getKey(); - final Field field = MetaUtils.getField(cls, key); - Object rhs = e.getValue(); - if (field != null) - { - assignField(stack, jsonObj, field, rhs); - } - else if (missingFieldHandler != null) - { - handleMissingField(stack, jsonObj, rhs, key); - }//else no handler so ignor. - } - } - - /** - * Map Json Map object field to Java object field. - * - * @param stack Stack (Deque) used for graph traversal. - * @param jsonObj a Map-of-Map representation of the current object being examined (containing all fields). - * @param field a Java Field object representing where the jsonObj should be converted and stored. - * @param rhs the JSON value that will be converted and stored in the 'field' on the associated - * Java target object. - */ - protected void assignField(final Deque> stack, final JsonObject jsonObj, - final Field field, final Object rhs) - { - final Object target = jsonObj.target; - try - { - final Class fieldType = field.getType(); - if (rhs == null) - { // Logically clear field (allows null to be set against primitive fields, yielding their zero value. - if (fieldType.isPrimitive()) - { - field.set(target, MetaUtils.newPrimitiveWrapper(fieldType, "0")); - } - else - { - field.set(target, null); - } - return; - } - - // If there is a "tree" of objects (e.g, Map>), the subobjects may not have an - // @type on them, if the source of the JSON is from JSON.stringify(). Deep traverse the args and - // mark @type on the items within the Maps and Collections, based on the parameterized type (if it - // exists). - if (rhs instanceof JsonObject) - { - if (field.getGenericType() instanceof ParameterizedType) - { // Only JsonObject instances could contain unmarked objects. - markUntypedObjects(field.getGenericType(), rhs, MetaUtils.getDeepDeclaredFields(fieldType)); - } - - // Ensure .type field set on JsonObject - final JsonObject job = (JsonObject) rhs; - final String type = job.type; - if (type == null || type.isEmpty()) - { - job.setType(fieldType.getName()); - } - } - - Object special; - if (rhs == JsonParser.EMPTY_OBJECT) - { - final JsonObject jObj = new JsonObject(); - jObj.type = fieldType.getName(); - Object value = createJavaObjectInstance(fieldType, jObj); - field.set(target, value); - } - else if ((special = readIfMatching(rhs, fieldType, stack)) != null) - { - field.set(target, special); - } - else if (rhs.getClass().isArray()) - { // LHS of assignment is an [] field or RHS is an array and LHS is Object - final Object[] elements = (Object[]) rhs; - JsonObject jsonArray = new JsonObject(); - if (char[].class == fieldType) - { // Specially handle char[] because we are writing these - // out as UTF8 strings for compactness and speed. - if (elements.length == 0) - { - field.set(target, new char[]{}); - } - else - { - field.set(target, ((String) elements[0]).toCharArray()); - } - } - else - { - jsonArray.put("@items", elements); - createJavaObjectInstance(fieldType, jsonArray); - field.set(target, jsonArray.target); - stack.addFirst(jsonArray); - } - } - else if (rhs instanceof JsonObject) - { - final JsonObject jObj = (JsonObject) rhs; - final Long ref = jObj.getReferenceId(); - - if (ref != null) - { // Correct field references - final JsonObject refObject = getReferencedObj(ref); - - if (refObject.target != null) - { - field.set(target, refObject.target); - } - else - { - unresolvedRefs.add(new UnresolvedReference(jsonObj, field.getName(), ref)); - } - } - else - { // Assign ObjectMap's to Object (or derived) fields - field.set(target, createJavaObjectInstance(fieldType, jObj)); - if (!MetaUtils.isLogicalPrimitive(jObj.getTargetClass())) - { - stack.addFirst((JsonObject) rhs); - } - } - } - else - { - if (MetaUtils.isPrimitive(fieldType)) - { - field.set(target, MetaUtils.newPrimitiveWrapper(fieldType, rhs)); - } - else if (rhs instanceof String && "".equals(((String) rhs).trim()) && fieldType != String.class) - { // Allow "" to null out a non-String field - field.set(target, null); - } - else - { - field.set(target, rhs); - } - } - } - catch (Exception e) - { - String message = e.getClass().getSimpleName() + " setting field '" + field.getName() + "' on target: " + safeToString(target) + " with value: " + rhs; - if (MetaUtils.loadClassException != null) - { - message += " Caused by: " + MetaUtils.loadClassException + " (which created a LinkedHashMap instead of the desired class)"; - } - throw new JsonIoException(message, e); - } - } - - - /** - * Try to create an java object from the missing field. - * Mosly primitive types and jsonObject that contains @type attribute will - * be candidate for the missing field callback, others will be ignored. - * All missing field are stored for later notification - * - * @param stack Stack (Deque) used for graph traversal. - * @param jsonObj a Map-of-Map representation of the current object being examined (containing all fields). - * @param rhs the JSON value that will be converted and stored in the 'field' on the associated Java target object. - * @param missingField name of the missing field in the java object. - */ - protected void handleMissingField(final Deque> stack, final JsonObject jsonObj, final Object rhs, - final String missingField) - { - final Object target = jsonObj.target; - try - { - if (rhs == null) - { // Logically clear field (allows null to be set against primitive fields, yielding their zero value. - storeMissingField(target, missingField, null); - return; - } - - // we have a jsonobject with a type - Object special; - if (rhs == JsonParser.EMPTY_OBJECT) - { - storeMissingField(target, missingField, null); - } - else if ((special = readIfMatching(rhs, null, stack)) != null) - { - storeMissingField(target, missingField, special); - } - else if (rhs.getClass().isArray()) - { - // impossible to determine the array type. - storeMissingField(target, missingField, null); - } - else if (rhs instanceof JsonObject) - { - final JsonObject jObj = (JsonObject) rhs; - final Long ref = jObj.getReferenceId(); - - if (ref != null) - { // Correct field references - final JsonObject refObject = getReferencedObj(ref); - storeMissingField(target, missingField, refObject.target); - } - else - { // Assign ObjectMap's to Object (or derived) fields - // check that jObj as a type - if (jObj.getType() != null) - { - Object createJavaObjectInstance = createJavaObjectInstance(null, jObj); - if (!MetaUtils.isLogicalPrimitive(jObj.getTargetClass())) - { - stack.addFirst((JsonObject) rhs); - } - storeMissingField(target, missingField, createJavaObjectInstance); - } - else //no type found, just notify. - { - storeMissingField(target, missingField, null); - } - } - } - else - { - storeMissingField(target, missingField, rhs); - } - } - catch (Exception e) - { - String message = e.getClass().getSimpleName() + " missing field '" + missingField + "' on target: " - + safeToString(target) + " with value: " + rhs; - if (MetaUtils.loadClassException != null) - { - message += " Caused by: " + MetaUtils.loadClassException - + " (which created a LinkedHashMap instead of the desired class)"; - } - throw new JsonIoException(message, e); - } - } - - /** - * stores the missing field and their values to call back the handler at the end of the resolution, cause some - * reference may need to be resolved later. - */ - private void storeMissingField(Object target, String missingField, Object value) - { - missingFields.add(new Missingfields(target, missingField, value)); - } - - - /** - * @param o Object to turn into a String - * @return .toString() version of o or "null" if o is null. - */ - private static String safeToString(Object o) - { - if (o == null) - { - return "null"; - } - try - { - return o.toString(); - } - catch (Exception e) - { - return o.getClass().toString(); - } - } - - /** - * Process java.util.Collection and it's derivatives. Collections are written specially - * so that the serialization does not expose the Collection's internal structure, for - * example, a TreeSet. All entries are processed, except unresolved references, which - * are filled in later. For an indexable collection, the unresolved references are set - * back into the proper element location. For non-indexable collections (Sets), the - * unresolved references are added via .add(). - * @param jsonObj a Map-of-Map representation of the JSON input stream. - */ - protected void traverseCollection(final Deque> stack, final JsonObject jsonObj) - { - final Object[] items = jsonObj.getArray(); - if (items == null || items.length == 0) - { - return; - } - final Collection col = (Collection) jsonObj.target; - final boolean isList = col instanceof List; - int idx = 0; - - for (final Object element : items) - { - Object special; - if (element == null) - { - col.add(null); - } - else if (element == JsonParser.EMPTY_OBJECT) - { // Handles {} - col.add(new JsonObject()); - } - else if ((special = readIfMatching(element, null, stack)) != null) - { - col.add(special); - } - else if (element instanceof String || element instanceof Boolean || element instanceof Double || element instanceof Long) - { // Allow Strings, Booleans, Longs, and Doubles to be "inline" without Java object decoration (@id, @type, etc.) - col.add(element); - } - else if (element.getClass().isArray()) - { - final JsonObject jObj = new JsonObject(); - jObj.put("@items", element); - createJavaObjectInstance(Object.class, jObj); - col.add(jObj.target); - convertMapsToObjects(jObj); - } - else // if (element instanceof JsonObject) - { - final JsonObject jObj = (JsonObject) element; - final Long ref = jObj.getReferenceId(); - - if (ref != null) - { - JsonObject refObject = getReferencedObj(ref); - - if (refObject.target != null) - { - col.add(refObject.target); - } - else - { - unresolvedRefs.add(new UnresolvedReference(jsonObj, idx, ref)); - if (isList) - { // Indexable collection, so set 'null' as element for now - will be patched in later. - col.add(null); - } - } - } - else - { - createJavaObjectInstance(Object.class, jObj); - - if (!MetaUtils.isLogicalPrimitive(jObj.getTargetClass())) - { - convertMapsToObjects(jObj); - } - col.add(jObj.target); - } - } - idx++; - } - - jsonObj.remove("@items"); // Reduce memory required during processing - } - - /** - * Traverse the JsonObject associated to an array (of any type). Convert and - * assign the list of items in the JsonObject (stored in the @items field) - * to each array element. All array elements are processed excluding elements - * that reference an unresolved object. These are filled in later. - * - * @param stack a Stack (Deque) used to support graph traversal. - * @param jsonObj a Map-of-Map representation of the JSON input stream. - */ - protected void traverseArray(final Deque> stack, final JsonObject jsonObj) - { - final int len = jsonObj.getLength(); - if (len == 0) - { - return; - } - - final Class compType = jsonObj.getComponentType(); - - if (char.class == compType) - { - return; - } - - if (byte.class == compType) - { // Handle byte[] special for performance boost. - jsonObj.moveBytesToMate(); - jsonObj.clearArray(); - return; - } - - final boolean isPrimitive = MetaUtils.isPrimitive(compType); - final Object array = jsonObj.target; - final Object[] items = jsonObj.getArray(); - - for (int i=0; i < len; i++) - { - final Object element = items[i]; - - Object special; - if (element == null) - { - Array.set(array, i, null); - } - else if (element == JsonParser.EMPTY_OBJECT) - { // Use either explicitly defined type in ObjectMap associated to JSON, or array component type. - Object arrayElement = createJavaObjectInstance(compType, new JsonObject()); - Array.set(array, i, arrayElement); - } - else if ((special = readIfMatching(element, compType, stack)) != null) - { - Array.set(array, i, special); - } - else if (isPrimitive) - { // Primitive component type array - Array.set(array, i, MetaUtils.newPrimitiveWrapper(compType, element)); - } - else if (element.getClass().isArray()) - { // Array of arrays - if (char[].class == compType) - { // Specially handle char[] because we are writing these - // out as UTF-8 strings for compactness and speed. - Object[] jsonArray = (Object[]) element; - if (jsonArray.length == 0) - { - Array.set(array, i, new char[]{}); - } - else - { - final String value = (String) jsonArray[0]; - final int numChars = value.length(); - final char[] chars = new char[numChars]; - for (int j = 0; j < numChars; j++) - { - chars[j] = value.charAt(j); - } - Array.set(array, i, chars); - } - } - else - { - JsonObject jsonObject = new JsonObject(); - jsonObject.put("@items", element); - Array.set(array, i, createJavaObjectInstance(compType, jsonObject)); - stack.addFirst(jsonObject); - } - } - else if (element instanceof JsonObject) - { - JsonObject jsonObject = (JsonObject) element; - Long ref = jsonObject.getReferenceId(); - - if (ref != null) - { // Connect reference - JsonObject refObject = getReferencedObj(ref); - if (refObject.target != null) - { // Array element with reference to existing object - Array.set(array, i, refObject.target); - } - else - { // Array with a forward reference as an element - unresolvedRefs.add(new UnresolvedReference(jsonObj, i, ref)); - } - } - else - { // Convert JSON HashMap to Java Object instance and assign values - Object arrayElement = createJavaObjectInstance(compType, jsonObject); - Array.set(array, i, arrayElement); - if (!MetaUtils.isLogicalPrimitive(arrayElement.getClass())) - { // Skip walking primitives, primitive wrapper classes, Strings, and Classes - stack.addFirst(jsonObject); - } - } - } - else - { - if (element instanceof String && "".equals(((String) element).trim()) && compType != String.class && compType != Object.class) - { // Allow an entry of "" in the array to set the array element to null, *if* the array type is NOT String[] and NOT Object[] - Array.set(array, i, null); - } - else - { - Array.set(array, i, element); - } - } - } - jsonObj.clearArray(); - } - - /** - * Convert the passed in object (o) to a proper Java object. If the passed in object (o) has a custom reader - * associated to it, then have it convert the object. If there is no custom reader, then return null. - * @param o Object to read (convert). Will be either a JsonObject or a JSON primitive String, long, boolean, - * double, or null. - * @param compType Class destination type to which the passed in object should be converted to. - * @param stack a Stack (Deque) used to support graph traversal. - * @return Java object converted from the passed in object o, or if there is no custom reader. - */ - protected Object readIfMatching(final Object o, final Class compType, final Deque> stack) - { - if (o == null) - { - throw new JsonIoException("Bug in json-io, null must be checked before calling this method."); - } - - if (compType != null && notCustom(compType)) - { - return null; - } - - final boolean isJsonObject = o instanceof JsonObject; - if (!isJsonObject && compType == null) - { // If not a JsonObject (like a Long that represents a date, then compType must be set) - return null; - } - - Class c; - boolean needsType = false; - - // Set up class type to check against reader classes (specified as @type, or jObj.target, or compType) - if (isJsonObject) - { - JsonObject jObj = (JsonObject) o; - if (jObj.isReference()) - { - return null; - } - - if (jObj.target == null) - { // '@type' parameter used (not target instance) - String typeStr = null; - try - { - Object type = jObj.type; - if (type != null) - { - typeStr = (String) type; - c = MetaUtils.classForName((String) type, classLoader); - } - else - { - if (compType != null) - { - c = compType; - needsType = true; - } - else - { - return null; - } - } - createJavaObjectInstance(c, jObj); - } - catch(Exception e) - { - throw new JsonIoException("Class listed in @type [" + typeStr + "] is not found", e); - } - } - else - { // Type inferred from target object - c = jObj.target.getClass(); - } - } - else - { - c = compType; - } - - if (notCustom(c)) - { - return null; - } - - JsonReader.JsonClassReaderBase closestReader = getCustomReader(c); - - if (closestReader == null) - { - return null; - } - - if (needsType) - { - ((JsonObject)o).setType(c.getName()); - } - - Object read; - if (closestReader instanceof JsonReader.JsonClassReaderEx) - { - read = ((JsonReader.JsonClassReaderEx)closestReader).read(o, stack, getReader().getArgs()); - } - else - { - read = ((JsonReader.JsonClassReader)closestReader).read(o, stack); - } - return read; - } - - private static void markUntypedObjects(final Type type, final Object rhs, final Map classFields) - { - final Deque stack = new ArrayDeque(); - stack.addFirst(new Object[] {type, rhs}); - - while (!stack.isEmpty()) - { - Object[] item = stack.removeFirst(); - final Type t = (Type) item[0]; - final Object instance = item[1]; - if (t instanceof ParameterizedType) - { - final Class clazz = getRawType(t); - final ParameterizedType pType = (ParameterizedType)t; - final Type[] typeArgs = pType.getActualTypeArguments(); - - if (typeArgs == null || typeArgs.length < 1 || clazz == null) - { - continue; - } - - stampTypeOnJsonObject(instance, t); - - if (Map.class.isAssignableFrom(clazz)) - { - Map map = (Map) instance; - if (!map.containsKey("@keys") && !map.containsKey("@items") && map instanceof JsonObject) - { // Maps created in Javascript will come over without @keys / @items. - convertMapToKeysItems((JsonObject) map); - } - - Object[] keys = (Object[])map.get("@keys"); - getTemplateTraverseWorkItem(stack, keys, typeArgs[0]); - - Object[] items = (Object[])map.get("@items"); - getTemplateTraverseWorkItem(stack, items, typeArgs[1]); - } - else if (Collection.class.isAssignableFrom(clazz)) - { - if (instance instanceof Object[]) - { - Object[] array = (Object[]) instance; - for (int i=0; i < array.length; i++) - { - Object vals = array[i]; - stack.addFirst(new Object[]{t, vals}); - - if (vals instanceof JsonObject) - { - stack.addFirst(new Object[]{t, vals}); - } - else if (vals instanceof Object[]) - { - JsonObject coll = new JsonObject(); - coll.type = clazz.getName(); - List items = Arrays.asList((Object[]) vals); - coll.put("@items", items.toArray()); - stack.addFirst(new Object[]{t, items}); - array[i] = coll; - } - else - { - stack.addFirst(new Object[]{t, vals}); - } - } - } - else if (instance instanceof Collection) - { - final Collection col = (Collection)instance; - for (Object o : col) - { - stack.addFirst(new Object[]{typeArgs[0], o}); - } - } - else if (instance instanceof JsonObject) - { - final JsonObject jObj = (JsonObject) instance; - final Object[] array = jObj.getArray(); - if (array != null) - { - for (Object o : array) - { - stack.addFirst(new Object[]{typeArgs[0], o}); - } - } - } - } - else - { - if (instance instanceof JsonObject) - { - final JsonObject jObj = (JsonObject) instance; - - for (Map.Entry entry : jObj.entrySet()) - { - final String fieldName = entry.getKey(); - if (!fieldName.startsWith("this$")) - { - // TODO: If more than one type, need to associate correct typeArgs entry to value - Field field = classFields.get(fieldName); - - if (field != null && (field.getType().getTypeParameters().length > 0 || field.getGenericType() instanceof TypeVariable)) - { - stack.addFirst(new Object[]{typeArgs[0], entry.getValue()}); - } - } - } - } - } - } - else - { - stampTypeOnJsonObject(instance, t); - } - } - } - - private static void getTemplateTraverseWorkItem(final Deque stack, final Object[] items, final Type type) - { - if (items == null || items.length < 1) - { - return; - } - Class rawType = getRawType(type); - if (rawType != null && Collection.class.isAssignableFrom(rawType)) - { - stack.add(new Object[]{type, items}); - } - else - { - for (Object o : items) - { - stack.add(new Object[]{type, o}); - } - } - } - - // Mark 'type' on JsonObject when the type is missing and it is a 'leaf' - // node (no further subtypes in it's parameterized type definition) - private static void stampTypeOnJsonObject(final Object o, final Type t) - { - Class clazz = t instanceof Class ? (Class)t : getRawType(t); - - if (o instanceof JsonObject && clazz != null) - { - JsonObject jObj = (JsonObject) o; - if ((jObj.type == null || jObj.type.isEmpty()) && jObj.target == null) - { - jObj.type = clazz.getName(); - } - } - } - - /** - * Given the passed in Type t, return the raw type of it, if the passed in value is a ParameterizedType. - * @param t Type to attempt to get raw type from. - * @return Raw type obtained from the passed in parameterized type or null if T is not a ParameterizedType - */ - public static Class getRawType(final Type t) - { - if (t instanceof ParameterizedType) - { - ParameterizedType pType = (ParameterizedType) t; - - if (pType.getRawType() instanceof Class) - { - return (Class) pType.getRawType(); - } - } - return null; - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/Readers.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/Readers.java deleted file mode 100644 index 97459f03..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/Readers.java +++ /dev/null @@ -1,838 +0,0 @@ -package cn.lastwhisper.monitor.agent.json; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Timestamp; -import java.util.Calendar; -import java.util.Date; -import java.util.Deque; -import java.util.LinkedHashMap; -import java.util.Locale; -import java.util.Map; -import java.util.TimeZone; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * All custom readers for json-io subclass this class. Special readers are not needed for handling - * user-defined classes. However, special readers are built/supplied by json-io for many of the - * primitive types and other JDK classes simply to allow for a more concise form. - * - * @author John DeRegnaucourt (jdereg@gmail.com) - *
- * Copyright (c) Cedar Software LLC - *

- * Licensed 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.* - */ -public class Readers -{ - private Readers () {} - - private static final String DAYS = "(monday|mon|tuesday|tues|tue|wednesday|wed|thursday|thur|thu|friday|fri|saturday|sat|sunday|sun)"; // longer before shorter matters - private static final String MOS = "(January|Jan|February|Feb|March|Mar|April|Apr|May|June|Jun|July|Jul|August|Aug|September|Sept|Sep|October|Oct|November|Nov|December|Dec)"; - private static final Pattern datePattern1 = Pattern.compile("(\\d{4})[./-](\\d{1,2})[./-](\\d{1,2})"); - private static final Pattern datePattern2 = Pattern.compile("(\\d{1,2})[./-](\\d{1,2})[./-](\\d{4})"); - private static final Pattern datePattern3 = Pattern.compile(MOS + "[ ]*[,]?[ ]*(\\d{1,2})(st|nd|rd|th|)[ ]*[,]?[ ]*(\\d{4})", Pattern.CASE_INSENSITIVE); - private static final Pattern datePattern4 = Pattern.compile("(\\d{1,2})(st|nd|rd|th|)[ ]*[,]?[ ]*" + MOS + "[ ]*[,]?[ ]*(\\d{4})", Pattern.CASE_INSENSITIVE); - private static final Pattern datePattern5 = Pattern.compile("(\\d{4})[ ]*[,]?[ ]*" + MOS + "[ ]*[,]?[ ]*(\\d{1,2})(st|nd|rd|th|)", Pattern.CASE_INSENSITIVE); - private static final Pattern datePattern6 = Pattern.compile(DAYS + "[ ]+" + MOS + "[ ]+(\\d{1,2})[ ]+(\\d{2}:\\d{2}:\\d{2})[ ]+[A-Z]{1,4}\\s+(\\d{4})", Pattern.CASE_INSENSITIVE); - private static final Pattern timePattern1 = Pattern.compile("(\\d{2})[.:](\\d{2})[.:](\\d{2})[.](\\d{1,10})([+-]\\d{2}[:]?\\d{2}|Z)?"); - private static final Pattern timePattern2 = Pattern.compile("(\\d{2})[.:](\\d{2})[.:](\\d{2})([+-]\\d{2}[:]?\\d{2}|Z)?"); - private static final Pattern timePattern3 = Pattern.compile("(\\d{2})[.:](\\d{2})([+-]\\d{2}[:]?\\d{2}|Z)?"); - private static final Pattern dayPattern = Pattern.compile(DAYS, Pattern.CASE_INSENSITIVE); - private static final Map months = new LinkedHashMap(); - - static - { - // Month name to number map - months.put("jan", "1"); - months.put("january", "1"); - months.put("feb", "2"); - months.put("february", "2"); - months.put("mar", "3"); - months.put("march", "3"); - months.put("apr", "4"); - months.put("april", "4"); - months.put("may", "5"); - months.put("jun", "6"); - months.put("june", "6"); - months.put("jul", "7"); - months.put("july", "7"); - months.put("aug", "8"); - months.put("august", "8"); - months.put("sep", "9"); - months.put("sept", "9"); - months.put("september", "9"); - months.put("oct", "10"); - months.put("october", "10"); - months.put("nov", "11"); - months.put("november", "11"); - months.put("dec", "12"); - months.put("december", "12"); - } - - public static class TimeZoneReader implements JsonReader.JsonClassReaderEx - { - public Object read(Object o, Deque> stack, Map args) - { - JsonObject jObj = (JsonObject)o; - Object zone = jObj.get("zone"); - if (zone == null) - { - throw new JsonIoException("java.util.TimeZone must specify 'zone' field"); - } - jObj.target = TimeZone.getTimeZone((String) zone); - return jObj.target; - } - } - - public static class LocaleReader implements JsonReader.JsonClassReaderEx - { - public Object read(Object o, Deque> stack, Map args) - { - JsonObject jObj = (JsonObject) o; - Object language = jObj.get("language"); - if (language == null) - { - throw new JsonIoException("java.util.Locale must specify 'language' field"); - } - Object country = jObj.get("country"); - Object variant = jObj.get("variant"); - if (country == null) - { - jObj.target = new Locale((String) language); - return jObj.target; - } - if (variant == null) - { - jObj.target = new Locale((String) language, (String) country); - return jObj.target; - } - - jObj.target = new Locale((String) language, (String) country, (String) variant); - return jObj.target; - } - } - - public static class CalendarReader implements JsonReader.JsonClassReaderEx - { - public Object read(Object o, Deque> stack, Map args) - { - String time = null; - try - { - JsonObject jObj = (JsonObject) o; - time = (String) jObj.get("time"); - if (time == null) - { - throw new JsonIoException("Calendar missing 'time' field"); - } - Date date = MetaUtils.dateFormat.get().parse(time); - Class c; - if (jObj.getTarget() != null) - { - c = jObj.getTarget().getClass(); - } - else - { - Object type = jObj.type; - c = classForName((String) type, (ClassLoader)args.get(JsonReader.CLASSLOADER)); - } - - Calendar calendar = (Calendar) newInstance(c, jObj); - calendar.setTime(date); - jObj.setTarget(calendar); - String zone = (String) jObj.get("zone"); - if (zone != null) - { - calendar.setTimeZone(TimeZone.getTimeZone(zone)); - } - return calendar; - } - catch(Exception e) - { - throw new JsonIoException("Failed to parse calendar, time: " + time); - } - } - } - - public static class DateReader implements JsonReader.JsonClassReaderEx - { - public Object read(Object o, Deque> stack, Map args) - { - if (o instanceof Long) - { - return new Date((Long) o); - } - else if (o instanceof String) - { - return parseDate((String) o); - } - else if (o instanceof JsonObject) - { - JsonObject jObj = (JsonObject) o; - Object val = jObj.get("value"); - if (val instanceof Long) - { - return new Date((Long) val); - } - else if (val instanceof String) - { - return parseDate((String) val); - } - throw new JsonIoException("Unable to parse date: " + o); - } - else - { - throw new JsonIoException("Unable to parse date, encountered unknown object: " + o); - } - } - - private Date parseDate(String dateStr) - { - dateStr = dateStr.trim(); - if (dateStr.isEmpty()) - { - return null; - } - - // Determine which date pattern (Matcher) to use - Matcher matcher = datePattern1.matcher(dateStr); - - String year, month = null, day, mon = null, remains; - - if (matcher.find()) - { - year = matcher.group(1); - month = matcher.group(2); - day = matcher.group(3); - remains = matcher.replaceFirst(""); - } - else - { - matcher = datePattern2.matcher(dateStr); - if (matcher.find()) - { - month = matcher.group(1); - day = matcher.group(2); - year = matcher.group(3); - remains = matcher.replaceFirst(""); - } - else - { - matcher = datePattern3.matcher(dateStr); - if (matcher.find()) - { - mon = matcher.group(1); - day = matcher.group(2); - year = matcher.group(4); - remains = matcher.replaceFirst(""); - } - else - { - matcher = datePattern4.matcher(dateStr); - if (matcher.find()) - { - day = matcher.group(1); - mon = matcher.group(3); - year = matcher.group(4); - remains = matcher.replaceFirst(""); - } - else - { - matcher = datePattern5.matcher(dateStr); - if (matcher.find()) - { - year = matcher.group(1); - mon = matcher.group(2); - day = matcher.group(3); - remains = matcher.replaceFirst(""); - } - else - { - matcher = datePattern6.matcher(dateStr); - if (!matcher.find()) - { - throw new JsonIoException("Unable to parse: " + dateStr); - } - year = matcher.group(5); - mon = matcher.group(2); - day = matcher.group(3); - remains = matcher.group(4); - } - } - } - } - } - - if (mon != null) - { // Month will always be in Map, because regex forces this. - month = months.get(mon.trim().toLowerCase()); - } - - // Determine which date pattern (Matcher) to use - String hour = null, min = null, sec = "00", milli = "0", tz = null; - remains = remains.trim(); - matcher = timePattern1.matcher(remains); - if (matcher.find()) - { - hour = matcher.group(1); - min = matcher.group(2); - sec = matcher.group(3); - milli = matcher.group(4); - if (matcher.groupCount() > 4) - { - tz = matcher.group(5); - } - } - else - { - matcher = timePattern2.matcher(remains); - if (matcher.find()) - { - hour = matcher.group(1); - min = matcher.group(2); - sec = matcher.group(3); - if (matcher.groupCount() > 3) - { - tz = matcher.group(4); - } - } - else - { - matcher = timePattern3.matcher(remains); - if (matcher.find()) - { - hour = matcher.group(1); - min = matcher.group(2); - if (matcher.groupCount() > 2) - { - tz = matcher.group(3); - } - } - else - { - matcher = null; - } - } - } - - if (matcher != null) - { - remains = matcher.replaceFirst(""); - } - - // Clear out day of week (mon, tue, wed, ...) - if (remains != null && remains.length() > 0) - { - Matcher dayMatcher = dayPattern.matcher(remains); - if (dayMatcher.find()) - { - remains = dayMatcher.replaceFirst("").trim(); - } - } - if (remains != null && remains.length() > 0) - { - remains = remains.trim(); - if (!remains.equals(",") && (!remains.equals("T"))) - { - throw new JsonIoException("Issue parsing data/time, other characters present: " + remains); - } - } - - Calendar c = Calendar.getInstance(); - c.clear(); - if (tz != null) - { - if ("z".equalsIgnoreCase(tz)) - { - c.setTimeZone(TimeZone.getTimeZone("GMT")); - } - else - { - c.setTimeZone(TimeZone.getTimeZone("GMT" + tz)); - } - } - - // Regex prevents these from ever failing to parse - int y = Integer.parseInt(year); - int m = Integer.parseInt(month) - 1; // months are 0-based - int d = Integer.parseInt(day); - - if (m < 0 || m > 11) - { - throw new JsonIoException("Month must be between 1 and 12 inclusive, date: " + dateStr); - } - if (d < 1 || d > 31) - { - throw new JsonIoException("Day must be between 1 and 31 inclusive, date: " + dateStr); - } - - if (matcher == null) - { // no [valid] time portion - c.set(y, m, d); - } - else - { - // Regex prevents these from ever failing to parse. - int h = Integer.parseInt(hour); - int mn = Integer.parseInt(min); - int s = Integer.parseInt(sec); - int ms = Integer.parseInt(milli); - - if (h > 23) - { - throw new JsonIoException("Hour must be between 0 and 23 inclusive, time: " + dateStr); - } - if (mn > 59) - { - throw new JsonIoException("Minute must be between 0 and 59 inclusive, time: " + dateStr); - } - if (s > 59) - { - throw new JsonIoException("Second must be between 0 and 59 inclusive, time: " + dateStr); - } - - // regex enforces millis to number - c.set(y, m, d, h, mn, s); - c.set(Calendar.MILLISECOND, ms); - } - return c.getTime(); - } - } - - public static class SqlDateReader extends DateReader - { - public Object read(Object o, Deque> stack, Map args) - { - return new java.sql.Date(((Date) super.read(o, stack, args)).getTime()); - } - } - - public static class StringReader implements JsonReader.JsonClassReaderEx - { - public Object read(Object o, Deque> stack, Map args) - { - if (o instanceof String) - { - return o; - } - - if (MetaUtils.isPrimitive(o.getClass())) - { - return o.toString(); - } - - JsonObject jObj = (JsonObject) o; - if (jObj.containsKey("value")) - { - jObj.target = jObj.get("value"); - return jObj.target; - } - throw new JsonIoException("String missing 'value' field"); - } - } - - public static class ClassReader implements JsonReader.JsonClassReaderEx - { - public Object read(Object o, Deque> stack, Map args) - { - if (o instanceof String) - { - return classForName((String) o, (ClassLoader)args.get(JsonReader.CLASSLOADER)); - } - - JsonObject jObj = (JsonObject) o; - if (jObj.containsKey("value")) - { - jObj.target = classForName((String) jObj.get("value"), (ClassLoader)args.get(JsonReader.CLASSLOADER)); - return jObj.target; - } - throw new JsonIoException("Class missing 'value' field"); - } - } - - public static class AtomicBooleanReader implements JsonReader.JsonClassReaderEx - { - public Object read(Object o, Deque> stack, Map args) - { - Object value = o; - value = getValueFromJsonObject(o, value, "AtomicBoolean"); - - if (value instanceof String) - { - String state = (String) value; - if ("".equals(state.trim())) - { // special case - return null; - } - return new AtomicBoolean("true".equalsIgnoreCase(state)); - } - else if (value instanceof Boolean) - { - return new AtomicBoolean((Boolean) value); - } - else if (value instanceof Number && !(value instanceof Double) && !(value instanceof Float)) - { - return new AtomicBoolean(((Number)value).longValue() != 0); - } - throw new JsonIoException("Unknown value in JSON assigned to AtomicBoolean, value type = " + value.getClass().getName()); - } - } - - public static class AtomicIntegerReader implements JsonReader.JsonClassReaderEx - { - public Object read(Object o, Deque> stack, Map args) - { - Object value = o; - value = getValueFromJsonObject(o, value, "AtomicInteger"); - - if (value instanceof String) - { - String num = (String) value; - if ("".equals(num.trim())) - { // special case - return null; - } - return new AtomicInteger(Integer.parseInt(MetaUtils.removeLeadingAndTrailingQuotes(num))); - } - else if (value instanceof Number && !(value instanceof Double) && !(value instanceof Float)) - { - return new AtomicInteger(((Number)value).intValue()); - } - throw new JsonIoException("Unknown value in JSON assigned to AtomicInteger, value type = " + value.getClass().getName()); - } - } - - public static class AtomicLongReader implements JsonReader.JsonClassReaderEx - { - public Object read(Object o, Deque> stack, Map args) - { - Object value = o; - value = getValueFromJsonObject(o, value, "AtomicLong"); - - if (value instanceof String) - { - String num = (String) value; - if ("".equals(num.trim())) - { // special case - return null; - } - return new AtomicLong(Long.parseLong(MetaUtils.removeLeadingAndTrailingQuotes(num))); - } - else if (value instanceof Number && !(value instanceof Double) && !(value instanceof Float)) - { - return new AtomicLong(((Number)value).longValue()); - } - throw new JsonIoException("Unknown value in JSON assigned to AtomicLong, value type = " + value.getClass().getName()); - } - } - - private static Object getValueFromJsonObject(Object o, Object value, String typeName) - { - if (o instanceof JsonObject) - { - JsonObject jObj = (JsonObject) o; - if (jObj.containsKey("value")) - { - value = jObj.get("value"); - } - else - { - throw new JsonIoException(typeName + " defined as JSON {} object, missing 'value' field"); - } - } - return value; - } - - public static class BigIntegerReader implements JsonReader.JsonClassReaderEx - { - public Object read(Object o, Deque> stack, Map args) - { - JsonObject jObj = null; - Object value = o; - if (o instanceof JsonObject) - { - jObj = (JsonObject) o; - if (jObj.containsKey("value")) - { - value = jObj.get("value"); - } - else - { - throw new JsonIoException("BigInteger missing 'value' field"); - } - } - - if (value instanceof JsonObject) - { - JsonObject valueObj = (JsonObject)value; - if ("java.math.BigDecimal".equals(valueObj.type)) - { - BigDecimalReader reader = new BigDecimalReader(); - value = reader.read(value, stack, args); - } - else if ("java.math.BigInteger".equals(valueObj.type)) - { - value = read(value, stack, args); - } - else - { - return bigIntegerFrom(valueObj.get("value")); - } - } - - BigInteger x = bigIntegerFrom(value); - if (jObj != null) - { - jObj.target = x; - } - - return x; - } - } - - /** - * @param value to be converted to BigInteger. Can be a null which will return null. Can be - * BigInteger in which case it will be returned as-is. Can also be String, BigDecimal, - * Boolean (which will be returned as BigInteger.ZERO or .ONE), byte, short, int, long, float, - * or double. If an unknown type is passed in, an exception will be thrown. - * @return a BigInteger from the given input. A best attempt will be made to support - * as many input types as possible. For example, if the input is a Boolean, a BigInteger of - * 1 or 0 will be returned. If the input is a String "", a null will be returned. If the - * input is a Double, Float, or BigDecimal, a BigInteger will be returned that retains the - * integer portion (fractional part is dropped). The input can be a Byte, Short, Integer, - * or Long. - */ - public static BigInteger bigIntegerFrom(Object value) - { - if (value == null) - { - return null; - } - else if (value instanceof BigInteger) - { - return (BigInteger) value; - } - else if (value instanceof String) - { - String s = (String) value; - if ("".equals(s.trim())) - { // Allows "" to be used to assign null to BigInteger field. - return null; - } - try - { - return new BigInteger(MetaUtils.removeLeadingAndTrailingQuotes(s)); - } - catch (Exception e) - { - throw new JsonIoException("Could not parse '" + value + "' as BigInteger.", e); - } - } - else if (value instanceof BigDecimal) - { - BigDecimal bd = (BigDecimal) value; - return bd.toBigInteger(); - } - else if (value instanceof Boolean) - { - return (Boolean) value ? BigInteger.ONE : BigInteger.ZERO; - } - else if (value instanceof Double || value instanceof Float) - { - return new BigDecimal(((Number)value).doubleValue()).toBigInteger(); - } - else if (value instanceof Long || value instanceof Integer || - value instanceof Short || value instanceof Byte) - { - return new BigInteger(value.toString()); - } - throw new JsonIoException("Could not convert value: " + value.toString() + " to BigInteger."); - } - - public static class BigDecimalReader implements JsonReader.JsonClassReaderEx - { - public Object read(Object o, Deque> stack, Map args) - { - JsonObject jObj = null; - Object value = o; - if (o instanceof JsonObject) - { - jObj = (JsonObject) o; - if (jObj.containsKey("value")) - { - value = jObj.get("value"); - } - else - { - throw new JsonIoException("BigDecimal missing 'value' field"); - } - } - - if (value instanceof JsonObject) - { - JsonObject valueObj = (JsonObject)value; - if ("java.math.BigInteger".equals(valueObj.type)) - { - BigIntegerReader reader = new BigIntegerReader(); - value = reader.read(value, stack, args); - } - else if ("java.math.BigDecimal".equals(valueObj.type)) - { - value = read(value, stack, args); - } - else - { - return bigDecimalFrom(valueObj.get("value")); - } - } - - BigDecimal x = bigDecimalFrom(value); - if (jObj != null) - { - jObj.target = x; - } - return x; - } - } - - /** - * @param value to be converted to BigDecimal. Can be a null which will return null. Can be - * BigDecimal in which case it will be returned as-is. Can also be String, BigInteger, - * Boolean (which will be returned as BigDecimal.ZERO or .ONE), byte, short, int, long, float, - * or double. If an unknown type is passed in, an exception will be thrown. - * - * @return a BigDecimal from the given input. A best attempt will be made to support - * as many input types as possible. For example, if the input is a Boolean, a BigDecimal of - * 1 or 0 will be returned. If the input is a String "", a null will be returned. The input - * can be a Byte, Short, Integer, Long, or BigInteger. - */ - public static BigDecimal bigDecimalFrom(Object value) - { - if (value == null) - { - return null; - } - else if (value instanceof BigDecimal) - { - return (BigDecimal) value; - } - else if (value instanceof String) - { - String s = (String) value; - if ("".equals(s.trim())) - { - return null; - } - try - { - return new BigDecimal(MetaUtils.removeLeadingAndTrailingQuotes(s)); - } - catch (Exception e) - { - throw new JsonIoException("Could not parse '" + s + "' as BigDecimal.", e); - } - } - else if (value instanceof BigInteger) - { - return new BigDecimal((BigInteger) value); - } - else if (value instanceof Boolean) - { - return (Boolean) value ? BigDecimal.ONE : BigDecimal.ZERO; - } - else if (value instanceof Long || value instanceof Integer || value instanceof Double || - value instanceof Short || value instanceof Byte || value instanceof Float) - { - return new BigDecimal(value.toString()); - } - throw new JsonIoException("Could not convert value: " + value.toString() + " to BigInteger."); - } - - public static class StringBuilderReader implements JsonReader.JsonClassReaderEx - { - public Object read(Object o, Deque> stack, Map args) - { - if (o instanceof String) - { - return new StringBuilder((String) o); - } - - JsonObject jObj = (JsonObject) o; - if (jObj.containsKey("value")) - { - jObj.target = new StringBuilder((String) jObj.get("value")); - return jObj.target; - } - throw new JsonIoException("StringBuilder missing 'value' field"); - } - } - - public static class StringBufferReader implements JsonReader.JsonClassReaderEx - { - public Object read(Object o, Deque> stack, Map args) - { - if (o instanceof String) - { - return new StringBuffer((String) o); - } - - JsonObject jObj = (JsonObject) o; - if (jObj.containsKey("value")) - { - jObj.target = new StringBuffer((String) jObj.get("value")); - return jObj.target; - } - throw new JsonIoException("StringBuffer missing 'value' field"); - } - } - - public static class TimestampReader implements JsonReader.JsonClassReaderEx - { - public Object read(Object o, Deque> stack, Map args) - { - JsonObject jObj = (JsonObject) o; - Object time = jObj.get("time"); - if (time == null) - { - throw new JsonIoException("java.sql.Timestamp must specify 'time' field"); - } - Object nanos = jObj.get("nanos"); - if (nanos == null) - { - jObj.target = new Timestamp(Long.valueOf((String) time)); - return jObj.target; - } - - Timestamp tstamp = new Timestamp(Long.valueOf((String) time)); - tstamp.setNanos(Integer.valueOf((String) nanos)); - jObj.target = tstamp; - return jObj.target; - } - } - - // ========== Maintain dependency knowledge in once place, down here ========= - static Class classForName(String name, ClassLoader classLoader) - { - return MetaUtils.classForName(name, classLoader); - } - - static Object newInstance(Class c, JsonObject jsonObject) - { - return JsonReader.newInstance(c, jsonObject); - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/Resolver.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/Resolver.java deleted file mode 100644 index 71de7f0c..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/Resolver.java +++ /dev/null @@ -1,647 +0,0 @@ -package cn.lastwhisper.monitor.agent.json; - -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.util.*; - -//import com.cedarsoftware.util.io.JsonReader.MissingFieldHandler; - -/** - * This class is used to convert a source of Java Maps that were created from - * the JsonParser. These are in 'raw' form with no 'pointers'. This code will - * reconstruct the 'shape' of the graph by connecting @ref's to @ids. - * - * The subclasses that override this class can build an object graph using Java - * classes or a Map-of-Map representation. In both cases, the @ref value will - * be replaced with the Object (or Map) that had the corresponding @id. - * - * @author John DeRegnaucourt (jdereg@gmail.com) - *
- * Copyright (c) Cedar Software LLC - *

- * Licensed 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.* - */ -abstract class Resolver -{ - final Collection unresolvedRefs = new ArrayList(); - protected final JsonReader reader; - private static final NullClass nullReader = new NullClass(); - final Map readerCache = new HashMap(); - private final Collection prettyMaps = new ArrayList(); - private final boolean useMaps; - private final Object unknownClass; - private final boolean failOnUnknownType; - private final static Map coercedTypes = new LinkedHashMap(); - // store the missing field found during deserialization to notify any client after the complete resolution is done - protected final Collection missingFields = new ArrayList(); - - static { - coercedTypes.put("java.util.Arrays$ArrayList", ArrayList.class); - coercedTypes.put("java.util.LinkedHashMap$LinkedKeySet", LinkedHashSet.class); - coercedTypes.put("java.util.LinkedHashMap$LinkedValues", ArrayList.class); - coercedTypes.put("java.util.HashMap$KeySet", HashSet.class); - coercedTypes.put("java.util.HashMap$Values", ArrayList.class); - coercedTypes.put("java.util.TreeMap$KeySet", TreeSet.class); - coercedTypes.put("java.util.TreeMap$Values", ArrayList.class); - coercedTypes.put("java.util.concurrent.ConcurrentHashMap$KeySet", LinkedHashSet.class); - coercedTypes.put("java.util.concurrent.ConcurrentHashMap$KeySetView", LinkedHashSet.class); - coercedTypes.put("java.util.concurrent.ConcurrentHashMap$Values", ArrayList.class); - coercedTypes.put("java.util.concurrent.ConcurrentHashMap$ValuesView", ArrayList.class); - coercedTypes.put("java.util.concurrent.ConcurrentSkipListMap$KeySet", LinkedHashSet.class); - coercedTypes.put("java.util.concurrent.ConcurrentSkipListMap$Values", ArrayList.class); - coercedTypes.put("java.util.IdentityHashMap$KeySet", LinkedHashSet.class); - coercedTypes.put("java.util.IdentityHashMap$Values", ArrayList.class); - } - - /** - * UnresolvedReference is created to hold a logical pointer to a reference that - * could not yet be loaded, as the @ref appears ahead of the referenced object's - * definition. This can point to a field reference or an array/Collection element reference. - */ - static final class UnresolvedReference - { - private final JsonObject referencingObj; - private String field; - private final long refId; - private int index = -1; - - UnresolvedReference(JsonObject referrer, String fld, long id) - { - referencingObj = referrer; - field = fld; - refId = id; - } - - UnresolvedReference(JsonObject referrer, int idx, long id) - { - referencingObj = referrer; - index = idx; - refId = id; - } - } - - /** - * stores missing fields information to notify client after the complete deserialization resolution - */ - protected static class Missingfields - { - private Object target; - private String fieldName; - private Object value; - - public Missingfields(Object target, String fieldName, Object value) - { - this.target = target; - this.fieldName = fieldName; - this.value = value; - } - } - - /** - * Dummy place-holder class exists only because ConcurrentHashMap cannot contain a - * null value. Instead, singleton instance of this class is placed where null values - * are needed. - */ - private static final class NullClass implements JsonReader.JsonClassReaderBase { } - - protected Resolver(JsonReader reader) - { - this.reader = reader; - Map optionalArgs = reader.getArgs(); - optionalArgs.put(JsonReader.OBJECT_RESOLVER, this); - useMaps = Boolean.TRUE.equals(optionalArgs.get(JsonReader.USE_MAPS)); - unknownClass = optionalArgs.containsKey(JsonReader.UNKNOWN_OBJECT) ? optionalArgs.get(JsonReader.UNKNOWN_OBJECT) : null; - failOnUnknownType = Boolean.TRUE.equals(optionalArgs.get(JsonReader.FAIL_ON_UNKNOWN_TYPE)); - } - - protected JsonReader getReader() - { - return reader; - } - - /** - * Walk a JsonObject (Map of String keys to values) and return the - * Java object equivalent filled in as best as possible (everything - * except unresolved reference fields or unresolved array/collection elements). - * - * @param root JsonObject reference to a Map-of-Maps representation of the JSON - * input after it has been completely read. - * @return Properly constructed, typed, Java object graph built from a Map - * of Maps representation (JsonObject root). - */ - protected Object convertMapsToObjects(final JsonObject root) - { - final Deque> stack = new ArrayDeque>(); - stack.addFirst(root); - - while (!stack.isEmpty()) - { - final JsonObject jsonObj = stack.removeFirst(); - - if (jsonObj.isArray()) - { - traverseArray(stack, jsonObj); - } - else if (jsonObj.isCollection()) - { - traverseCollection(stack, jsonObj); - } - else if (jsonObj.isMap()) - { - traverseMap(stack, jsonObj); - } - else - { - Object special; - if ((special = readIfMatching(jsonObj, null, stack)) != null) - { - jsonObj.target = special; - } - else - { - traverseFields(stack, jsonObj); - } - } - } - return root.target; - } - - protected abstract Object readIfMatching(final Object o, final Class compType, final Deque> stack); - - public abstract void traverseFields(Deque> stack, JsonObject jsonObj); - - protected abstract void traverseCollection(Deque> stack, JsonObject jsonObj); - - protected abstract void traverseArray(Deque> stack, JsonObject jsonObj); - - protected void cleanup() - { - patchUnresolvedReferences(); - rehashMaps(); - reader.getObjectsRead().clear(); - unresolvedRefs.clear(); - prettyMaps.clear(); - readerCache.clear(); - handleMissingFields(); - } - - // calls the missing field handler if any for each recorded missing field. - private void handleMissingFields() - { - JsonReader.MissingFieldHandler missingFieldHandler = reader.getMissingFieldHandler(); - if (missingFieldHandler != null) - { - for (Missingfields mf : missingFields) - { - missingFieldHandler.fieldMissing(mf.target, mf.fieldName, mf.value); - } - }//else no handler so ignore. - } - - /** - * Process java.util.Map and it's derivatives. These can be written specially - * so that the serialization would not expose the derivative class internals - * (internal fields of TreeMap for example). - * - * @param stack a Stack (Deque) used to support graph traversal. - * @param jsonObj a Map-of-Map representation of the JSON input stream. - */ - protected void traverseMap(Deque> stack, JsonObject jsonObj) - { - // Convert @keys to a Collection of Java objects. - convertMapToKeysItems(jsonObj); - final Object[] keys = (Object[]) jsonObj.get("@keys"); - final Object[] items = jsonObj.getArray(); - - if (keys == null || items == null) - { - if (keys != items) - { - throw new JsonIoException("Map written where one of @keys or @items is empty"); - } - return; - } - - final int size = keys.length; - if (size != items.length) - { - throw new JsonIoException("Map written with @keys and @items entries of different sizes"); - } - - Object[] mapKeys = buildCollection(stack, keys, size); - Object[] mapValues = buildCollection(stack, items, size); - - // Save these for later so that unresolved references inside keys or values - // get patched first, and then build the Maps. - prettyMaps.add(new Object[]{jsonObj, mapKeys, mapValues}); - } - - private static Object[] buildCollection(Deque> stack, Object[] items, int size) - { - final JsonObject jsonCollection = new JsonObject(); - jsonCollection.put("@items", items); - final Object[] javaKeys = new Object[size]; - jsonCollection.target = javaKeys; - stack.addFirst(jsonCollection); - return javaKeys; - } - - /** - * Convert an input JsonObject map (known to represent a Map.class or derivative) that has regular keys and values - * to have its keys placed into @keys, and its values placed into @items. - * - * @param map Map to convert - */ - protected static void convertMapToKeysItems(final JsonObject map) - { - if (!map.containsKey("@keys") && !map.isReference()) - { - final Object[] keys = new Object[map.size()]; - final Object[] values = new Object[map.size()]; - int i = 0; - - for (Object e : map.entrySet()) - { - final Map.Entry entry = (Map.Entry) e; - keys[i] = entry.getKey(); - values[i] = entry.getValue(); - i++; - } - String saveType = map.getType(); - map.clear(); - map.setType(saveType); - map.put("@keys", keys); - map.put("@items", values); - } - } - - /** - * This method creates a Java Object instance based on the passed in parameters. - * If the JsonObject contains a key '@type' then that is used, as the type was explicitly - * set in the JSON stream. If the key '@type' does not exist, then the passed in Class - * is used to create the instance, handling creating an Array or regular Object - * instance. - *
- * The '@type' is not often specified in the JSON input stream, as in many - * cases it can be inferred from a field reference or array component type. - * - * @param clazz Instance will be create of this class. - * @param jsonObj Map-of-Map representation of object to create. - * @return a new Java object of the appropriate type (clazz) using the jsonObj to provide - * enough hints to get the right class instantiated. It is not populated when returned. - */ - protected Object createJavaObjectInstance(Class clazz, JsonObject jsonObj) - { - final boolean useMapsLocal = useMaps; - String type = jsonObj.type; - - // We can't set values to an Object, so well try to use the contained type instead - if ("java.lang.Object".equals(type)) - { - Object value = jsonObj.get("value"); - if (jsonObj.keySet().size() == 1 && value != null) - { - type = value.getClass().getName(); - } - } - - Object mate; - - // @type always takes precedence over inferred Java (clazz) type. - if (type != null) - { // @type is explicitly set, use that as it always takes precedence - Class c; - try - { - c = MetaUtils.classForName(type, reader.getClassLoader(), failOnUnknownType); - } - catch (Exception e) - { - if (useMapsLocal) - { - jsonObj.type = null; - jsonObj.target = null; - return jsonObj; - } - else - { - String name = clazz == null ? "null" : clazz.getName(); - throw new JsonIoException("Unable to create class: " + name, e); - } - } - if (c.isArray()) - { // Handle [] - Object[] items = jsonObj.getArray(); - int size = (items == null) ? 0 : items.length; - if (c == char[].class) - { - jsonObj.moveCharsToMate(); - mate = jsonObj.target; - } - else - { - mate = Array.newInstance(c.getComponentType(), size); - } - } - else - { // Handle regular field.object reference - if (MetaUtils.isPrimitive(c)) - { - mate = MetaUtils.newPrimitiveWrapper(c, jsonObj.get("value")); - } - else if (c == Class.class) - { - mate = MetaUtils.classForName((String) jsonObj.get("value"), reader.getClassLoader()); - } - else if (c.isEnum()) - { - mate = getEnum(c, jsonObj); - } - else if (Enum.class.isAssignableFrom(c)) // anonymous subclass of an enum - { - mate = getEnum(c.getSuperclass(), jsonObj); - } - else if (EnumSet.class.isAssignableFrom(c)) - { - mate = getEnumSet(c, jsonObj); - } - else if ((mate = coerceCertainTypes(c.getName())) != null) - { // if coerceCertainTypes() returns non-null, it did the work - } - else - { - mate = newInstance(c, jsonObj); - } - } - } - else - { // @type, not specified, figure out appropriate type - Object[] items = jsonObj.getArray(); - - // if @items is specified, it must be an [] type. - // if clazz.isArray(), then it must be an [] type. - if (clazz.isArray() || (items != null && clazz == Object.class && !jsonObj.containsKey("@keys"))) - { - int size = (items == null) ? 0 : items.length; - mate = Array.newInstance(clazz.isArray() ? clazz.getComponentType() : Object.class, size); - } - else if (clazz.isEnum()) - { - mate = getEnum(clazz, jsonObj); - } - else if (Enum.class.isAssignableFrom(clazz)) // anonymous subclass of an enum - { - mate = getEnum(clazz.getSuperclass(), jsonObj); - } - else if (EnumSet.class.isAssignableFrom(clazz)) // anonymous subclass of an enum - { - mate = getEnumSet(clazz, jsonObj); - } - else if ((mate = coerceCertainTypes(clazz.getName())) != null) - { // if coerceCertainTypes() returns non-null, it did the work - } - else if (clazz == Object.class && !useMapsLocal) - { - if (unknownClass == null) - { - mate = new JsonObject(); - ((JsonObject)mate).type = Map.class.getName(); - } - else if (unknownClass instanceof String) - { - mate = newInstance(MetaUtils.classForName(((String)unknownClass).trim(), reader.getClassLoader()), jsonObj); - } - else - { - throw new JsonIoException("Unable to determine object type at column: " + jsonObj.col + ", line: " + jsonObj.line + ", content: " + jsonObj); - } - } - else - { - mate = newInstance(clazz, jsonObj); - } - } - jsonObj.target = mate; - return jsonObj.target; - } - - protected Object coerceCertainTypes(String type) - { - Class clazz = coercedTypes.get(type); - if (clazz == null) - { - return null; - } - - return MetaUtils.newInstance(clazz); - } - - protected JsonObject getReferencedObj(Long ref) - { - JsonObject refObject = reader.getObjectsRead().get(ref); - if (refObject == null) - { - throw new JsonIoException("Forward reference @ref: " + ref + ", but no object defined (@id) with that value"); - } - return refObject; - } - - protected JsonReader.JsonClassReaderBase getCustomReader(Class c) - { - JsonReader.JsonClassReaderBase reader = readerCache.get(c); - if (reader == null) - { - reader = forceGetCustomReader(c); - readerCache.put(c, reader); - } - return reader == nullReader ? null : reader; - } - - private JsonReader.JsonClassReaderBase forceGetCustomReader(Class c) - { - JsonReader.JsonClassReaderBase closestReader = nullReader; - int minDistance = Integer.MAX_VALUE; - - for (Map.Entry entry : getReaders().entrySet()) - { - Class clz = entry.getKey(); - if (clz == c) - { - return entry.getValue(); - } - int distance = MetaUtils.getDistance(clz, c); - if (distance < minDistance) - { - minDistance = distance; - closestReader = entry.getValue(); - } - } - return closestReader; - } - - /** - * Fetch enum value (may need to try twice, due to potential 'name' field shadowing by enum subclasses - */ - private Object getEnum(Class c, JsonObject jsonObj) - { - try - { - return Enum.valueOf(c, (String) jsonObj.get("name")); - } - catch (Exception e) - { // In case the enum class has it's own 'name' member variable (shadowing the 'name' variable on Enum) - return Enum.valueOf(c, (String) jsonObj.get("java.lang.Enum.name")); - } - } - - /** - * Create the EnumSet with its values (it must be created this way) - */ - private Object getEnumSet(Class c, JsonObject jsonObj) - { - Object[] items = jsonObj.getArray(); - if (items == null || items.length == 0) - { - return newInstance(c, jsonObj); - } - JsonObject item = (JsonObject) items[0]; - String type = item.getType(); - Class enumClass = MetaUtils.classForName(type, reader.getClassLoader()); - EnumSet enumSet = null; - for (Object objectItem : items) - { - item = (JsonObject) objectItem; - Enum enumItem = (Enum) getEnum(enumClass, item); - if (enumSet == null) - { // Lazy init the EnumSet - enumSet = EnumSet.of(enumItem); - } - else - { - enumSet.add(enumItem); - } - } - return enumSet; - } - - /** - * For all fields where the value was "@ref":"n" where 'n' was the id of an object - * that had not yet been encountered in the stream, make the final substitution. - */ - protected void patchUnresolvedReferences() - { - Iterator i = unresolvedRefs.iterator(); - while (i.hasNext()) - { - UnresolvedReference ref = (UnresolvedReference) i.next(); - Object objToFix = ref.referencingObj.target; - JsonObject objReferenced = reader.getObjectsRead().get(ref.refId); - - if (ref.index >= 0) - { // Fix []'s and Collections containing a forward reference. - if (objToFix instanceof List) - { // Patch up Indexable Collections - List list = (List) objToFix; - list.set(ref.index, objReferenced.target); - } - else if (objToFix instanceof Collection) - { // Add element (since it was not indexable, add it to collection) - Collection col = (Collection) objToFix; - col.add(objReferenced.target); - } - else - { - Array.set(objToFix, ref.index, objReferenced.target); // patch array element here - } - } - else - { // Fix field forward reference - Field field = MetaUtils.getField(objToFix.getClass(), ref.field); - if (field != null) - { - try - { - field.set(objToFix, objReferenced.target); // patch field here - } - catch (Exception e) - { - throw new JsonIoException("Error setting field while resolving references '" + field.getName() + "', @ref = " + ref.refId, e); - } - } - } - - i.remove(); - } - } - - /** - * Process Maps/Sets (fix up their internal indexing structure) - * This is required because Maps hash items using hashCode(), which will - * change between VMs. Rehashing the map fixes this. - *
- * If useMaps==true, then move @keys to keys and @items to values - * and then drop these two entries from the map. - *
- * This hashes both Sets and Maps because the JDK sets are implemented - * as Maps. If you have a custom built Set, this would not 'treat' it - * and you would need to provider a custom reader for that set. - */ - protected void rehashMaps() - { - final boolean useMapsLocal = useMaps; - for (Object[] mapPieces : prettyMaps) - { - JsonObject jObj = (JsonObject) mapPieces[0]; - Object[] javaKeys, javaValues; - Map map; - - if (useMapsLocal) - { // Make the @keys be the actual keys of the map. - map = jObj; - javaKeys = (Object[]) jObj.remove("@keys"); - javaValues = (Object[]) jObj.remove("@items"); - } - else - { - map = (Map) jObj.target; - javaKeys = (Object[]) mapPieces[1]; - javaValues = (Object[]) mapPieces[2]; - jObj.clear(); - } - - int j = 0; - - while (javaKeys != null && j < javaKeys.length) - { - map.put(javaKeys[j], javaValues[j]); - j++; - } - } - } - - // ========== Keep relationship knowledge below the line ========== - public static Object newInstance(Class c, JsonObject jsonObject) - { - return JsonReader.newInstance(c, jsonObject); - } - - protected Map getReaders() - { - return reader.readers; - } - - protected boolean notCustom(Class cls) - { - return reader.notCustom.contains(cls); - } -} diff --git a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/Writers.java b/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/Writers.java deleted file mode 100644 index 993d2f9b..00000000 --- a/java-advance/apm/agent/src/main/java/cn/lastwhisper/monitor/agent/json/Writers.java +++ /dev/null @@ -1,376 +0,0 @@ -package cn.lastwhisper.monitor.agent.json; - -import java.io.IOException; -import java.io.Writer; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Timestamp; -import java.text.Format; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.Locale; -import java.util.Map; -import java.util.TimeZone; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -/** - * All custom writers for json-io subclass this class. Special writers are not needed for handling - * user-defined classes. However, special writers are built/supplied by json-io for many of the - * primitive types and other JDK classes simply to allow for a more concise form. - * - * @author John DeRegnaucourt (jdereg@gmail.com) - *
- * Copyright (c) Cedar Software LLC - *

- * Licensed 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.* - */ -public class Writers -{ - private Writers () {} - - public static class TimeZoneWriter implements JsonWriter.JsonClassWriter - { - public void write(Object obj, boolean showType, Writer output) throws IOException - { - TimeZone cal = (TimeZone) obj; - output.write("\"zone\":\""); - output.write(cal.getID()); - output.write('"'); - } - - public boolean hasPrimitiveForm() { return false; } - public void writePrimitiveForm(Object o, Writer output) throws IOException {} - } - - public static class CalendarWriter implements JsonWriter.JsonClassWriter - { - public void write(Object obj, boolean showType, Writer output) throws IOException - { - Calendar cal = (Calendar) obj; - MetaUtils.dateFormat.get().setTimeZone(cal.getTimeZone()); - output.write("\"time\":\""); - output.write(MetaUtils.dateFormat.get().format(cal.getTime())); - output.write("\",\"zone\":\""); - output.write(cal.getTimeZone().getID()); - output.write('"'); - } - - public boolean hasPrimitiveForm() { return false; } - public void writePrimitiveForm(Object o, Writer output) throws IOException {} - } - - public static class DateWriter implements JsonWriter.JsonClassWriter, JsonWriter.JsonClassWriterEx - { - public void write(Object obj, boolean showType, Writer output) throws IOException - { - throw new JsonIoException("Should never be called."); - } - - public void write(Object obj, boolean showType, Writer output, Map args) throws IOException - { - Date date = (Date)obj; - Object dateFormat = args.get(DATE_FORMAT); - if (dateFormat instanceof String) - { // Passed in as String, turn into a SimpleDateFormat instance to be used throughout this stream write. - dateFormat = new SimpleDateFormat((String) dateFormat, Locale.ENGLISH); - args.put(DATE_FORMAT, dateFormat); - } - if (showType) - { - output.write("\"value\":"); - } - - if (dateFormat instanceof Format) - { - output.write("\""); - output.write(((Format) dateFormat).format(date)); - output.write("\""); - } - else - { - output.write(Long.toString(((Date) obj).getTime())); - } - } - - public boolean hasPrimitiveForm() { return true; } - - public void writePrimitiveForm(Object o, Writer output) throws IOException - { - throw new JsonIoException("Should never be called."); - } - - public void writePrimitiveForm(Object o, Writer output, Map args) throws IOException - { - if (args.containsKey(DATE_FORMAT)) - { - write(o, false, output, args); - } - else - { - output.write(Long.toString(((Date) o).getTime())); - } - } - } - - public static class TimestampWriter implements JsonWriter.JsonClassWriter - { - public void write(Object o, boolean showType, Writer output) throws IOException - { - Timestamp tstamp = (Timestamp) o; - output.write("\"time\":\""); - output.write(Long.toString((tstamp.getTime() / 1000) * 1000)); - output.write("\",\"nanos\":\""); - output.write(Integer.toString(tstamp.getNanos())); - output.write('"'); - } - - public boolean hasPrimitiveForm() { return false; } - - public void writePrimitiveForm(Object o, Writer output) throws IOException { } - } - - public static class ClassWriter implements JsonWriter.JsonClassWriter - { - public void write(Object obj, boolean showType, Writer output) throws IOException - { - String value = ((Class) obj).getName(); - output.write("\"value\":"); - writeJsonUtf8String(value, output); - } - - public boolean hasPrimitiveForm() { return true; } - - public void writePrimitiveForm(Object o, Writer output) throws IOException - { - writeJsonUtf8String(((Class)o).getName(), output); - } - } - - public static class JsonStringWriter implements JsonWriter.JsonClassWriter - { - public void write(Object obj, boolean showType, Writer output) throws IOException - { - output.write("\"value\":"); - writeJsonUtf8String((String) obj, output); - } - - public boolean hasPrimitiveForm() { return true; } - - public void writePrimitiveForm(Object o, Writer output) throws IOException - { - writeJsonUtf8String((String) o, output); - } - } - - public static class LocaleWriter implements JsonWriter.JsonClassWriter - { - public void write(Object obj, boolean showType, Writer output) throws IOException - { - Locale locale = (Locale) obj; - - output.write("\"language\":\""); - output.write(locale.getLanguage()); - output.write("\",\"country\":\""); - output.write(locale.getCountry()); - output.write("\",\"variant\":\""); - output.write(locale.getVariant()); - output.write('"'); - } - public boolean hasPrimitiveForm() { return false; } - public void writePrimitiveForm(Object o, Writer output) throws IOException { } - } - - public static class BigIntegerWriter implements JsonWriter.JsonClassWriter - { - public void write(Object obj, boolean showType, Writer output) throws IOException - { - if (showType) - { - BigInteger big = (BigInteger) obj; - output.write("\"value\":\""); - output.write(big.toString(10)); - output.write('"'); - } - else - { - writePrimitiveForm(obj, output); - } - } - - public boolean hasPrimitiveForm() { return true; } - - public void writePrimitiveForm(Object o, Writer output) throws IOException - { - BigInteger big = (BigInteger) o; - output.write('"'); - output.write(big.toString(10)); - output.write('"'); - } - } - - public static class AtomicBooleanWriter implements JsonWriter.JsonClassWriter - { - public void write(Object obj, boolean showType, Writer output) throws IOException - { - if (showType) - { - AtomicBoolean value = (AtomicBoolean) obj; - output.write("\"value\":"); - output.write(value.toString()); - } - else - { - writePrimitiveForm(obj, output); - } - } - - public boolean hasPrimitiveForm() { return true; } - - public void writePrimitiveForm(Object o, Writer output) throws IOException - { - AtomicBoolean value = (AtomicBoolean) o; - output.write(value.toString()); - } - } - - public static class AtomicIntegerWriter implements JsonWriter.JsonClassWriter - { - public void write(Object obj, boolean showType, Writer output) throws IOException - { - if (showType) - { - AtomicInteger value = (AtomicInteger) obj; - output.write("\"value\":"); - output.write(value.toString()); - } - else - { - writePrimitiveForm(obj, output); - } - } - - public boolean hasPrimitiveForm() { return true; } - - public void writePrimitiveForm(Object o, Writer output) throws IOException - { - AtomicInteger value = (AtomicInteger) o; - output.write(value.toString()); - } - } - - public static class AtomicLongWriter implements JsonWriter.JsonClassWriter - { - public void write(Object obj, boolean showType, Writer output) throws IOException - { - if (showType) - { - AtomicLong value = (AtomicLong) obj; - output.write("\"value\":"); - output.write(value.toString()); - } - else - { - writePrimitiveForm(obj, output); - } - } - - public boolean hasPrimitiveForm() { return true; } - - public void writePrimitiveForm(Object o, Writer output) throws IOException - { - AtomicLong value = (AtomicLong) o; - output.write(value.toString()); - } - } - - public static class BigDecimalWriter implements JsonWriter.JsonClassWriter - { - public void write(Object obj, boolean showType, Writer output) throws IOException - { - if (showType) - { - BigDecimal big = (BigDecimal) obj; - output.write("\"value\":\""); - output.write(big.toPlainString()); - output.write('"'); - } - else - { - writePrimitiveForm(obj, output); - } - } - - public boolean hasPrimitiveForm() { return true; } - - public void writePrimitiveForm(Object o, Writer output) throws IOException - { - BigDecimal big = (BigDecimal) o; - output.write('"'); - output.write(big.toPlainString()); - output.write('"'); - } - } - - public static class StringBuilderWriter implements JsonWriter.JsonClassWriter - { - public void write(Object obj, boolean showType, Writer output) throws IOException - { - StringBuilder builder = (StringBuilder) obj; - output.write("\"value\":\""); - output.write(builder.toString()); - output.write('"'); - } - - public boolean hasPrimitiveForm() { return true; } - - public void writePrimitiveForm(Object o, Writer output) throws IOException - { - StringBuilder builder = (StringBuilder) o; - output.write('"'); - output.write(builder.toString()); - output.write('"'); - } - } - - public static class StringBufferWriter implements JsonWriter.JsonClassWriter - { - public void write(Object obj, boolean showType, Writer output) throws IOException - { - StringBuffer buffer = (StringBuffer) obj; - output.write("\"value\":\""); - output.write(buffer.toString()); - output.write('"'); - } - - public boolean hasPrimitiveForm() { return true; } - - public void writePrimitiveForm(Object o, Writer output) throws IOException - { - StringBuffer buffer = (StringBuffer) o; - output.write('"'); - output.write(buffer.toString()); - output.write('"'); - } - } - - // ========== Maintain knowledge about relationships below this line ========== - static final String DATE_FORMAT = JsonWriter.DATE_FORMAT; - - protected static void writeJsonUtf8String(String s, final Writer output) throws IOException - { - JsonWriter.writeJsonUtf8String(s, output); - } -} diff --git a/java-advance/apm/agent/src/test/java/cn/lastwhisper/test/JdbcCollectTest.java b/java-advance/apm/agent/src/test/java/cn/lastwhisper/test/JdbcCollectTest.java deleted file mode 100644 index cd2ab82f..00000000 --- a/java-advance/apm/agent/src/test/java/cn/lastwhisper/test/JdbcCollectTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package cn.lastwhisper.test; - - -import cn.lastwhisper.monitor.agent.collects.JdbcCommonCollects; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.LoaderClassPath; -import javassist.NotFoundException; - -import org.junit.Assert; -import org.junit.Test; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.SQLException; - -/** - * - * Created by tommy on 17/7/17. - */ -public class JdbcCollectTest { - - @Test - public void isTarget() throws NotFoundException { - JdbcCommonCollects ins = JdbcCommonCollects.INSTANCE; - String classname = "com.mysql.jdbc.NonRegisteringDriver"; - ClassLoader loader = JdbcCommonCollects.class.getClassLoader(); - ClassPool pool = new ClassPool(); - pool.insertClassPath(new LoaderClassPath(loader)); - CtClass cclass = pool.get(classname); - Assert.assertTrue(ins.isTarget(classname, loader, cclass)); - } - - @Test - public void proxyConnectionTest() throws SQLException, ClassNotFoundException { - JdbcCommonCollects ins = JdbcCommonCollects.INSTANCE; - Connection conn = ins.proxyConnection(getConnection()); - PreparedStatement ps = conn.prepareStatement("select * FROM t_m_sql"); - ps.execute(); - } - - @Test - public void transform() throws Exception { - - System.setProperty("$bit_server", "http://123.56.21.219:8860/receive"); - System.setProperty("$bit_key", "c4f3508aee6058f3"); - System.setProperty("$bit_secret", "966eedc1903454b8"); - - JdbcCommonCollects ins = JdbcCommonCollects.INSTANCE; - String classname = "com.mysql.jdbc.NonRegisteringDriver"; - ClassLoader loader = SpringControllerCollectsTest.class.getClassLoader(); - ClassPool pool = new ClassPool(); - pool.insertClassPath(new LoaderClassPath(loader)); - CtClass ctClass = pool.get(classname); - String className=classname; - byte[] classFileBuffer=null; - if (ins.isTarget(className, loader, ctClass)) { - ins.transform(loader, className, classFileBuffer, ctClass); - Class cla = ctClass.toClass(); - Connection conn = getConnection(); - PreparedStatement ps = conn.prepareStatement("select * FROM t_m_sql"); - ps.execute(); - } else { - Assert.assertTrue(false); - } - Thread.sleep(2000); - } - - - private static Connection getConnection() throws ClassNotFoundException, SQLException { - Class.forName("com.mysql.jdbc.Driver"); - Connection conn = DriverManager.getConnection("jdbc:mysql://123.56.21.219:3899/bit_monitor?useUnicode=true","bit_dev","bit2017##"); - return conn; - } - - public static void main(String[] args) throws SQLException, ClassNotFoundException { - String url = "jdbc:mysql://123.56.21.219:3899/bit_monitor?useUnicode=true"; - Class.forName("com.mysql.jdbc.Driver"); - Connection conn = DriverManager.getConnection(url, "bit_dev", "bit2017##"); - conn.getMetaData(); - int index = url.indexOf("?"); //$NON-NLS-1$ - if (index != -1) { - String paramString = url.substring(index + 1, url.length()); - url = url.substring(0, index); - } - String dbName = url.substring(url.lastIndexOf("/") + 1); - System.out.println(dbName); - } - -} diff --git a/java-advance/apm/agent/src/test/java/cn/lastwhisper/test/SpringControllerCollectsTest.java b/java-advance/apm/agent/src/test/java/cn/lastwhisper/test/SpringControllerCollectsTest.java deleted file mode 100644 index 2636baac..00000000 --- a/java-advance/apm/agent/src/test/java/cn/lastwhisper/test/SpringControllerCollectsTest.java +++ /dev/null @@ -1,123 +0,0 @@ -package cn.lastwhisper.test; - - -import cn.lastwhisper.monitor.agent.collects.SpringControllerCollects; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.LoaderClassPath; -import javassist.NotFoundException; - -import org.junit.Assert; -import org.junit.Test; -import org.springframework.stereotype.Controller; -import org.springframework.ui.ModelMap; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; - -import java.nio.file.Files; -import java.nio.file.Path; - -/** - * Created by tommy on 17/7/16. - */ - -public class SpringControllerCollectsTest { - @Test - public void isTarget() throws NotFoundException { - SpringControllerCollects ins = SpringControllerCollects.INSTANCE; - String classname = "com.bit.monitoring.test.SpringControllerCollectsTest$SpringControllerMock"; - ClassLoader loader = SpringControllerCollectsTest.class - .getClassLoader(); - ClassPool pool = new ClassPool(); - pool.insertClassPath(new LoaderClassPath(loader)); - CtClass cclass = pool.get(classname); - Assert.assertTrue(ins.isTarget(classname, loader, cclass)); - } - - @Test - public void transformTest() throws Exception { - System.setProperty("$bit_server", "http://123.56.21.219:8860/receive"); - System.setProperty("$bit_key", "c4f3508aee6058f3"); - System.setProperty("$bit_secret", "966eedc1903454b8"); - - SpringControllerCollects ins = SpringControllerCollects.INSTANCE; - String classname = "com.bit.test.SpringControllerCollectsTest$SpringControllerMock"; - ClassLoader loader = SpringControllerCollectsTest.class - .getClassLoader(); - ClassPool pool = new ClassPool(); - pool.insertClassPath(new LoaderClassPath(loader)); - CtClass cclass = pool.get(classname); - String className = classname; - byte[] classfileBuffer = null; - if (ins.isTarget(className, loader, cclass)) { - ins.transform(loader, className, classfileBuffer, cclass); - Class cla = cclass.toClass(); - SpringControllerMock mock = new SpringControllerMock(); - mock.sayHello(); - System.out.println(mock.getName("", "")); - } else { - Assert.assertTrue(false); - } - - Path path = new java.io.File(System.getProperty("user.dir") - + "/target/test-classes/" + cclass.getSimpleName() + ".class") - .toPath(); - Files.write(path, cclass.toBytecode()); - // 留出时间用于上传线程执行 - Thread.sleep(2000); - } - - @Test - public void errorTest() throws Exception { - SpringControllerCollects ins = SpringControllerCollects.INSTANCE; - String classname = "com.bit.test.SpringControllerCollectsTest.SpringControllerMock"; - ClassLoader loader = SpringControllerCollectsTest.class - .getClassLoader(); - ClassPool pool = new ClassPool(); - pool.insertClassPath(new LoaderClassPath(loader)); - CtClass cclass = pool.get(classname); - String className = classname; - byte[] classfileBuffer = null; - if (ins.isTarget(className, loader, cclass)) { - ins.transform(loader, className, classfileBuffer, cclass); - Class cla = cclass.toClass(); - SpringControllerMock mock = new SpringControllerMock(); - // mock.sayHello(); - try { - System.out.println(mock.getName("李大刚", "男")); - } catch (Exception e) { - e.printStackTrace(); - } - } else { - Assert.assertTrue(false); - } - // 留出时间用于上传线程执行 - Thread.sleep(2000); - } - - @Controller("aaa") - @RequestMapping("/mock") - public static class SpringControllerMock { - // /mock/hello - @RequestMapping("/hello") - public void sayHello() { - System.out.println("hello"); - } - - @RequestMapping(value = "/getName.do"/*, params = { "method=ddddd" }*/) - @ResponseBody - public String getName(String name, String sex) { - if ("男".equals(sex)) { - throw new RuntimeException("该方法传女不传男"); - } - return "hanmeme"; - } - - @RequestMapping("{id}") - public String product(ModelMap model, @PathVariable("id") String id) { - return " 商品ID:" + id; - } - - } -} diff --git a/java-advance/apm/agent/src/test/java/cn/lastwhisper/test/SpringServiceCollectTest.java b/java-advance/apm/agent/src/test/java/cn/lastwhisper/test/SpringServiceCollectTest.java deleted file mode 100644 index d36b1514..00000000 --- a/java-advance/apm/agent/src/test/java/cn/lastwhisper/test/SpringServiceCollectTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package cn.lastwhisper.test; - -import cn.lastwhisper.monitor.agent.collects.SpringServiceCollects; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.LoaderClassPath; -import javassist.NotFoundException; -import org.junit.Test; -import org.springframework.stereotype.Service; -import org.springframework.util.Assert; - -/** - * @author lastwhisper - */ -public class SpringServiceCollectTest { - - @Service - public static class StringServiceMock { - public void sayHello(String name) { - System.out.println("hello" + name); - } - } - - @Test - public void transformTest() throws Exception { - System.setProperty("$bit_server","http://123.56.21.219:8860/receive"); - System.setProperty("$bit_key","c4f3508aee6058f3"); - System.setProperty("$bit_secret","966eedc1903454b8"); - SpringServiceCollects ins = SpringServiceCollects.INSTANCE; - ClassLoader loader = SpringServiceCollectTest.class.getClassLoader(); - String className = "cn.lastwhisper.test.SpringServiceCollectTest$StringServiceMock"; - byte[] classFileBuffer = null; - ClassPool pool = new ClassPool(); - pool.insertClassPath(new LoaderClassPath(loader)); - CtClass ctClass = pool.get(className); - ins.transform(loader, className, classFileBuffer, ctClass); - Class clazz = ctClass.toClass(); - StringServiceMock mock = new StringServiceMock(); - mock.sayHello("hanmeme"); - Thread.sleep(2000); - } - - @Test - public void isTargetTest() throws NotFoundException { - String className = "cn.lastwhisper.test.SpringServiceCollectTest$StringServiceMock"; - ClassLoader loader = SpringServiceCollectTest.class.getClassLoader(); - ClassPool pool = new ClassPool(true); - CtClass ctClass = pool.get(className); - Assert.isTrue(SpringServiceCollects.INSTANCE.isTarget(className, loader, ctClass)); - } - - public static void main(String[] args){ - System.err.println("132123"); - System.out.println("132123"); - } -} diff --git a/java-advance/apm/javaagent/pom.xml b/java-advance/apm/javaagent/pom.xml deleted file mode 100644 index f3977842..00000000 --- a/java-advance/apm/javaagent/pom.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - apm - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - javaagent - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.2 - - - - ${project.name} - ${project.version} - cn.lastwhisper.javaagent.Agent - javassist-3.18.1-GA.jar - false - - - true - - - - - - - org.javassist - javassist - 3.18.1-GA - - - org.springframework - spring-webmvc - 4.0.4.RELEASE - - - javax.servlet - javax.servlet-api - 3.1.0 - - - \ No newline at end of file diff --git a/java-advance/apm/javaagent/src/main/java/cn/lastwhisper/javaagent/AgentTest.java b/java-advance/apm/javaagent/src/main/java/cn/lastwhisper/javaagent/AgentTest.java deleted file mode 100644 index 5ab13805..00000000 --- a/java-advance/apm/javaagent/src/main/java/cn/lastwhisper/javaagent/AgentTest.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.lastwhisper.javaagent; - -/** - * 该main方法用于测试Agent - * @author lastwhisper - */ -public class AgentTest { - /** - * 启动参数:-javaagent:C:\Users\Administrator\Code\GitRepository\Apm\apm\javaagent\target\javaagent-1.0-SNAPSHOT.jar - */ - public static void main(String[] args){ - System.out.println("=========main方法执行========"); - } -} diff --git a/java-advance/apm/javassist/pom.xml b/java-advance/apm/javassist/pom.xml deleted file mode 100644 index 248b20c7..00000000 --- a/java-advance/apm/javassist/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - apm - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - cn.lastwhisper - javassist - - - - org.javassist - javassist - 3.18.1-GA - - - org.springframework - spring-webmvc - 4.0.4.RELEASE - - - javax.servlet - javax.servlet-api - 3.1.0 - - - \ No newline at end of file diff --git a/java-advance/apm/pom.xml b/java-advance/apm/pom.xml deleted file mode 100644 index 9eb2c524..00000000 --- a/java-advance/apm/pom.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - 4.0.0 - - cn.lastwhisper - apm - pom - 1.0-SNAPSHOT - - javassist - javaagent - agent - - - - \ No newline at end of file diff --git a/java-advance/groovy/README.md b/java-advance/groovy/README.md new file mode 100644 index 00000000..1a6b7677 --- /dev/null +++ b/java-advance/groovy/README.md @@ -0,0 +1 @@ +groovy动态解析脚本 \ No newline at end of file diff --git a/java-advance/groovy/pom.xml b/java-advance/groovy/pom.xml new file mode 100644 index 00000000..24cfd548 --- /dev/null +++ b/java-advance/groovy/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + cn.cunchang + groovy + 1.0-SNAPSHOT + + + 8 + 8 + + + + + org.codehaus.groovy + groovy-all + 2.4.10 + + + junit + junit + 4.12 + + + + org.projectlombok + lombok + 1.18.24 + true + + + + com.alibaba + fastjson + 1.2.80 + + + + cn.hutool + hutool-all + 5.8.0 + + + \ No newline at end of file diff --git a/java-advance/groovy/src/main/java/cn/cunchang/Client.java b/java-advance/groovy/src/main/java/cn/cunchang/Client.java new file mode 100644 index 00000000..6c67b14b --- /dev/null +++ b/java-advance/groovy/src/main/java/cn/cunchang/Client.java @@ -0,0 +1,48 @@ +package cn.cunchang; + +import cn.hutool.core.io.file.FileReader; +import com.alibaba.fastjson.JSONObject; +import groovy.lang.GroovyClassLoader; +import groovy.lang.GroovyObject; +import groovy.lang.GroovyShell; +import groovy.lang.Script; +import org.junit.Test; + +/** + * @author cunchang + * @date 2022/5/30 11:38 AM + */ +public class Client { + + + public static void main(String[] args) throws InstantiationException, IllegalAccessException { + FileReader jsonFileReader = new FileReader("rsp.json"); + String jsonStr = jsonFileReader.readString(); + JSONObject jsonObject = JSONObject.parseObject(jsonStr); + + FileReader groovyFileReader = new FileReader("Demo.groovy"); + String groovyStr = groovyFileReader.readString(); + + GroovyShell shell = new GroovyShell(); + Script script = shell.parse(groovyStr); + PaymentRequestOrderBO paymentRequestOrderBO = (PaymentRequestOrderBO) script.invokeMethod("extract", jsonObject); + + System.out.println(JSONObject.toJSONString(paymentRequestOrderBO)); + } + + @Test + public void test() throws InstantiationException, IllegalAccessException { + GroovyClassLoader groovyClassLoader = new GroovyClassLoader(); + String helloScript = "package cn.cunchang;" + // 可以是纯Java代码 + "class Hello {" + + "String say(String name) {" + + "System.out.println(\"hello, \" + name);" + + " return name;" + + "}" + + "}"; + Class helloClass = groovyClassLoader.parseClass(helloScript); + GroovyObject object = (GroovyObject) helloClass.newInstance(); + Object ret = object.invokeMethod("say", "vivo"); + System.out.println(helloClass.getName()); + } +} diff --git a/java-advance/groovy/src/main/java/cn/cunchang/Constants.java b/java-advance/groovy/src/main/java/cn/cunchang/Constants.java new file mode 100644 index 00000000..e229fc05 --- /dev/null +++ b/java-advance/groovy/src/main/java/cn/cunchang/Constants.java @@ -0,0 +1,47 @@ +package cn.cunchang; + +/** + * @author cunchang + * @date 2022/5/30 4:14 PM + */ +public class Constants { + + // 详情的form节点 + public static final String VALUE = "value"; + public static final String FORM = "form"; + /** + * 单据模板唯一ID + * 同一个单据模板,除非删除重建,不然不会改变 + */ + public static final String TEMPLATE_ID = "specificationId"; + // 单据编码 + public static final String CODE = "code"; + // 收款人id,用于获取收款人信息 + public static final String PAYEE_ID = "payeeId"; + // 证件类型 + public static final String CERTIFICATE_TYPE_1 = "居民身份证"; + // 提交人id + public static final String SUBMITTER_ID = "submitterId"; + // 提交日期 + public static final String SUBMITTER_DATE = "submitDate"; + public static final String CONTRACT_ID = "u_合同ID"; + public static final String SHOP_ID = "u_商户ID"; + public static final String SHOP_NAME = "u_商户名称"; + public static final String SHOP_TYPE = "u_商户类型1"; + public static final String INVOICE_METHOD = "u_票款顺序"; + public static final String AREA_DEPARTMENT = "u_大区事业部"; + public static final String REMARK = "description"; + public static final String CITY = "u_所属城市"; + public static final String PAYMENT_COMPANY = "法人实体"; + public static final String PAYMENT_COMPANY_2 = "u_我方公司名称"; + public static final String u_所属主体 = "u_所属主体"; + public static final String PAY_MONEY = "payMoney"; + public static final String PRE_TAX_MONEY = "u_税前金额"; + public static final String PAY_MONEY_STANDARD = "standard"; + + public static final String u_代理商名称 = "u_代理商名称"; + + public static final String 个人账户 = "个人账户"; + public static final String 对公账户 = "对公账户"; + +} diff --git a/java-advance/groovy/src/main/java/cn/cunchang/PaymentRequestOrderBO.java b/java-advance/groovy/src/main/java/cn/cunchang/PaymentRequestOrderBO.java new file mode 100644 index 00000000..48e96486 --- /dev/null +++ b/java-advance/groovy/src/main/java/cn/cunchang/PaymentRequestOrderBO.java @@ -0,0 +1,179 @@ +package cn.cunchang; + +import lombok.Data; + +@Data +public class PaymentRequestOrderBO { + + /** + * 主键 + */ + private Long id; + + /** + * 业务单号
+ * 1. 易快报单据编码 + */ + private String bizNo; + + /** + * 易快报单据id + */ + private String flowId; + + /** + * 付款单流水号 + */ + private String payBillNo; + + /** + * 单据类型 + */ + private Integer bizType; + + /** + * 业务类型,对应付款单的业务类型 + */ + private Integer payBizType; + + /** + * 单据类型名称 + */ + private String bizTypeStr; + + /** + * 业务类型名称 + */ + private String payBizTypeStr; + + /** + * 付款金额,单位分 + */ + private Long payAmount; + + /** + * 税前金额,单位分 + */ + private Long preTaxAmount; + + /** + * 付款主体 + */ + private Integer paymentCompany; + + /** + * 合同id + */ + private Long contractId; + + /** + * 商家id + */ + private Long shopId; + + /** + * 商家名称 + */ + private String shopName; + + /** + * 主体名称 + */ + private String subjectName; + + /** + * 账户所属主体 + */ + private String accountSubject; + + /** + * 结算方id + */ + private Long settleSubjectId; + + /** + * 大区/事业部 + */ + private String areaDepartment; + + /** + * 所属城市 + */ + private String city; + + /** + * 申请单说明 + */ + private String remark; + + /** + * 附件信息 + */ + private String attachment; + + /** + * 提交人ID + */ + private String submitterId; + + /** + * 提交人 + */ + private String submitter; + + /** + * 单据提交时间 + */ + protected Long submitTime; + + // --------------- 收款人信息 ----------------- + + /** + * 收款人 + */ + private String revAccName; + + /** + * 收款账号 + */ + private String revAccNo; + + /** + * 开户银行名称 + */ + private String revBankName; + + /** + * 开户银行支行名称 + */ + private String revBankBranch; + + /** + * 银行联行号,直接支付需要 + */ + private String revBankNo; + + /** + * 收款人身份证号,第三方支付身份证必传 + */ + private String revCardId; + + /** + * 收款人手机号 + */ + private String revMobile; + + /** + * 收方开户银行省份 + */ + private String revBankProvince; + + /** + * 收方开户银行城市 + */ + private String revBankCity; + /** + * 付款主体在易快报code + */ + private String ykbCompanyCode; +} diff --git a/java-advance/groovy/src/main/resources/Demo.groovy b/java-advance/groovy/src/main/resources/Demo.groovy new file mode 100644 index 00000000..dfeac409 --- /dev/null +++ b/java-advance/groovy/src/main/resources/Demo.groovy @@ -0,0 +1,18 @@ +import cn.cunchang.Constants +import cn.cunchang.PaymentRequestOrderBO +import com.alibaba.fastjson.JSONObject + +PaymentRequestOrderBO extract(JSONObject jsonObject) throws Exception { + PaymentRequestOrderBO paymentRequestOrderBO = new PaymentRequestOrderBO() + + // value节点 + JSONObject value = jsonObject.getJSONObject(Constants.VALUE) + // form节点 + JSONObject form = value.getJSONObject(Constants.FORM) + + // 合同ID + String agentName = form.getString(Constants.u_代理商名称); + paymentRequestOrderBO.setShopName(agentName); + + return paymentRequestOrderBO; +} diff --git a/java-advance/groovy/src/main/resources/rsp.json b/java-advance/groovy/src/main/resources/rsp.json new file mode 100644 index 00000000..0fff182b --- /dev/null +++ b/java-advance/groovy/src/main/resources/rsp.json @@ -0,0 +1,242 @@ + +{ + "value":{ + "pipeline":1, + "grayver":"9.30.0.0:A", + "version":5, + "active":true, + "createTime":1653564772443, + "updateTime":1653566242498, + "corporationId":"aOc9TH-dmo0c00", + "sourceCorporationId":null, + "dataCorporationId":null, + "form":{ + "code":"B22004119", + "title":"代理商", + "details":[ + { + "feeTypeId":"Z0gc6-zLKosQ00", + "feeTypeForm":{ + "amount":{ + "standard":"1", + "standardUnit":"元", + "standardScale":2, + "standardSymbol":"¥", + "standardNumCode":"156", + "standardStrCode":"CNY" + }, + "feeDate":1653494400000, + "detailId":"ID_3GZvaW6cp30", + "attachments":[ + + ], + "invoiceForm":{ + "type":"noWrite" + }, + "consumptionReasons":"1" + }, + "specificationId":"Z0gc6-zLKosQ00:expense:c3d95ed2347bf65b3ffda07e0a460a742c846454", + "feeType":{ + "id":"Z0gc6-zLKosQ00", + "name":"商家分成相关-有票", + "parentId":"", + "active":true, + "code":"016" + } + } + ], + "payeeId":"ID_3GZu7TEgjDg", + "payMoney":{ + "standard":"1.00", + "standardUnit":"元", + "standardScale":2, + "standardSymbol":"¥", + "standardNumCode":"156", + "standardStrCode":"CNY" + }, + "voucherNo":"", + "printCount":"0", + "printState":"noPrint", + "submitDate":1653566109520, + "attachments":[ + { + "key":"2-1653564645311-142.webp", + "fileId":"ID_3GZthA$IIPw", + "fileName":"2.webp" + } + ], + "description":"1", + "expenseDate":1653494400000, + "submitterId":"aOc9TH-dmo0c00:2167475407768135", + "expenseMoney":{ + "standard":"1.00", + "standardUnit":"元", + "standardScale":2, + "standardSymbol":"¥", + "standardNumCode":"156", + "standardStrCode":"CNY" + }, + "u_代理商ID":"1", + "voucherStatus":"未生成", + "companyRealPay":{ + "standard":"0.00", + "standardUnit":"元", + "standardScale":2, + "standardSymbol":"¥", + "standardNumCode":"156", + "standardStrCode":"CNY" + }, + "onlyOwnerPrint":false, + "u_所属主体":"ID_3gv0rVL4has", + "u_所属城市":"[{\"key\":\"858\",\"label\":\"上海市/上海市区\"}]", + "u_打款金额":{ + "standard":"1", + "standardUnit":"元", + "standardScale":2, + "standardSymbol":"¥", + "standardNumCode":"156", + "standardStrCode":"CNY" + }, + "specificationId":"ID_3GTiWkHZSDM:2521411b6b88ac1fdc2bddc949208018932e67ea", + "writtenOffMoney":{ + "standard":"0.00", + "standardUnit":"元", + "standardScale":2, + "standardSymbol":"¥", + "standardNumCode":"156", + "standardStrCode":"CNY" + }, + "expenseDepartment":"aOc9TH-dmo0c00:476694398", + "u_代理商名称":"寸长代理商", + "u_第几次付款":"1", + "voucherCreateTime":0, + "preNodeApprovedTime":1653566242488, + "u_分成账户余额":{ + "standard":"10", + "standardUnit":"元", + "standardScale":2, + "standardSymbol":"¥", + "standardNumCode":"156", + "standardStrCode":"CNY" + }, + "u_我方公司名称":"gi0cghrKAAOk00", + "u_渠道所属大区":"ID_3GsSytCFJZM", + "u_线下付款原因":"线下付款原因", + "timeToEnterPendingPayment":1653566242498, + "ownerAndApproverPrintNodeFlag":false + }, + "ownerId":"aOc9TH-dmo0c00:2167475407768135", + "ownerDefaultDepartment":"aOc9TH-dmo0c00:476694398", + "state":"paying", + "flowType":"freeflow", + "formType":"expense", + "logs":[ + { + "action":"freeflow.submit", + "state":"approving", + "operatorId":"aOc9TH-dmo0c00:2167475407768135", + "byDelegateId":null, + "operatorDefaultDepartment":"aOc9TH-dmo0c00:476694398", + "nextOperatorId":"ebot", + "nextOperatorIds":[ + + ], + "time":1653566113650, + "attributes":{ + "nextId":"FLOW:1337089428:1774981071", + "nodeId":"SUBMIT", + "comment":"", + "isUrgent":false, + "nextName":"费用标准检查", + "urgentReason":null, + "resubmitMethod":"FROM_START", + "nextCounterSign":false, + "sensitiveContent":null, + "resubmitOperatorIds":[ + + ] + }, + "modifyFlowLog":null, + "attachments":[ + + ] + }, + { + "action":"freeflow.agree", + "state":"approving", + "operatorId":"aOc9TH-dmo0c00:2167475407768135", + "byDelegateId":null, + "operatorDefaultDepartment":"aOc9TH-dmo0c00:476694398", + "nextOperatorId":"ebot", + "nextOperatorIds":[ + + ], + "time":1653566241843, + "attributes":{ + "nextId":"FLOW:194583488:1595867343", + "nodeId":"FLOW:1489097468:862917124", + "comment":"同意", + "complete":true, + "nextName":"对接CBS", + "nodeName":"审批节点1", + "expressNum":null, + "isEbotNode":false, + "counterSign":false, + "isRecalNode":false, + "oldFlowPlanId":null, + "nextCounterSign":false, + "autographImageId":null + }, + "modifyFlowLog":null, + "attachments":[ + + ] + }, + { + "action":"freeflow.agree", + "state":"paying", + "operatorId":"ebot", + "byDelegateId":null, + "operatorDefaultDepartment":null, + "nextOperatorId":"aOc9TH-dmo0c00:2167475407768135", + "nextOperatorIds":[ + + ], + "time":1653566242498, + "attributes":{ + "nextId":"FLOW:1374256138:1133323930", + "nodeId":"FLOW:194583488:1595867343", + "comment":"", + "complete":true, + "nextName":"出纳支付", + "nodeName":"对接CBS", + "expressNum":null, + "isEbotNode":true, + "counterSign":false, + "isRecalNode":false, + "oldFlowPlanId":null, + "nextCounterSign":false, + "autographImageId":null + }, + "modifyFlowLog":null, + "attachments":[ + + ] + } + ], + "actions":{ + "aOc9TH-dmo0c00:2167475407768135":[ + "freeflow.urge", + "freeflow.copy", + "freeflow.print", + "freeflow.reject", + "freeflow.pay", + "freeflow.addnode", + "freeflow.remind", + "freeflow.printed" + ] + }, + "invoiceRemind":false, + "id":"ID_3GZvaW6cc30" + } +} diff --git a/java-advance/javaagent/pom.xml b/java-advance/javaagent/pom.xml new file mode 100644 index 00000000..2711850d --- /dev/null +++ b/java-advance/javaagent/pom.xml @@ -0,0 +1,52 @@ + + + + apm + cn.lastwhisper + 1.0-SNAPSHOT + + 4.0.0 + + javaagent + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + ${project.name} + ${project.version} + cn.lastwhisper.Agent + javassist-3.18.1-GA.jar + false + + + true + + + + + + + org.javassist + javassist + 3.18.1-GA + + + org.springframework + spring-webmvc + 4.0.4.RELEASE + + + javax.servlet + javax.servlet-api + 3.1.0 + + + \ No newline at end of file diff --git a/java-advance/apm/javaagent/src/main/java/cn/lastwhisper/javaagent/Agent.java b/java-advance/javaagent/src/main/java/cn/lastwhisper/Agent.java similarity index 96% rename from java-advance/apm/javaagent/src/main/java/cn/lastwhisper/javaagent/Agent.java rename to java-advance/javaagent/src/main/java/cn/lastwhisper/Agent.java index f55cf93d..2e8bee50 100644 --- a/java-advance/apm/javaagent/src/main/java/cn/lastwhisper/javaagent/Agent.java +++ b/java-advance/javaagent/src/main/java/cn/lastwhisper/Agent.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.javaagent; +package cn.lastwhisper; import java.lang.instrument.Instrumentation; diff --git a/java-advance/javaagent/src/main/java/cn/lastwhisper/AgentTest.java b/java-advance/javaagent/src/main/java/cn/lastwhisper/AgentTest.java new file mode 100644 index 00000000..56779a07 --- /dev/null +++ b/java-advance/javaagent/src/main/java/cn/lastwhisper/AgentTest.java @@ -0,0 +1,15 @@ +package cn.lastwhisper; + +/** + * 该main方法用于测试Agent + * @author lastwhisper + */ +public class AgentTest { + + /** + * 启动参数:-javaagent:$HOME\Projects\Github\code\java-advance\apm\javaagent\target\javaagent-1.0-SNAPSHOT.jar + */ + public static void main(String[] args){ + System.out.println("=========main方法执行========"); + } +} diff --git a/java-advance/javassist/pom.xml b/java-advance/javassist/pom.xml new file mode 100644 index 00000000..c0e11173 --- /dev/null +++ b/java-advance/javassist/pom.xml @@ -0,0 +1,44 @@ + + + + apm + cn.lastwhisper + 1.0-SNAPSHOT + + 4.0.0 + + cn.lastwhisper + javassist + + + + org.apache.maven.plugins + maven-compiler-plugin + + 6 + 6 + + + + + + + + org.javassist + javassist + 3.18.1-GA + + + org.springframework + spring-webmvc + 4.0.4.RELEASE + + + javax.servlet + javax.servlet-api + 3.1.0 + + + \ No newline at end of file diff --git a/java-advance/apm/javassist/src/main/java/cn/lastwhisper/javassist/DispatcherServletCollect.java b/java-advance/javassist/src/main/java/cn/lastwhisper/javassist/DispatcherServletCollect.java similarity index 100% rename from java-advance/apm/javassist/src/main/java/cn/lastwhisper/javassist/DispatcherServletCollect.java rename to java-advance/javassist/src/main/java/cn/lastwhisper/javassist/DispatcherServletCollect.java diff --git a/java-advance/apm/javassist/src/main/java/cn/lastwhisper/javassist/Error1.java b/java-advance/javassist/src/main/java/cn/lastwhisper/javassist/Error1.java similarity index 100% rename from java-advance/apm/javassist/src/main/java/cn/lastwhisper/javassist/Error1.java rename to java-advance/javassist/src/main/java/cn/lastwhisper/javassist/Error1.java diff --git a/java-advance/apm/javassist/src/main/java/cn/lastwhisper/javassist/Error2.java b/java-advance/javassist/src/main/java/cn/lastwhisper/javassist/Error2.java similarity index 100% rename from java-advance/apm/javassist/src/main/java/cn/lastwhisper/javassist/Error2.java rename to java-advance/javassist/src/main/java/cn/lastwhisper/javassist/Error2.java diff --git a/java-advance/apm/javassist/src/main/java/cn/lastwhisper/javassist/JavassistDynamicProxyClass.java b/java-advance/javassist/src/main/java/cn/lastwhisper/javassist/JavassistDynamicProxyClass.java similarity index 100% rename from java-advance/apm/javassist/src/main/java/cn/lastwhisper/javassist/JavassistDynamicProxyClass.java rename to java-advance/javassist/src/main/java/cn/lastwhisper/javassist/JavassistDynamicProxyClass.java diff --git a/java-advance/apm/javassist/src/main/java/cn/lastwhisper/javassist/JavassistDynamicProxyInterface.java b/java-advance/javassist/src/main/java/cn/lastwhisper/javassist/JavassistDynamicProxyInterface.java similarity index 100% rename from java-advance/apm/javassist/src/main/java/cn/lastwhisper/javassist/JavassistDynamicProxyInterface.java rename to java-advance/javassist/src/main/java/cn/lastwhisper/javassist/JavassistDynamicProxyInterface.java diff --git a/java-advance/apm/javassist/src/main/java/cn/lastwhisper/javassist/JavassistMonitorMethod.java b/java-advance/javassist/src/main/java/cn/lastwhisper/javassist/JavassistMonitorMethod.java similarity index 100% rename from java-advance/apm/javassist/src/main/java/cn/lastwhisper/javassist/JavassistMonitorMethod.java rename to java-advance/javassist/src/main/java/cn/lastwhisper/javassist/JavassistMonitorMethod.java diff --git a/java-advance/apm/javassist/src/main/java/cn/lastwhisper/javassist/JavassistMonitorServlet.java b/java-advance/javassist/src/main/java/cn/lastwhisper/javassist/JavassistMonitorServlet.java similarity index 100% rename from java-advance/apm/javassist/src/main/java/cn/lastwhisper/javassist/JavassistMonitorServlet.java rename to java-advance/javassist/src/main/java/cn/lastwhisper/javassist/JavassistMonitorServlet.java diff --git a/java-advance/apm/javassist/src/main/java/cn/lastwhisper/javassist/StringUtil.java b/java-advance/javassist/src/main/java/cn/lastwhisper/javassist/StringUtil.java similarity index 100% rename from java-advance/apm/javassist/src/main/java/cn/lastwhisper/javassist/StringUtil.java rename to java-advance/javassist/src/main/java/cn/lastwhisper/javassist/StringUtil.java diff --git a/java-advance/network/socketproxy/pom.xml b/java-advance/network/socketproxy/pom.xml new file mode 100644 index 00000000..95115404 --- /dev/null +++ b/java-advance/network/socketproxy/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + + cn.cunchang + socketproxy + 1.0-SNAPSHOT + + + 8 + 8 + + + \ No newline at end of file diff --git a/java-advance/network/socketproxy/src/main/java/cn/cunchang/CreateSecretKey.java b/java-advance/network/socketproxy/src/main/java/cn/cunchang/CreateSecretKey.java new file mode 100644 index 00000000..0763d4c9 --- /dev/null +++ b/java-advance/network/socketproxy/src/main/java/cn/cunchang/CreateSecretKey.java @@ -0,0 +1,286 @@ +package cn.cunchang; + +import sun.misc.BASE64Decoder; +import sun.misc.BASE64Encoder; + +import javax.crypto.Cipher; +import java.io.ByteArrayOutputStream; +import java.security.*; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.HashMap; +import java.util.Map; + +/** + * @Auther: + * @Date: 2021-03-26 11:35 + * @Since + * @Description: + */ +public class CreateSecretKey { + public static final String KEY_ALGORITHM = "RSA"; + private static final String PUBLIC_KEY = "RSAPublicKey"; + private static final String PRIVATE_KEY = "RSAPrivateKey"; + public static final String SIGNATURE_ALGORITHM="MD5withRSA"; + /** + * RSA最大加密明文大小 + */ + private static final int MAX_ENCRYPT_BLOCK = 117; + + /** + * RSA最大解密密文大小 + */ + private static final int MAX_DECRYPT_BLOCK = 128; + //获得公钥字符串 + public static String getPublicKeyStr(Map keyMap) throws Exception { + //获得map中的公钥对象 转为key对象 + Key key = (Key) keyMap.get(PUBLIC_KEY); + //编码返回字符串 + return encryptBASE64(key.getEncoded()); + } + + + //获得私钥字符串 + public static String getPrivateKeyStr(Map keyMap) throws Exception { + //获得map中的私钥对象 转为key对象 + Key key = (Key) keyMap.get(PRIVATE_KEY); + //编码返回字符串 + return encryptBASE64(key.getEncoded()); + } + + //获取公钥 + public static PublicKey getPublicKey(String key) throws Exception { + byte[] keyBytes; + keyBytes = (new BASE64Decoder()).decodeBuffer(key); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); + KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); + PublicKey publicKey = keyFactory.generatePublic(keySpec); + return publicKey; + } + + //获取私钥 + public static PrivateKey getPrivateKey(String key) throws Exception { + byte[] keyBytes; + keyBytes = (new BASE64Decoder()).decodeBuffer(key); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); + KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); + PrivateKey privateKey = keyFactory.generatePrivate(keySpec); + return privateKey; + } + + //解码返回byte + public static byte[] decryptBASE64(String key) throws Exception { + return (new BASE64Decoder()).decodeBuffer(key); + } + + + //编码返回字符串 + public static String encryptBASE64(byte[] key) throws Exception { + return (new BASE64Encoder()).encodeBuffer(key); + } + + //***************************签名和验证******************************* + public static byte[] sign(byte[] data,String privateKeyStr) throws Exception{ + PrivateKey priK = getPrivateKey(privateKeyStr); + Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM); + sig.initSign(priK); + sig.update(data); + return sig.sign(); + } + + public static boolean verify(byte[] data,byte[] sign,String publicKeyStr) throws Exception{ + PublicKey pubK = getPublicKey(publicKeyStr); + Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM); + sig.initVerify(pubK); + sig.update(data); + return sig.verify(sign); + } + + //************************公钥加密************************** + public static byte[] encryptByPublic(byte[] plainText,String publicKeyStr)throws Exception{ + PublicKey publicKey = getPublicKey(publicKeyStr); + Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + int inputLen = plainText.length; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int offSet = 0; + int i = 0; + byte[] cache; + while (inputLen - offSet > 0) { + if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { + cache = cipher.doFinal(plainText, offSet, MAX_ENCRYPT_BLOCK); + } else { + cache = cipher.doFinal(plainText, offSet, inputLen - offSet); + } + out.write(cache, 0, cache.length); + i++; + offSet = i * MAX_ENCRYPT_BLOCK; + } + byte[] encryptText = out.toByteArray(); + out.close(); + return encryptText; + } + + //************************私钥加密************************** + public static byte[] encryptByPrivate(byte[] plainText,String privateKeyStr)throws Exception{ + PrivateKey privateKey = getPrivateKey(privateKeyStr); + Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, privateKey); + int inputLen = plainText.length; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int offSet = 0; + int i = 0; + byte[] cache; + while (inputLen - offSet > 0) { + if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { + cache = cipher.doFinal(plainText, offSet, MAX_ENCRYPT_BLOCK); + } else { + cache = cipher.doFinal(plainText, offSet, inputLen - offSet); + } + out.write(cache, 0, cache.length); + i++; + offSet = i * MAX_ENCRYPT_BLOCK; + } + byte[] encryptText = out.toByteArray(); + out.close(); + return encryptText; + } + + //************************私钥解密************************** + public static byte[] decryptByPrivate(byte[] encryptText,String privateKeyStr)throws Exception{ + PrivateKey privateKey = getPrivateKey(privateKeyStr); + Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); + cipher.init(Cipher.DECRYPT_MODE, privateKey); + int inputLen = encryptText.length; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int offSet = 0; + byte[] cache; + int i = 0; + // 对数据分段解密 + while (inputLen - offSet > 0) { + if (inputLen - offSet > MAX_DECRYPT_BLOCK) { + cache = cipher.doFinal(encryptText, offSet, MAX_DECRYPT_BLOCK); + } else { + cache = cipher.doFinal(encryptText, offSet, inputLen - offSet); + } + out.write(cache, 0, cache.length); + i++; + offSet = i * MAX_DECRYPT_BLOCK; + } + byte[] plainText = out.toByteArray(); + out.close(); + return plainText; + } + + //************************公钥解密************************** + public static byte[] decryptByPublic(byte[] encryptText,String publicKeyStr)throws Exception{ + PublicKey publicKey = getPublicKey(publicKeyStr); + Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); + cipher.init(Cipher.DECRYPT_MODE, publicKey); + int inputLen = encryptText.length; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int offSet = 0; + byte[] cache; + int i = 0; + // 对数据分段解密 + while (inputLen - offSet > 0) { + if (inputLen - offSet > MAX_DECRYPT_BLOCK) { + cache = cipher.doFinal(encryptText, offSet, MAX_DECRYPT_BLOCK); + } else { + cache = cipher.doFinal(encryptText, offSet, inputLen - offSet); + } + out.write(cache, 0, cache.length); + i++; + offSet = i * MAX_DECRYPT_BLOCK; + } + byte[] plainText = out.toByteArray(); + out.close(); + return plainText; + } + + public static Map initKey() throws Exception { + KeyPairGenerator keyPairGen = KeyPairGenerator + .getInstance(KEY_ALGORITHM); + keyPairGen.initialize(1024); + KeyPair keyPair = keyPairGen.generateKeyPair(); + RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); + RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); + Map keyMap = new HashMap(2); + keyMap.put(PUBLIC_KEY, publicKey); + keyMap.put(PRIVATE_KEY, privateKey); + return keyMap; + } + + + public static void main(String[] args) { + Map keyMap; + byte[] cipherText; + String input = "晚上10点203等我!"; + try { + keyMap = initKey(); + String publicKey = getPublicKeyStr(keyMap); + System.out.println("公钥------------------"); + System.out.println(publicKey); + String privateKey = getPrivateKeyStr(keyMap); + System.out.println("私钥------------------"); + System.out.println(privateKey); + + + /*System.out.println("测试 公钥加密 私钥解密-------------------"); + System.out.println("明文======="+input); + + cipherText = encryptByPublic(input.getBytes(),publicKey); + //加密后的东西 + System.out.println("公钥加密密文======="+new String(cipherText)); + //开始解密 + byte[] plainText = decryptByPrivate(cipherText,privateKey); + System.out.println("私钥解密后明文===== " + new String(plainText));*/ + + + /*System.out.println("测试 私钥加密 公钥解密-------------------"); + System.out.println("明文======="+input); + + cipherText = encryptByPrivate(input.getBytes(),privateKey); + //加密后的东西 + System.out.println("私钥加密密文======="+new String(cipherText)); + //开始解密 + byte[] plainText = decryptByPublic(cipherText,publicKey); + System.out.println("公钥解密后明文===== " + new String(plainText));*/ + + + /*System.out.println("测试 私钥加密 私钥解密-------------------"); + System.out.println("明文======="+input); + + cipherText = encryptByPrivate(input.getBytes(),privateKey); + //加密后的东西 + System.out.println("私钥加密密文======="+new String(cipherText)); + //开始解密 + byte[] plainText = decryptByPrivate(cipherText,privateKey); + System.out.println("私钥解密后明文===== " + new String(plainText));*/ + + /*System.out.println("测试 公钥加密 公钥解密-------------------"); + System.out.println("明文======="+input); + + cipherText = encryptByPublic(input.getBytes(),publicKey); + //加密后的东西 + System.out.println("公钥加密密文======="+new String(cipherText)); + //开始解密 + byte[] plainText = decryptByPublic(cipherText,publicKey); + System.out.println("公钥解密后明文===== " + new String(plainText));*/ + + System.out.println("验证签名-----------"); + + /*String str="被签名的内容"; + System.out.println("\n原文:"+str); + byte[] signature=sign(str.getBytes(),privateKey); + boolean status=verify(str.getBytes(), signature,publicKey); + System.out.println("验证情况:"+status);*/ + } catch (Exception e) { + e.printStackTrace(); + } + } + + +} diff --git a/java-advance/network/socketproxy/src/main/java/cn/cunchang/LineBuffer.java b/java-advance/network/socketproxy/src/main/java/cn/cunchang/LineBuffer.java new file mode 100644 index 00000000..d63babab --- /dev/null +++ b/java-advance/network/socketproxy/src/main/java/cn/cunchang/LineBuffer.java @@ -0,0 +1,46 @@ +package cn.cunchang; + +import java.io.IOException; +import java.io.InputStream; + +/** + * @Auther: + * @Date: 2021-03-22 15:52 + * @Since + * @Description: + */ +public class LineBuffer { + private int size; + + public LineBuffer(int size) { + this.size = size; + } + + public String readLine(InputStream input) throws IOException { + int flag = 0; + int index = 0; + byte[] bts = new byte[this.size]; + int b; + while(flag!=2&&(b= input.read())!=-1){ + bts[index++] = (byte) b; + if(b=='\r'&&flag%2==0){ + flag++; + }else if(b=='\n'&&flag%2==1){ + flag++; + if(flag==2){ + return new String(bts,0,index-2); + } + }else{ + flag = 0; + } + if(index==bts.length){ + //满了扩容 + byte[] newBts = new byte[bts.length*2]; + System.arraycopy(bts,0,newBts,0,bts.length); + bts = null; + bts = newBts; + } + } + return null; + } +} diff --git a/java-advance/network/socketproxy/src/main/java/cn/cunchang/ProxyHandleThread.java b/java-advance/network/socketproxy/src/main/java/cn/cunchang/ProxyHandleThread.java new file mode 100644 index 00000000..ba1fa3d6 --- /dev/null +++ b/java-advance/network/socketproxy/src/main/java/cn/cunchang/ProxyHandleThread.java @@ -0,0 +1,33 @@ +package cn.cunchang; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.concurrent.CountDownLatch; + +/** + * @Auther: + * @Date: 2021-03-22 15:51 + * @Since + * @Description: + */ +public class ProxyHandleThread extends Thread{ + private InputStream input; + private OutputStream output; + + public ProxyHandleThread(InputStream input, OutputStream output, CountDownLatch cdl) { + this.input = input; + this.output = output; + } + + @Override + public void run() { + try { + while (true) { + output.write(input.read()); + } + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/java-advance/network/socketproxy/src/main/java/cn/cunchang/ProxyServer.java b/java-advance/network/socketproxy/src/main/java/cn/cunchang/ProxyServer.java new file mode 100644 index 00000000..2924ba2c --- /dev/null +++ b/java-advance/network/socketproxy/src/main/java/cn/cunchang/ProxyServer.java @@ -0,0 +1,100 @@ +package cn.cunchang; + +import javax.swing.*; +import java.awt.*; +import java.io.*; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URL; +import java.util.Date; + +/** + * @Auther: + * @Date: 2021-03-22 16:22 + * @Since + * @Description: + */ +public class ProxyServer extends JFrame { + private JTextArea jta =new JTextArea();//create an JTextArea to output some information + + public static void main(String[] args){ + new ProxyServer(); + } + + public ProxyServer() { + setLayout(new BorderLayout()); + add(new JScrollPane(jta), BorderLayout.CENTER); + + setTitle("Proxy Server by Li Zhaoji"); + setSize(500, 300); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setVisible(true); + try{ + ServerSocket serverSocket = new ServerSocket(8081);//Listening port 8081 + jta.append("Proxy Server started at " + new Date() + '\n'); + jta.append("Proxy Server is listening on port "+serverSocket.getLocalPort() + '\n' + '\n'); + + int clientNo = 1; + + while (true) { + + Socket socket = serverSocket.accept(); + + jta.append("1****************************************************************************1" + '\n'); + jta.append("Starting thread for client " + clientNo + " at " + new Date() + '\n'); + + InetAddress inetAddress = socket.getInetAddress();//get the host PC's information + jta.append("Client " + clientNo + "'s host name is " + inetAddress.getHostName() + '\n'); + jta.append("Client " + clientNo + "'s IP Address is " + inetAddress.getHostAddress() + '\n'); + + HandleClient task = new HandleClient(socket); + + new Thread(task).start();//start a new thread to handle the require of the host + + clientNo++; + } + } + catch(IOException ex) { + System.err.println(ex); + } + } + + class HandleClient implements Runnable { + private Socket socket; + + public HandleClient(Socket socket){ + this.socket = socket; + } + + @Override + public void run() { + try{ + BufferedReader inputFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream())); + PrintStream outputToClient = new PrintStream(socket.getOutputStream()); + String str = inputFromClient.readLine();//read the GET require string from Host + jta.append("The require from Client:" + str + '\n'); + String inurl = str.substring(4, str.indexOf("HTTP/")-1);//get the URL string from GET + jta.append("The require URL:" + inurl + '\n'); + URL url = new URL(inurl); + InputStream infile = url.openStream();//the input stream that get the data from Web Server + int n = infile.available();//the number of bytes that accept from Web Server + byte buf[] = new byte[1024]; + while((n = infile.read(buf)) >= 0){ + outputToClient.write(buf, 0, n);//start send with buf[0], send n bytes + } + outputToClient.close(); + socket.close(); + inputFromClient.close(); + + jta.append("socket has been closed!!!" + '\n'); + jta.append("2****************************************************************************2" + '\n' + '\n'); + } + catch(IOException e) { + System.err.println(e); + jta.append("Sorry! There is no require file??? :(" + '\n'); + } + } + } + +} diff --git a/java-advance/network/socketproxy/src/main/java/cn/cunchang/SocketHandle.java b/java-advance/network/socketproxy/src/main/java/cn/cunchang/SocketHandle.java new file mode 100644 index 00000000..c5084980 --- /dev/null +++ b/java-advance/network/socketproxy/src/main/java/cn/cunchang/SocketHandle.java @@ -0,0 +1,136 @@ +package cn.cunchang; + +import java.io.*; +import java.net.Socket; + +/** + * @Auther: + * @Date: 2021-03-22 15:49 + * @Since + * @Description: + */ +public class SocketHandle extends Thread{ + + private Socket socket; + + public SocketHandle(Socket socket) { + this.socket = socket; + } + + @Override + public void run() { + OutputStream clientOutput = null; + InputStream clientInput = null; + Socket proxySocket = null; + InputStream proxyInput = null; + OutputStream proxyOutput = null; + try { + clientInput = socket.getInputStream(); + clientOutput = socket.getOutputStream(); + String line; + String host = ""; + LineBuffer lineBuffer = new LineBuffer(1024); + StringBuilder headStr = new StringBuilder(); + //读取HTTP请求头,并拿到HOST请求头和method + while (null != (line = lineBuffer.readLine(clientInput))) { + System.out.println(line); + headStr.append(line + "\r\n"); + if (line.length() == 0) { + break; + } else { + String[] temp = line.split(" "); + if (temp[0].contains("Host")) { + host = temp[1]; + } + } + } + String type = headStr.substring(0, headStr.indexOf(" ")); + //根据host头解析出目标服务器的host和port + String[] hostTemp = host.split(":"); + host = hostTemp[0]; + int port = 80; + if (hostTemp.length > 1) { + port = Integer.valueOf(hostTemp[1]); + } + //连接到目标服务器 + proxySocket = new Socket(host, port); + proxyInput = proxySocket.getInputStream(); + proxyOutput = proxySocket.getOutputStream(); + //根据HTTP method来判断是https还是http请求 + if ("CONNECT".equalsIgnoreCase(type)) {//https先建立隧道 + clientOutput.write("HTTP/1.1 200 Connection Established\r\n\r\n".getBytes()); + clientOutput.flush(); + } else {//http直接将请求头转发 + proxyOutput.write(headStr.toString().getBytes()); + } + //新开线程转发客户端请求至目标服务器 + new ProxyHandleThread(clientInput, proxyOutput,null).start(); + //转发目标服务器响应至客户端 + while (true) { + clientOutput.write(proxyInput.read()); + print(proxyInput); + /*String url ="https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=false&word=%E6%9E%97%E5%BF%97%E7%8E%B2&step_word=&hs=2&pn=8&spn=0&di=7150&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=0&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=undefined&cs=2732989282%2C3677770873&os=2359571368%2C569377150&simid=55908706%2C799425763&adpicid=0&lpn=0&ln=2666&fr=&fmq=1616661848576_R&fm=&ic=undefined&s=undefined&hd=undefined&latest=undefined©right=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=undefined&ist=&jit=&cg=star&bdtype=0&oriquery=&objurl=https%3A%2F%2Fround-lake.dustinice.workers.dev%3A443%2Fhttps%2Fgimg2.baidu.com%2Fimage_search%2Fsrc%3Dhttps%3A%2F%2Fround-lake.dustinice.workers.dev%3A443%2Fhttp%2Fup.enterdesk.com%2Fedpic_source%2Fc3%2F28%2F51%2Fc328516d6a64807408f0180f8e7e9032.jpg%26refer%3Dhttps%3A%2F%2Fround-lake.dustinice.workers.dev%3A443%2Fhttp%2Fup.enterdesk.com%26app%3D2002%26size%3Df9999%2C10000%26q%3Da80%26n%3D0%26g%3D0n%26fmt%3Djpeg%3Fsec%3D1619253875%26t%3D1dae7d851056b4b20dde8c9749192719&fromurl=ippr_z2C%24qAzdH3FAzdH3Fp7_z%26e3Bjgpj61jfh_z%26e3Bv54AzdH3F15ogs5w1AzdH3F8888cAzdH3F&gsm=9&rpstart=0&rpnum=0&islist=&querylist=&force=undefined"; + clientOutput.write(url.getBytes());*/ + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (proxyInput != null) { + try { + proxyOutput.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (proxyOutput != null) { + try { + proxyOutput.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (proxySocket != null) { + try { + proxySocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (clientInput != null) { + try { + clientInput.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (clientOutput != null) { + try { + clientOutput.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (socket != null) { + try { + socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + } + + public static void print (InputStream is) throws UnsupportedEncodingException { + InputStreamReader isr =new InputStreamReader(is,"utf-8"); + BufferedReader br =new BufferedReader(isr); + try { + while ((br.read())!=-1) { + System.out.println(br.readLine()); + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/java-advance/network/socketproxy/src/main/java/cn/cunchang/SocketProxy.java b/java-advance/network/socketproxy/src/main/java/cn/cunchang/SocketProxy.java new file mode 100644 index 00000000..7a10b207 --- /dev/null +++ b/java-advance/network/socketproxy/src/main/java/cn/cunchang/SocketProxy.java @@ -0,0 +1,21 @@ +package cn.cunchang; + +import java.net.ServerSocket; + +/** + * @Auther: + * @Date: 2021-03-22 15:56 + * @Since + * @Description: + */ +public class SocketProxy { + + public static void main(String[] args) throws Exception { + //监听端口 + ServerSocket serverSocket = new ServerSocket(8001); + System.out.println("8001正在监听.........."); + for (; ; ) { + new SocketHandle(serverSocket.accept()).start(); + } + } +} diff --git a/java-advance/proxy/README.md b/java-advance/proxy/README.md new file mode 100644 index 00000000..f05d236d --- /dev/null +++ b/java-advance/proxy/README.md @@ -0,0 +1,49 @@ +# 代理 + +代理的优点 + + +## 静态代理 + +**继承实现** + +缺点: + +- 继承关系决定了代理顺序,代理顺序改变,需要新增继承类。 + +**组合实现** + +优点: + +- 组合关系决定了代理顺序,类可以任意组合,不会新增类 + + + +虽然静态代理侵入性很小,但是增强的代码无法复用。比如接口再加一个 stop 方法,需要复制耗时记录的代码 + + + + + +## 动态代理 + +需要一个代理类,可以给所有的类做代理。 + + + + + +**优点:** + +- 代理模式能将代理对象与真实被调用的目标对象分离 +- 一定程度上降低了系统的耦合度,扩展性好 +- 增强目标对象 + +**缺点:** + +- 代理模式会造成系统设计中类的数目增加 +- 在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢 +- 增加系统的复杂度 + + + diff --git a/java-advance/proxy/com/sun/proxy/$Proxy0.class b/java-advance/proxy/com/sun/proxy/$Proxy0.class new file mode 100644 index 00000000..2168a4ca Binary files /dev/null and b/java-advance/proxy/com/sun/proxy/$Proxy0.class differ diff --git a/java-advance/proxy/jdk-proxy/README.md b/java-advance/proxy/jdk-proxy/README.md new file mode 100644 index 00000000..c887afe9 --- /dev/null +++ b/java-advance/proxy/jdk-proxy/README.md @@ -0,0 +1,6 @@ + +v1 jdk动态代理常规用法 +v1.equal jdk动态代理生成的类,等价调用 + +v2 jdk动态代理接口 +v3 jdk动态代理无法代理抽象类 diff --git a/java-advance/proxy/jdk-proxy/pom.xml b/java-advance/proxy/jdk-proxy/pom.xml new file mode 100644 index 00000000..a6919d4a --- /dev/null +++ b/java-advance/proxy/jdk-proxy/pom.xml @@ -0,0 +1,19 @@ + + + + proxy + cn.cunchang + 1.0-SNAPSHOT + + 4.0.0 + + jdk-proxy + + + 11 + 11 + + + \ No newline at end of file diff --git a/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/ProxyInvocationHandler.java b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/ProxyInvocationHandler.java new file mode 100644 index 00000000..bac76061 --- /dev/null +++ b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/ProxyInvocationHandler.java @@ -0,0 +1,34 @@ +package cn.cunchang.v1; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +/** + * 定义动态代理调用处理器 + */ +public class ProxyInvocationHandler implements InvocationHandler { + /** + * 被代理类,我们自己定义的成员变量,不要也可以 + */ + private Object target; + + public ProxyInvocationHandler(Object target) { + this.target = target; + } + + /** + * @param proxy 代理对象,jdk给你生成的对象 + * @param method 被代理类的方法 + * @param args 被代理类方法的参数 + * @return + * @throws Throwable + */ + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + System.out.println("进入代理调用处理器 before"); + Object obj = method.invoke(target, args); + System.out.println("进入代理调用处理器 fater"); + return obj; + } + +} \ No newline at end of file diff --git a/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/ProxyTest.java b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/ProxyTest.java new file mode 100644 index 00000000..96a7518f --- /dev/null +++ b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/ProxyTest.java @@ -0,0 +1,20 @@ + +package cn.cunchang.v1; + +import java.lang.reflect.Proxy; + +public class ProxyTest { + public static void main(String[] args) { + + System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); + + Subject subject = new SubjectImpl(); + Subject proxy = (Subject) Proxy + .newProxyInstance( + subject.getClass().getClassLoader(), + subject.getClass().getInterfaces(), + new ProxyInvocationHandler(subject)); + + proxy.sayHello(); + } +} \ No newline at end of file diff --git a/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/Subject.java b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/Subject.java new file mode 100644 index 00000000..dc4fef32 --- /dev/null +++ b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/Subject.java @@ -0,0 +1,5 @@ +package cn.cunchang.v1; + +public interface Subject { // 定义代理接口 + String sayHello(); +} diff --git a/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/SubjectImpl.java b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/SubjectImpl.java new file mode 100644 index 00000000..6dc0d06b --- /dev/null +++ b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/SubjectImpl.java @@ -0,0 +1,9 @@ +package cn.cunchang.v1; + +public class SubjectImpl implements Subject { // 定义代理接口实现类 + @Override + public String sayHello() { + System.out.println(" Hello World"); + return "success"; + } +} \ No newline at end of file diff --git a/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/equal/$Proxy0.java b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/equal/$Proxy0.java new file mode 100644 index 00000000..546e880c --- /dev/null +++ b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/equal/$Proxy0.java @@ -0,0 +1,98 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +package cn.cunchang.v1.equal; + +import cn.cunchang.v2.Subject; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.lang.reflect.UndeclaredThrowableException; + +/** + * 继承jdk的Proxy,作用之一:直接使用handler成员变量 + * 副作用:由于Java只能单继承,所以jdk动态代理只能代理有接口实现的类 + */ +public final class $Proxy0 extends Proxy implements Subject { + private static Method m1; + private static Method m3; + private static Method m2; + private static Method m0; + + /** + * InvocationHandler 是代理对象的调用被代理对象的接口。 + * 也就是说代理对象为什么能调用被代理对象,是因为有这个handler在中间做桥梁 + * @param var1 + */ + public $Proxy0(InvocationHandler var1) { + super(var1); + } + + static { + try { + /** + * 获取代理对象接口的所有方法,用于代理方法回调 + */ + m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); + m3 = Class.forName("cn.cunchang.v1.equal.Subject").getMethod("sayHello"); + m2 = Class.forName("java.lang.Object").getMethod("toString"); + m0 = Class.forName("java.lang.Object").getMethod("hashCode"); + } catch (NoSuchMethodException var2) { + throw new NoSuchMethodError(var2.getMessage()); + } catch (ClassNotFoundException var3) { + throw new NoClassDefFoundError(var3.getMessage()); + } + } + + public final String sayHello() { + try { + /** + * 代理类调用handler,handler.invoke()方法,把方法的执行链交给用户 + * + * InvocationHandler.invoke(Object proxy, Method method, Object[] args) + * proxy – jdk给你生成的代理对象 + * method – 被代理类的方法 + * args – 被代理类方法的参数 + */ + return (String)super.h.invoke(this, m3, (Object[])null); + } catch (RuntimeException | Error var2) { + throw var2; + } catch (Throwable var3) { + throw new UndeclaredThrowableException(var3); + } + } + + public final boolean equals(Object var1) { + try { + return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); + } catch (RuntimeException | Error var3) { + throw var3; + } catch (Throwable var4) { + throw new UndeclaredThrowableException(var4); + } + } + + public final String toString() { + try { + return (String)super.h.invoke(this, m2, (Object[])null); + } catch (RuntimeException | Error var2) { + throw var2; + } catch (Throwable var3) { + throw new UndeclaredThrowableException(var3); + } + } + + public final int hashCode() { + try { + return (Integer)super.h.invoke(this, m0, (Object[])null); + } catch (RuntimeException | Error var2) { + throw var2; + } catch (Throwable var3) { + throw new UndeclaredThrowableException(var3); + } + } + + +} diff --git a/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/equal/ProxyInvocationHandler.java b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/equal/ProxyInvocationHandler.java new file mode 100644 index 00000000..3d253e35 --- /dev/null +++ b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/equal/ProxyInvocationHandler.java @@ -0,0 +1,34 @@ +package cn.cunchang.v1.equal; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +/** + * 定义动态代理调用处理器 + */ +public class ProxyInvocationHandler implements InvocationHandler { + /** + * 被代理类,我们自己定义的成员变量,不要也可以 + */ + private Object target; + + public ProxyInvocationHandler(Object target) { + this.target = target; + } + + /** + * @param proxy 代理对象,jdk给你生成的对象 + * @param method 被代理类的方法 + * @param args 被代理类方法的参数 + * @return + * @throws Throwable + */ + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + System.out.println("进入代理调用处理器 before"); + Object obj = method.invoke(target, args); + System.out.println("进入代理调用处理器 fater"); + return obj; + } + +} \ No newline at end of file diff --git a/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/equal/ProxyTest.java b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/equal/ProxyTest.java new file mode 100644 index 00000000..6c98f724 --- /dev/null +++ b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/equal/ProxyTest.java @@ -0,0 +1,20 @@ + +package cn.cunchang.v1.equal; + +public class ProxyTest { + public static void main(String[] args) { + + System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); + + Subject subject = new SubjectImpl(); +// Subject proxy = (Subject) Proxy +// .newProxyInstance( +// subject.getClass().getClassLoader(), +// subject.getClass().getInterfaces(), +// new ProxyInvocationHandler(subject)); + + $Proxy0 $Proxy0 = new $Proxy0(new ProxyInvocationHandler(subject)); + $Proxy0.sayHello(); + + } +} \ No newline at end of file diff --git a/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/equal/Subject.java b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/equal/Subject.java new file mode 100644 index 00000000..af71b97e --- /dev/null +++ b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/equal/Subject.java @@ -0,0 +1,5 @@ +package cn.cunchang.v1.equal; + +public interface Subject { // 定义代理接口 + String sayHello(); +} diff --git a/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/equal/SubjectImpl.java b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/equal/SubjectImpl.java new file mode 100644 index 00000000..ea8a4553 --- /dev/null +++ b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v1/equal/SubjectImpl.java @@ -0,0 +1,9 @@ +package cn.cunchang.v1.equal; + +public class SubjectImpl implements Subject { // 定义代理接口实现类 + @Override + public String sayHello() { + System.out.println(" Hello World"); + return "success"; + } +} \ No newline at end of file diff --git a/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v2/ProxyInvocationHandler.java b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v2/ProxyInvocationHandler.java new file mode 100644 index 00000000..c4946ad9 --- /dev/null +++ b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v2/ProxyInvocationHandler.java @@ -0,0 +1,22 @@ +package cn.cunchang.v2; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +public class ProxyInvocationHandler implements InvocationHandler { + + /** + * + * @param proxy + * @param method + * @param args + * @return + * @throws Throwable + */ + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + System.out.println("进入代理调用处理器"); + return "success"; + } + +} \ No newline at end of file diff --git a/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v2/ProxyTest.java b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v2/ProxyTest.java new file mode 100644 index 00000000..fb5b9043 --- /dev/null +++ b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v2/ProxyTest.java @@ -0,0 +1,19 @@ +package cn.cunchang.v2; + +import java.lang.reflect.Proxy; + +public class ProxyTest { + public static void main(String[] args) { + + System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); + + Subject proxy = (Subject) Proxy + .newProxyInstance( + ProxyTest.class.getClassLoader(), + new Class[]{Subject.class}, + new ProxyInvocationHandler()); + + proxy.sayHello(); + + } +} \ No newline at end of file diff --git a/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v2/Subject.java b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v2/Subject.java new file mode 100644 index 00000000..22226a81 --- /dev/null +++ b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v2/Subject.java @@ -0,0 +1,6 @@ +package cn.cunchang.v2; + +public interface Subject { + String sayHello(); +} + diff --git a/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v3/AbstractProxy.java b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v3/AbstractProxy.java new file mode 100644 index 00000000..d7d445d9 --- /dev/null +++ b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v3/AbstractProxy.java @@ -0,0 +1,5 @@ +package cn.cunchang.v3; + +public abstract class AbstractProxy { + abstract void sayHello(); +} diff --git a/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v3/ProxyInvocationHandler.java b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v3/ProxyInvocationHandler.java new file mode 100644 index 00000000..59c9ab61 --- /dev/null +++ b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v3/ProxyInvocationHandler.java @@ -0,0 +1,14 @@ +package cn.cunchang.v3; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +public class ProxyInvocationHandler implements InvocationHandler { + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + System.out.println("进入代理调用处理器"); + return "success"; + } + +} \ No newline at end of file diff --git a/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v3/ProxyTest.java b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v3/ProxyTest.java new file mode 100644 index 00000000..60e091d2 --- /dev/null +++ b/java-advance/proxy/jdk-proxy/src/main/java/cn/cunchang/v3/ProxyTest.java @@ -0,0 +1,16 @@ +package cn.cunchang.v3; + +import java.lang.reflect.Proxy; + +public class ProxyTest { + public static void main(String[] args) { + + AbstractProxy proxyInterface = (AbstractProxy) Proxy + .newProxyInstance( + ProxyTest.class.getClassLoader(), + new Class[]{AbstractProxy.class}, + new ProxyInvocationHandler()); + proxyInterface.sayHello(); + + } +} \ No newline at end of file diff --git a/java-advance/proxy/mybatis-mapper/pom.xml b/java-advance/proxy/mybatis-mapper/pom.xml new file mode 100644 index 00000000..71653055 --- /dev/null +++ b/java-advance/proxy/mybatis-mapper/pom.xml @@ -0,0 +1,19 @@ + + + + proxy + cn.cunchang + 1.0-SNAPSHOT + + 4.0.0 + + mybatis-mapper + + + 11 + 11 + + + \ No newline at end of file diff --git a/java-advance/proxy/mybatis-mapper/src/main/java/cn/cunchang/Main.java b/java-advance/proxy/mybatis-mapper/src/main/java/cn/cunchang/Main.java new file mode 100644 index 00000000..4f2cc064 --- /dev/null +++ b/java-advance/proxy/mybatis-mapper/src/main/java/cn/cunchang/Main.java @@ -0,0 +1,28 @@ +package cn.cunchang; + +import java.lang.reflect.Proxy; +import java.util.List; + +/** + * @author cunchang + * @date 2021/11/25 12:53 上午 + */ +public class Main { + + public static void main(String[] args) { + // 获取SqlSession + SqlSession sqlSession = new SqlSession() { + @Override + public List selectList(String statementId) { + System.out.println(statementId); + return null; + } + }; + // 获取UserMapper接口 + MyMapperProxy userMapperProxy = new MyMapperProxy<>(UserMapper.class, sqlSession); + UserMapper userMapper = (UserMapper) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), + new Class[] { UserMapper.class }, userMapperProxy); + // 调用selectAll方法 + List user = userMapper.selectAll(); + } +} diff --git a/java-advance/proxy/mybatis-mapper/src/main/java/cn/cunchang/MyMapperProxy.java b/java-advance/proxy/mybatis-mapper/src/main/java/cn/cunchang/MyMapperProxy.java new file mode 100644 index 00000000..97786dbc --- /dev/null +++ b/java-advance/proxy/mybatis-mapper/src/main/java/cn/cunchang/MyMapperProxy.java @@ -0,0 +1,29 @@ +package cn.cunchang; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.List; + +/** + * @author cunchang + * @date 2021/11/25 12:48 上午 + */ +public class MyMapperProxy implements InvocationHandler { + private Class mapperInterface; + private SqlSession sqlSession; + + public MyMapperProxy(Class mapperInterface, SqlSession sqlSession) { + this.mapperInterface = mapperInterface; + this.sqlSession = sqlSession; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + // 针对不同的sql类型,需要调用sqlSession不同的方法 + // 接口方法中的参数也有很多情况,这里只考虑没有参数的情况 + List list = sqlSession.selectList(mapperInterface.getCanonicalName() + "." + method.getName()); + // 返回值也有很多情况,这里不做处理直接返回 + return list; + } + +} \ No newline at end of file diff --git a/java-advance/proxy/mybatis-mapper/src/main/java/cn/cunchang/SqlSession.java b/java-advance/proxy/mybatis-mapper/src/main/java/cn/cunchang/SqlSession.java new file mode 100644 index 00000000..e36a0c22 --- /dev/null +++ b/java-advance/proxy/mybatis-mapper/src/main/java/cn/cunchang/SqlSession.java @@ -0,0 +1,13 @@ +package cn.cunchang; + +import java.util.List; + +/** + * @author cunchang + * @date 2021/11/25 12:46 上午 + */ +public interface SqlSession { + + List selectList(String statementId); + +} diff --git a/java-advance/proxy/mybatis-mapper/src/main/java/cn/cunchang/SysUser.java b/java-advance/proxy/mybatis-mapper/src/main/java/cn/cunchang/SysUser.java new file mode 100644 index 00000000..1e4b7a71 --- /dev/null +++ b/java-advance/proxy/mybatis-mapper/src/main/java/cn/cunchang/SysUser.java @@ -0,0 +1,8 @@ +package cn.cunchang; + +/** + * @author cunchang + * @date 2021/11/25 12:48 上午 + */ +public class SysUser { +} diff --git a/java-advance/proxy/mybatis-mapper/src/main/java/cn/cunchang/UserMapper.java b/java-advance/proxy/mybatis-mapper/src/main/java/cn/cunchang/UserMapper.java new file mode 100644 index 00000000..e4e3477c --- /dev/null +++ b/java-advance/proxy/mybatis-mapper/src/main/java/cn/cunchang/UserMapper.java @@ -0,0 +1,7 @@ +package cn.cunchang; + +import java.util.List; + +public interface UserMapper{ + List selectAll(); +} \ No newline at end of file diff --git a/java-advance/proxy/pom.xml b/java-advance/proxy/pom.xml new file mode 100644 index 00000000..e8e329fe --- /dev/null +++ b/java-advance/proxy/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + cn.cunchang + proxy + pom + 1.0-SNAPSHOT + + mybatis-mapper + jdk-proxy + + + + 8 + 8 + + + + + junit + junit + 4.13 + + + + cglib + cglib + 3.1 + + + + org.ow2.asm + asm-util + 8.0.1 + + + org.ow2.asm + asm + 8.0.1 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + \ No newline at end of file diff --git a/java-advance/proxy/src/main/java/cn/cunchang/Client.java b/java-advance/proxy/src/main/java/cn/cunchang/Client.java new file mode 100644 index 00000000..5bb29576 --- /dev/null +++ b/java-advance/proxy/src/main/java/cn/cunchang/Client.java @@ -0,0 +1,191 @@ +package cn.cunchang; + +import cn.cunchang.cglib.RunMethodIntercepot; +import cn.cunchang.myjdkdynamic.*; +import cn.cunchang.jdkdynamic.JdkTimeHandler; +import cn.cunchang.staticproxy.combination.TankLogProxy1; +import cn.cunchang.staticproxy.combination.TankTimeProxy1; +import cn.cunchang.staticproxy.inherit.TankLogTimeProxy; +import net.sf.cglib.core.DebuggingClassWriter; +import net.sf.cglib.proxy.Enhancer; +import org.junit.Test; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Collection; + +/** + * @author cunchang + * @date 2021/5/9 10:11 上午 + */ +public class Client { + + @Test + public void test继承代理() { + Moveable tank = new TankLogTimeProxy(); + tank.move(); + } + + @Test + public void test组合代理() { + Tank tank = new Tank(); + // 先时间后日志 +// TankTimeProxy1 ttp = new TankTimeProxy1(tank); +// TankLogProxy1 tlp = new TankLogProxy1(ttp); +// tlp.move(); + // 先日志后时间 + TankLogProxy1 tlp = new TankLogProxy1(tank); + TankTimeProxy1 ttp = new TankTimeProxy1(tlp); + ttp.move(); + } + + /** + * 动态代理原理 + * 1、动态生成代理类java源码 + * 2、通过java编译器将源码编译成字节码 + * 3、通过类加载器加载字节码,获取Class对象 + * 4、有了Class对象就可以通过反射获取代理对象 + * + * @throws Exception + */ + @Test + public void test手写动态代理1() throws Exception { + String path = System.getProperty("user.dir") + "/src/main/java/cn/cunchang/dynamic/"; + String pkg = "cn.cunchang.dynamic"; + MyClassLoader classLoader = new MyClassLoader(path, pkg); + + Moveable proxyObj = (Moveable) Proxy1.newProxyInstance(classLoader); + proxyObj.move(); + } + + /** + * 需要代理的方法,通过Class获取 + * @throws Exception + */ + @Test + public void test手写动态代理2() throws Exception { + String path = System.getProperty("user.dir") + "/src/main/java/cn/cunchang/dynamic/"; + String pkg = "cn.cunchang.dynamic"; + MyClassLoader classLoader = new MyClassLoader(path, pkg); + + Moveable proxyObj = (Moveable) Proxy2.newProxyInstance(classLoader, Moveable.class); + proxyObj.move(); + } + + /** + * 代理的逻辑,通过InvocationHandler封装 + * @throws Exception + */ + @Test + public void test手写动态代理3() throws Exception { + String path = System.getProperty("user.dir") + "/src/main/java/cn/cunchang/dynamic/"; + String pkg = "cn.cunchang.dynamic"; + MyClassLoader classLoader = new MyClassLoader(path, pkg); + + Tank tank = new Tank(); + InvocationHandler timeHandler = new TimeHandler(tank); + Moveable proxyObj = (Moveable) Proxy3.newProxyInstance(classLoader, Moveable.class, timeHandler); + proxyObj.move(); + } + + /** + * newProxyInstance + * |-- getProxyClass0 + * |--proxyClassCache.get(loader, interfaces); + * |--ProxyClassFactory + * |--apply + * |--代理类的名称 String proxyName = proxyPkg + proxyClassNamePrefix + num; + * |--生成字节码 byte[] proxyClassFile = ProxyGenerator.generateProxyClass( + * proxyName, interfaces, accessFlags);通过类加载器defineClass0加载 + * |--生成符合Java规范的代码 generateProxyClass + * 在动态生成的对象中,使用h.invoke(this, m3, (Object[])null)这种形式执行方法 + * 这个h就是Proxy的InvocationHandler成员变量,而这个成员变量是在 + * Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this)传入this时赋值的 + */ + public void testJdk动态代理1() throws Exception { + // 查看jdk生成的代理类,必须在main方法中才能生成 + System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); + + ClassLoader classLoader = Client.class.getClassLoader(); + Tank tank = new Tank(); + // 第二种方法、创建代理对象;使用Proxy提供的静态方法newProxyInstance + // 参数一:目标增强类的类加载器(用于加载代理类); + // 参数二:目标增强类的接口(代理类实现接口); + // 参数三:InvocationHandler执行增强代码和目标对象 + Moveable proxyObj = (Moveable) Proxy.newProxyInstance(classLoader, Tank.class.getInterfaces(), new JdkTimeHandler(tank)); + proxyObj.move(); + + } + + public static void main(String[] args) throws Exception { +// new Client().testJdk动态代理1(); + new Client().testCglib动态代理1(); + } + + public void testCglib动态代理1() throws Exception { + // 查看Cglib生成的代理类 + System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, System.getProperty("user.dir")); + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(Tank.class); + enhancer.setCallback(new RunMethodIntercepot()); + Moveable tank = (Moveable) enhancer.create(); + tank.move(); + } + + /** + * 代理jdk集合 + * @throws Exception + */ + @Test + public void testJdk动态代理2() throws Exception { + // 第一种方法、创建代理对象;使用有参构造 + Class proxyClass = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class); + Constructor constructor = proxyClass.getConstructor(java.lang.reflect.InvocationHandler.class); + Collection proxy1 = (Collection) constructor.newInstance(new java.lang.reflect.InvocationHandler() { +// List target = new ArrayList(); + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + Object retVal = null; +// retVal = method.invoke(target, args); + return retVal; + } + + }); + proxy1.clear(); + // 为什么待返回值的方法会报错? + // 因为InvocationHandler的invoke方法返回值为null + proxy1.size(); + + // 第二种方法、创建代理对象;使用Proxy提供的静态方法newProxyInstance + // 参数一:目标增强类的类加载器(用于加载代理类); + // 参数二:目标增强类的接口(代理类实现接口); + // 参数三:InvocationHandler执行增强代码和目标方法 + Collection proxy2 = (Collection) Proxy.newProxyInstance(Collection.class.getClassLoader(), + new Class[]{Collection.class}, + new java.lang.reflect.InvocationHandler() { + ArrayList target = new ArrayList(); + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + long start = System.currentTimeMillis(); + // 使用反射调用目标对象的方法 + Object retVal = method.invoke(target, args); + long end = System.currentTimeMillis(); + System.out.println("性能监控:" + method.getName() + "方法耗时 " + (end - start)); + // 修改代理类的返回值(过滤器) + // retVal = false; + return retVal; + } + }); + boolean retVal = proxy2.add("普通代理"); + proxy2.add("静态代理"); + proxy2.add("动态代理"); + proxy2.add("CGLIB代理"); + System.out.println(retVal); + System.out.println(proxy2.size()); + } + + +} diff --git a/java-advance/proxy/src/main/java/cn/cunchang/Moveable.java b/java-advance/proxy/src/main/java/cn/cunchang/Moveable.java new file mode 100644 index 00000000..330ca6af --- /dev/null +++ b/java-advance/proxy/src/main/java/cn/cunchang/Moveable.java @@ -0,0 +1,10 @@ +package cn.cunchang; + +/** + * @author cunchang + * @date 2021/5/9 9:57 上午 + */ +public interface Moveable { + void move(); +// void stop(); +} diff --git a/java-advance/proxy/src/main/java/cn/cunchang/Tank.java b/java-advance/proxy/src/main/java/cn/cunchang/Tank.java new file mode 100644 index 00000000..5b83e2e8 --- /dev/null +++ b/java-advance/proxy/src/main/java/cn/cunchang/Tank.java @@ -0,0 +1,39 @@ +package cn.cunchang; + +import java.util.Random; + +/** + * @author cunchang + * @date 2021/5/9 9:57 上午 + */ +public class Tank implements Moveable { + + @Override + public void move() { + try { + Thread.sleep(new Random().nextInt(1000)); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Tank Moving..."); + } + + /** + * 直接修改源码 + */ +// @Override +// public void move() { +// //计算方法运行了多长时间 +// long start = System.currentTimeMillis(); +// +// try { +// Thread.sleep(new Random().nextInt(1000)); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// System.out.println("Tank Moving..."); +// long end = System.currentTimeMillis(); +// System.out.println("耗时:"+(end-start)); +// } + +} \ No newline at end of file diff --git a/java-advance/proxy/src/main/java/cn/cunchang/cglib/RunMethodIntercepot.java b/java-advance/proxy/src/main/java/cn/cunchang/cglib/RunMethodIntercepot.java new file mode 100644 index 00000000..7c54b442 --- /dev/null +++ b/java-advance/proxy/src/main/java/cn/cunchang/cglib/RunMethodIntercepot.java @@ -0,0 +1,25 @@ +package cn.cunchang.cglib; + +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +import java.lang.reflect.Method; + +public class RunMethodIntercepot implements MethodInterceptor { + + @Override + public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { + long start = System.currentTimeMillis(); + Object result = null; + try { + result = methodProxy.invokeSuper(o, objects); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + long end = System.currentTimeMillis(); + System.out.println("耗时:" + (end - start)); + return result; + } + +} \ No newline at end of file diff --git a/java-advance/proxy/src/main/java/cn/cunchang/jdkdynamic/JdkTimeHandler.java b/java-advance/proxy/src/main/java/cn/cunchang/jdkdynamic/JdkTimeHandler.java new file mode 100644 index 00000000..af2b12d3 --- /dev/null +++ b/java-advance/proxy/src/main/java/cn/cunchang/jdkdynamic/JdkTimeHandler.java @@ -0,0 +1,42 @@ +package cn.cunchang.jdkdynamic; + +import cn.cunchang.Moveable; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +/** + * @author cunchang + * @date 2021/5/9 4:23 下午 + */ +public class JdkTimeHandler implements InvocationHandler { + + private Moveable moveable; + + public JdkTimeHandler(Moveable moveable) { + this.moveable = moveable; + } + + /** + * @param proxy 代理类 + * @param method 执行的方法 + * @param args 参数 + * @return + * @throws Throwable + */ + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + long start = System.currentTimeMillis(); + Object result = null; + try { + result = method.invoke(moveable, new Object[]{}); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + long end = System.currentTimeMillis(); + System.out.println("耗时:" + (end - start)); + return result; + } + +} diff --git a/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/InvocationHandler.java b/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/InvocationHandler.java new file mode 100644 index 00000000..bf753eb0 --- /dev/null +++ b/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/InvocationHandler.java @@ -0,0 +1,12 @@ +package cn.cunchang.myjdkdynamic; + +import java.lang.reflect.Method; +public interface InvocationHandler { + + /** + * 代理执行的逻辑 + * @param o 代理类 + * @param m 要执行的方法 + */ + public void invoke(Object o,Method m); +} \ No newline at end of file diff --git a/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/MyClassLoader.java b/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/MyClassLoader.java new file mode 100644 index 00000000..530d8852 --- /dev/null +++ b/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/MyClassLoader.java @@ -0,0 +1,42 @@ +package cn.cunchang.myjdkdynamic; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +public class MyClassLoader extends ClassLoader { + private File dir; + private String proxyClassPackage; + + public File getDir() { + return dir; + } + + public String getProxyClassPackage() { + return proxyClassPackage; + } + + public MyClassLoader(String path, String proxyClassPackage) { + this.dir = new File(path); + this.proxyClassPackage = proxyClassPackage; + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + if (null != dir) { + File classFile = new File(dir, name + ".class"); + if (classFile.exists()) { + try { + // Since JDK 7 + byte[] classBytes = Files.readAllBytes(classFile.toPath()); + return defineClass(proxyClassPackage + "." + name, classBytes, 0, classBytes.length); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + throw new ClassNotFoundException("class:" + name + " 找不到"); + } + + +} diff --git a/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/Proxy1.java b/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/Proxy1.java new file mode 100644 index 00000000..3b2fdef3 --- /dev/null +++ b/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/Proxy1.java @@ -0,0 +1,65 @@ +package cn.cunchang.myjdkdynamic; + +import cn.cunchang.Moveable; +import cn.cunchang.Tank; + +import javax.tools.JavaCompiler; +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; +import java.io.File; +import java.io.FileWriter; +import java.lang.reflect.Constructor; + +public class Proxy1 { + + public static Object newProxyInstance(MyClassLoader classLoader) throws Exception { + String rt = "\r\n"; + String src = + "package "+classLoader.getProxyClassPackage()+";" + rt + + + "import cn.cunchang.Moveable;" + rt + + + "public class $Proxy0 implements Moveable{" + rt + + + " Moveable m;" + rt + + + " public $Proxy0(Moveable m) {" + rt + + " super();" + rt + + " this.m = m;" + rt + + " }" + rt + + + " @Override" + rt + + " public void move() {" + rt + + " long start = System.currentTimeMillis();" + rt + + " m.move();" + rt + + " long end = System.currentTimeMillis();" + rt + + " System.out.println(\"耗时:\"+(end-start));" + rt + + " }" + rt + + "}"; + + //1,生成代理类 + String fileName = classLoader.getDir() + File.separator + "$Proxy0.java"; + File file = new File(fileName); + FileWriter fw = new FileWriter(file); + fw.write(src); + fw.flush(); + fw.close(); + + //2,将生成的类进行编译成class文件 + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();//拿到系统默认的编译器(其实就是javac) + StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);//诊断监听器;语言;编码 + Iterable units = fileMgr.getJavaFileObjects(fileName); + CompilationTask task = compiler.getTask(null, fileMgr, null, null, null, units); + task.call(); + fileMgr.close(); + + //3,将class load到内存 + Class clazz = classLoader.findClass("$Proxy0"); + //4,,创建一个对象 + //不能用 clazz.newInstance();创建对象因为它会调用空构造方法 + Constructor constructor = clazz.getConstructor(Moveable.class);//获取某个类型参数的构造器 + return constructor.newInstance(new Tank()); + } + +} \ No newline at end of file diff --git a/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/Proxy2.java b/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/Proxy2.java new file mode 100644 index 00000000..02ca324b --- /dev/null +++ b/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/Proxy2.java @@ -0,0 +1,91 @@ +package cn.cunchang.myjdkdynamic; + +import cn.cunchang.Moveable; +import cn.cunchang.Tank; + +import java.io.File; +import java.io.FileWriter; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +import javax.tools.JavaCompiler; +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +/** + * 产生代理的类 + * + */ +public class Proxy2 { + + /** + * 动态传入接口,其实jdk可以传多个接口 + * + * @param interfaces + * @return + * @throws Exception + */ + public static Object newProxyInstance(MyClassLoader classLoader,Class interfaces) throws Exception{ + //换行字符串 + String rt = "\r\n"; + String methodStr = ""; + //反射拿到接口的所有的方法 + Method[] methods = interfaces.getMethods(); + for(Method m : methods){ + methodStr += "@Override"+rt + + "public void "+ m.getName()+ "() {" +rt + + //计算方法运行了多长时间 + " long start = System.currentTimeMillis();" +rt + + " m."+m.getName() +"();" +rt + + " long end = System.currentTimeMillis();"+rt + + " System.out.println(\"耗时:\"+(end-start));"+rt + + "}"; + } + + //只要能动态的 编译这段代码,就能动态的产生代理类!类的名字无所谓 + //动态编译的技术:JDK6 Compiler API,CGLib(用到了ASM) ,ASM + //(CGLib、ASM不用源码来编译,能直接生成二进制文件,因为java的二进制文件格式是公开的) + //Spring内部,如果是实现接口就是用的JDK本身的API产生代理,否则就用CGLib + + String src = + "package "+classLoader.getProxyClassPackage()+";"+ rt + + + "import cn.cunchang.Moveable;" + rt + + + "public class $Proxy0 implements "+ interfaces.getName() +"{"+rt + + + " Moveable m;"+rt + + + " public $Proxy0(Moveable m) {"+rt + + " super();"+rt + + " this.m = m;"+rt + + " }"+rt + + + methodStr + + "}"; + + //1,生成代理类 + String fileName = classLoader.getDir() + File.separator + "$Proxy0.java"; + File file = new File(fileName); + FileWriter fw = new FileWriter(file); + fw.write(src); + fw.flush(); + fw.close(); + + //2,将生成的类进行编译成class文件 + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();//拿到系统默认的编译器(其实就是javac) + StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);//诊断监听器;语言;编码 + Iterable units = fileMgr.getJavaFileObjects(fileName); + CompilationTask task = compiler.getTask(null, fileMgr, null, null, null, units); + task.call(); + fileMgr.close(); + + //3,将class load到内存 + Class clazz = classLoader.findClass("$Proxy0"); + //4,,创建一个对象 + //不能用 clazz.newInstance();创建对象因为它会调用空构造方法 + Constructor constructor = clazz.getConstructor(Moveable.class);//获取某个类型参数的构造器 + return constructor.newInstance(new Tank()); + } +} \ No newline at end of file diff --git a/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/Proxy3.java b/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/Proxy3.java new file mode 100644 index 00000000..e72bf298 --- /dev/null +++ b/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/Proxy3.java @@ -0,0 +1,88 @@ +package cn.cunchang.myjdkdynamic; + +import javax.tools.JavaCompiler; +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; +import java.io.File; +import java.io.FileWriter; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +/** + * 产生代理的类 + * @author dev + * + */ +public class Proxy3 { + /** + * + * @param interfaces 代理实现的接口 + * @param h 代理处理逻辑 + * @return + * @throws Exception + */ + public static Object newProxyInstance(MyClassLoader classLoader,Class interfaces, InvocationHandler h) throws Exception{//动态传入接口,其实jdk可以传多个接口 + //换行字符串 + String rt = "\r\n"; + String methodStr = ""; + //反射拿到接口的所有的方法 + Method[] methods = interfaces.getMethods(); + for(Method m : methods){ + methodStr += "@Override"+rt + + "public void "+ m.getName()+ "() {"+ + " try{"+rt+ + " Method md = "+ interfaces.getName()+".class.getMethod(\""+m.getName()+"\");"+rt+ + " h.invoke(this,md);"+rt+ //this->代理对象 + " }catch(Exception e){e.printStackTrace();}"+ + "}"; + } + + //只要能动态的 编译这段代码,就能动态的产生代理类!类的名字无所谓 + //动态编译的技术:JDK6 Compiler API,CGLib(用到了ASM) ,ASM + //(CGLib、ASM不用源码来编译,能直接生成二进制文件,因为java的二进制文件格式是公开的) + //Spring内部,如果是实现接口就是用的JDK本身的API产生代理,否则就用CGLib + + String src = + "package "+classLoader.getProxyClassPackage()+";"+ rt + + + "import java.lang.reflect.Method;"+rt+ + "import cn.cunchang.Moveable;" + rt + + "import cn.cunchang.dynamic.InvocationHandler;"+rt+ + + "public class $Proxy0 implements "+ interfaces.getName() +"{"+rt + + + " InvocationHandler h;"+rt+ + " public $Proxy0(InvocationHandler h) {"+rt + + " this.h = h;"+rt + + " }"+rt + + + methodStr + + "}"; + + //1,生成代理类 + String fileName = classLoader.getDir() + File.separator + "$Proxy0.java"; + File file = new File(fileName); + FileWriter fw = new FileWriter(file); + fw.write(src); + fw.flush(); + fw.close(); + + //2,将生成的类进行编译成class文件 + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();//拿到系统默认的编译器(其实就是javac) + StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);//诊断监听器;语言;编码 + Iterable units = fileMgr.getJavaFileObjects(fileName); + CompilationTask task = compiler.getTask(null, fileMgr, null, null, null, units); + task.call(); + fileMgr.close(); + + //3,将class load到内存 + Class clazz = classLoader.findClass("$Proxy0"); + //4,,创建一个对象 + //不能用 clazz.newInstance();创建对象因为它会调用空构造方法 + Constructor constructor = clazz.getConstructor(InvocationHandler.class);//获取某个类型参数的构造器 + Object obj = constructor.newInstance(h);// + + return obj; + } +} \ No newline at end of file diff --git a/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/TimeHandler.java b/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/TimeHandler.java new file mode 100644 index 00000000..a9cd1f8c --- /dev/null +++ b/java-advance/proxy/src/main/java/cn/cunchang/myjdkdynamic/TimeHandler.java @@ -0,0 +1,28 @@ +package cn.cunchang.myjdkdynamic; + +import java.lang.reflect.Method; + +public class TimeHandler implements InvocationHandler{ + + //被代理类 + private Object target; + + + public TimeHandler(Object target) { + super(); + this.target = target; + } + + @Override + public void invoke(Object o,Method m) { + long start = System.currentTimeMillis(); + try { + m.invoke(target, new Object[]{}); + } catch (Exception e) { + e.printStackTrace(); + } + long end = System.currentTimeMillis(); + System.out.println("耗时:" + (end - start)); + + } +} \ No newline at end of file diff --git a/java-advance/proxy/src/main/java/cn/cunchang/staticproxy/combination/TankLogProxy1.java b/java-advance/proxy/src/main/java/cn/cunchang/staticproxy/combination/TankLogProxy1.java new file mode 100644 index 00000000..2a02cca2 --- /dev/null +++ b/java-advance/proxy/src/main/java/cn/cunchang/staticproxy/combination/TankLogProxy1.java @@ -0,0 +1,24 @@ +package cn.cunchang.staticproxy.combination; + +import cn.cunchang.Moveable; + +/** + * @author cunchang + * @date 2021/5/9 9:57 上午 + */ +public class TankLogProxy1 implements Moveable { + + Moveable m; + public TankLogProxy1(Moveable m) { + super(); + this.m = m; + } + + @Override + public void move() { + System.out.println("Tank start...."); + m.move(); + System.out.println("Tank end...."); + } + +} \ No newline at end of file diff --git a/java-advance/proxy/src/main/java/cn/cunchang/staticproxy/combination/TankTimeProxy1.java b/java-advance/proxy/src/main/java/cn/cunchang/staticproxy/combination/TankTimeProxy1.java new file mode 100644 index 00000000..24a15a1f --- /dev/null +++ b/java-advance/proxy/src/main/java/cn/cunchang/staticproxy/combination/TankTimeProxy1.java @@ -0,0 +1,34 @@ +package cn.cunchang.staticproxy.combination; + +import cn.cunchang.Moveable; + +/** + * @author cunchang + * @date 2021/5/9 9:57 上午 + */ +public class TankTimeProxy1 implements Moveable { + + Moveable m; + public TankTimeProxy1(Moveable m) { + super(); + this.m = m; + } + @Override + public void move() { + //计算方法运行了多长时间 + long start = System.currentTimeMillis(); + m.move(); + long end = System.currentTimeMillis(); + System.out.println("耗时:"+(end-start)); + } + +// @Override +// public void stop() { +// //计算方法运行了多长时间 +// long start = System.currentTimeMillis(); +// System.out.println("start:"+start); +// m.stop(); +// long end = System.currentTimeMillis(); +// System.out.println("耗时:"+(end-start)); +// } +} \ No newline at end of file diff --git a/java-advance/proxy/src/main/java/cn/cunchang/staticproxy/inherit/TankLogTimeProxy.java b/java-advance/proxy/src/main/java/cn/cunchang/staticproxy/inherit/TankLogTimeProxy.java new file mode 100644 index 00000000..4130a607 --- /dev/null +++ b/java-advance/proxy/src/main/java/cn/cunchang/staticproxy/inherit/TankLogTimeProxy.java @@ -0,0 +1,14 @@ +package cn.cunchang.staticproxy.inherit; + +public class TankLogTimeProxy extends TankTimeProxy { + + @Override + public void move() { + //记录日志 + System.out.println("Tank start...."); + super.move(); + System.out.println("Tank end...."); + } + + +} \ No newline at end of file diff --git a/java-advance/proxy/src/main/java/cn/cunchang/staticproxy/inherit/TankTimeProxy.java b/java-advance/proxy/src/main/java/cn/cunchang/staticproxy/inherit/TankTimeProxy.java new file mode 100644 index 00000000..37144847 --- /dev/null +++ b/java-advance/proxy/src/main/java/cn/cunchang/staticproxy/inherit/TankTimeProxy.java @@ -0,0 +1,20 @@ +package cn.cunchang.staticproxy.inherit; + +import cn.cunchang.Tank; + +/** + * @author cunchang + * @date 2021/5/9 9:57 上午 + */ +public class TankTimeProxy extends Tank { + + @Override + public void move() { + //计算方法运行了多长时间 + long start = System.currentTimeMillis(); + super.move(); + long end = System.currentTimeMillis(); + System.out.println("耗时:"+(end-start)); + } + +} \ No newline at end of file diff --git a/java-advance/spi/README.md b/java-advance/spi/README.md new file mode 100644 index 00000000..260eecb1 --- /dev/null +++ b/java-advance/spi/README.md @@ -0,0 +1,21 @@ + +https://www.jianshu.com/p/46b42f7f593c + + +比如,我们日常使用是数据库驱动,会提供统一的规范(java.sql.Driver),各数据库服务商提供对应数据库的逻辑实现。当使用到该数据库时,直接引入不同的SPI服务实现即可。 + +常见场景: + +Spring框架中有大量实现,如上图中Spring对servlet3.0规范的ServletContainerInitializer的实现。 +数据库驱动程序加载不同数据库的实现,如上图中java.sql.Driver接口的实现。 +日志框架log4j中的实现。 +Dubbo中实现框架扩展的实现。 + +使用规范,下面了解一下使用SPI的基本规范步骤: + +服务提供者定义对外接口及方法,比如数据库驱动会提供一个java.sql.Driver的接口。 +针对定义的接口,提供一个实现类。 +在项目或jar包的META-INF/services目录下,创建一个文本文件:名称为接口的“全限定名”,内容为实现类的全限定名(包+实现类名)。上面的截图中其实已经可以发现,统一都是如此。 +服务调用者引入该项目的jar包,并将其放置于classpath下。 +服务调用者通过核心API java.util.ServiceLoader来动态加载该实现,主要就是扫描classpath下所有jar包内META-INF/services目录下,按照指定格式定义的文件,并把其中类进行加载。 +由于SPI机制使用的过程中无法进行传递构造参数,因此需提供一个无参的构造方法。 diff --git a/java-advance/spi/pom.xml b/java-advance/spi/pom.xml new file mode 100644 index 00000000..5f6216be --- /dev/null +++ b/java-advance/spi/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + cn.cunchang + spi + pom + 1.0-SNAPSHOT + + spi-jdbc-interface + spi-mysql + spi-oracle + web-client + + + + 8 + 8 + + + \ No newline at end of file diff --git a/java-advance/spi/spi-jdbc-interface/pom.xml b/java-advance/spi/spi-jdbc-interface/pom.xml new file mode 100644 index 00000000..257f4ee6 --- /dev/null +++ b/java-advance/spi/spi-jdbc-interface/pom.xml @@ -0,0 +1,19 @@ + + + + spi + cn.cunchang + 1.0-SNAPSHOT + + 4.0.0 + + spi-jdbc-interface + + + 8 + 8 + + + \ No newline at end of file diff --git a/java-advance/spi/spi-jdbc-interface/src/main/java/cn/jdbc/Driver.java b/java-advance/spi/spi-jdbc-interface/src/main/java/cn/jdbc/Driver.java new file mode 100644 index 00000000..765f35b4 --- /dev/null +++ b/java-advance/spi/spi-jdbc-interface/src/main/java/cn/jdbc/Driver.java @@ -0,0 +1,22 @@ +package cn.jdbc; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * spi-interface: 是针对厂商定义的接口项目,只提供接口,不提供实现 + *

+ * 服务接口 (Service Interface),这是提供者实现的 + * Connection口就是其服务接口 + * + * @author lastwhisper + */ +public interface Driver { + + public boolean available(String url, + String user, String password); + + + public Connection getConnection() throws SQLException; + +} diff --git a/java-advance/spi/spi-jdbc-interface/src/main/java/cn/jdbc/DriverManager.java b/java-advance/spi/spi-jdbc-interface/src/main/java/cn/jdbc/DriverManager.java new file mode 100644 index 00000000..3c088e3e --- /dev/null +++ b/java-advance/spi/spi-jdbc-interface/src/main/java/cn/jdbc/DriverManager.java @@ -0,0 +1,52 @@ +package cn.jdbc; + + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.ServiceLoader; + +/** + * spi-core: 是提供给用户使用的核心jar文件, + * 同样依赖于interface项目, 用户使用时需要引入spi-core.jar和厂商具体实现的jar + *

+ * 提供者注册 API ( Provider Registration API),这是提供者用来注册实现的 + * DriverManager.registerDriver是提供者注册API + *

+ * 服务访问 API (Service Access API),这是客户端用来获取服务的实例 + * DriverManager.getConnection 是服务访问 API + * + * @author lastwhisper + */ +public class DriverManager { + + public static List driverList; + + static { + registerDriver(); + } + + private static void registerDriver() { + ServiceLoader services = ServiceLoader.load(Driver.class); + driverList = new ArrayList<>(); + for (Driver driver : services) { + driverList.add(driver); + } + } + + + public static Driver getDriver(String url, + String user, String password) { + if (Objects.isNull(driverList)) { + throw new IllegalStateException("未找到 Driver 的实现"); + } + System.out.println("找到" + driverList.size() + "个jdbc实现驱动"); + for (Driver driver : driverList) { + if (driver.available(url, user, password)) { + return driver; + } + } + throw new IllegalStateException("未找到 Driver 的实现"); + } + +} diff --git a/java-advance/spi/spi-mysql/pom.xml b/java-advance/spi/spi-mysql/pom.xml new file mode 100644 index 00000000..7ee7a542 --- /dev/null +++ b/java-advance/spi/spi-mysql/pom.xml @@ -0,0 +1,26 @@ + + + + spi + cn.cunchang + 1.0-SNAPSHOT + + 4.0.0 + + spi-mysql + + + 8 + 8 + + + + + cn.cunchang + spi-jdbc-interface + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/java-advance/spi/spi-mysql/src/main/java/cn/mysql/MysqlDriver.java b/java-advance/spi/spi-mysql/src/main/java/cn/mysql/MysqlDriver.java new file mode 100644 index 00000000..cbb5f792 --- /dev/null +++ b/java-advance/spi/spi-mysql/src/main/java/cn/mysql/MysqlDriver.java @@ -0,0 +1,34 @@ +package cn.mysql; + + +import cn.jdbc.Driver; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * MysqlDriver/OracleDriver: 分别是两个厂商对interface的不同实现,所以他们会依赖于interface项目 + * + * @author lastwhisper + */ +public class MysqlDriver implements Driver { + + static { + System.out.println("加载mysql driver"); + } + + @Override + public boolean available(String url, String user, String password) { + if (url != null && url.contains("mysql")) { + System.out.println("成功注册mysql驱动"); + return true; + } + return false; + } + + @Override + public Connection getConnection() throws SQLException { + // return new MysqlConnection(); + return null; + } +} diff --git a/java-advance/spi/spi-mysql/src/main/resources/META-INF/services/cn.jdbc.Driver b/java-advance/spi/spi-mysql/src/main/resources/META-INF/services/cn.jdbc.Driver new file mode 100644 index 00000000..8ff7ab24 --- /dev/null +++ b/java-advance/spi/spi-mysql/src/main/resources/META-INF/services/cn.jdbc.Driver @@ -0,0 +1 @@ +cn.mysql.MysqlDriver \ No newline at end of file diff --git a/java-advance/spi/spi-oracle/pom.xml b/java-advance/spi/spi-oracle/pom.xml new file mode 100644 index 00000000..b79f1a95 --- /dev/null +++ b/java-advance/spi/spi-oracle/pom.xml @@ -0,0 +1,26 @@ + + + + spi + cn.cunchang + 1.0-SNAPSHOT + + 4.0.0 + + spi-oracle + + + 8 + 8 + + + + + cn.cunchang + spi-jdbc-interface + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/java-advance/spi/spi-oracle/src/main/java/cn/oracle/OracleDriver.java b/java-advance/spi/spi-oracle/src/main/java/cn/oracle/OracleDriver.java new file mode 100644 index 00000000..ffaed4be --- /dev/null +++ b/java-advance/spi/spi-oracle/src/main/java/cn/oracle/OracleDriver.java @@ -0,0 +1,34 @@ +package cn.oracle; + + +import cn.jdbc.Driver; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * spi-boy/spi-gril: 分别是两个厂商对interface的不同实现,所以他们会依赖于interface项目 + * + * @author lastwhisper + */ +public class OracleDriver implements Driver { + + static { + System.out.println("加载oracle driver"); + } + + @Override + public boolean available(String url, String user, String password) { + if (url != null && url.contains("oracle")) { + System.out.println("成功注册oracle驱动"); + return true; + } + return false; + } + + @Override + public Connection getConnection() throws SQLException { + // return new OracleConnection(); + return null; + } +} diff --git a/java-advance/spi/spi-oracle/src/main/resources/META-INF/services/cn.jdbc.Driver b/java-advance/spi/spi-oracle/src/main/resources/META-INF/services/cn.jdbc.Driver new file mode 100644 index 00000000..50ae9acc --- /dev/null +++ b/java-advance/spi/spi-oracle/src/main/resources/META-INF/services/cn.jdbc.Driver @@ -0,0 +1 @@ +cn.oracle.OracleDriver \ No newline at end of file diff --git a/java-advance/spi/web-client/pom.xml b/java-advance/spi/web-client/pom.xml new file mode 100644 index 00000000..75130634 --- /dev/null +++ b/java-advance/spi/web-client/pom.xml @@ -0,0 +1,32 @@ + + + + spi + cn.cunchang + 1.0-SNAPSHOT + + 4.0.0 + + web-client + + + 8 + 8 + + + + + cn.cunchang + spi-mysql + 1.0-SNAPSHOT + + + + cn.cunchang + spi-oracle + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/java-advance/spi/web-client/src/main/java/cn/lastwhisper/JdbcUtil.java b/java-advance/spi/web-client/src/main/java/cn/lastwhisper/JdbcUtil.java new file mode 100644 index 00000000..1501aa8d --- /dev/null +++ b/java-advance/spi/web-client/src/main/java/cn/lastwhisper/JdbcUtil.java @@ -0,0 +1,27 @@ +package cn.lastwhisper; + + +import cn.jdbc.Driver; +import cn.jdbc.DriverManager; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * @author cunchang + * @date 2022/5/8 7:17 PM + */ +public class JdbcUtil { + + public static void main(String[] args) throws SQLException { + String user = "root"; + String password = "12456"; + String url = "jdbc:mysql://47.100.54.177:3637/mysqlstudy?characterEnconding=UTF-8"; + + // 拿到jdbc链接搞事情 + Driver driver = DriverManager.getDriver(url, user, password); + System.out.println("客户端获取driver:" + driver); + Connection connection = driver.getConnection(); + } + +} diff --git a/java-advance/spi/web-client/src/main/resources/META-INF/services/cn.jdbc.Driver b/java-advance/spi/web-client/src/main/resources/META-INF/services/cn.jdbc.Driver new file mode 100644 index 00000000..9ab433f5 --- /dev/null +++ b/java-advance/spi/web-client/src/main/resources/META-INF/services/cn.jdbc.Driver @@ -0,0 +1 @@ +#cn.mysql.MysqlDriver \ No newline at end of file diff --git a/java-basic/basic/pom.xml b/java-basic/basic/pom.xml new file mode 100644 index 00000000..e2243446 --- /dev/null +++ b/java-basic/basic/pom.xml @@ -0,0 +1,114 @@ + + + + 4.0.0 + basic + cn.lastwhisper + 0.0.1-SNAPSHOT + + + + + junit + junit + 4.13 + + + + + org.slf4j + slf4j-api + 1.7.26 + + + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.9.1 + + + + + org.apache.logging.log4j + log4j-api + 2.11.1 + + + + + org.apache.logging.log4j + log4j-core + 2.11.1 + + + + + com.alibaba + fastjson + 1.2.80 + + + + + org.projectlombok + lombok + 1.18.22 + + + + + com.google.guava + guava + 30.1.1-jre + + + + + cn.hutool + hutool-all + 5.8.0 + + + + + com.belerweb + pinyin4j + 2.5.0 + + + + + org.springframework + spring-expression + 5.2.7.RELEASE + + + + org.apache.commons + commons-lang3 + 3.11 + + + + commons-collections + commons-collections + 3.2.2 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/java-basic/basic/src/main/java/cn/cunchang/Jsq.java b/java-basic/basic/src/main/java/cn/cunchang/Jsq.java new file mode 100644 index 00000000..e0258ac2 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/Jsq.java @@ -0,0 +1,162 @@ +package cn.cunchang; + + + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextField; + +public class Jsq extends JFrame implements ActionListener{ + private final String[] KEYS = {"7","8","9","/","4","5","6","*","1","2","3","-","0",".","=","+"}; + + private JTextField resultText = new JTextField("hello world");//文本框 + private JButton Clear = new JButton("C"); + private JButton keys[] = new JButton[KEYS.length];//定义数组 + + // 标志用户按的是否是整个表达式的第一个数字,或者是运算符后的第一个数字 + private boolean firstDigit = true; + // 计算的中间结果。 + private double resultNum = 0.0; + // 当前运算的运算符 + private String operator = "="; + // 操作是否合法 + private boolean operateValidFlag = true; + + public Jsq() { + super("计算器");//设置窗体标题 + this.setSize(300, 300); + this.setLocationRelativeTo(null);//设置窗体的相对位置(屏幕中间) + this.setResizable(true);// 修改计算器的大小,默认是true.如果是false,则不能拉伸。 + init(); + + } + + + private void init() { + // 建立一个画板放文本框和清空按钮。 + JPanel top = new JPanel(); + top.setLayout(new BorderLayout());//边框的布局管理器,设置样式 + resultText.setHorizontalAlignment(JTextField.RIGHT);// Java文本框左右对齐属性;文本框中的内容采用右对齐方式。 + resultText.setEditable(false);// 不允许修改结果文本框,使调用这个函数的控件不能被编辑。 + resultText.setBackground(Color.white); + top.add("Center", resultText);//文本框位于top画板中间。 + Clear.setForeground(Color.red); + Clear.setBackground(Color.black);//黑色 + top.add("East",Clear); + + JPanel calckeysPanel = new JPanel(); // 建立另一个画板放按键 + calckeysPanel.setLayout(new GridLayout(4, 4, 5, 5)); + // 用网格布局器,4行,4列的网格,网格之间的水平方向间隔为5个象素,垂直方向间隔为5个象素 + for (int i = 0; i < KEYS.length; i++) { //从keys0开始数。 + keys[i] = new JButton(KEYS[i]); + keys[i].setForeground(Color.blue); + keys[i].setFont(new Font("alias", Font.PLAIN, 6)); + calckeysPanel.add(keys[i]); + } + keys[3].setForeground(Color.red); + keys[7].setForeground(Color.red); + keys[11].setForeground(Color.red); + keys[14].setForeground(Color.red); + keys[15].setForeground(Color.red); + + // 整体布局 + getContentPane().setLayout(new BorderLayout());//布局管理器 + getContentPane().add("North", top); + getContentPane().add("Center", calckeysPanel); + +// 为各按钮添加事件侦听器,都使用同一个事件侦听器,即本对象。 本类的声明中有implements ActionListener(能点击按钮) + for (int i = 0; i < KEYS.length; i++) { + keys[i].addActionListener(this);//this表示当前类的对象 + } + Clear.addActionListener(this); + + } + + public void actionPerformed(ActionEvent e) { + // 获取事件源的标签 + String label = e.getActionCommand();//返回的是当前动作指向对象的名称 + + if (label.equals("C")) {// 用户按了"C"键 + resultText.setText("0"); + firstDigit = true; + operator = "="; + } else if ("0123456789.".indexOf(label) >= 0) { // 用户按了数字键或者小数点键(按下任何一个数字进行运算) + handleNumber(label); + } else { + handleOperator(label);// 用户按了运算符键 + } + } + + //处理数字键被按下的事件 + private void handleNumber(String key) { + if (firstDigit) { + // 输入的第一个数字 + resultText.setText(key);//向text中放置数值 + } + else { + resultText.setText(resultText.getText() + key);//获取text的值 + } + firstDigit = false; + } + + //处理运算符键被按下的事件 + private void handleOperator(String key) { + if (operator.equals("/")) { + // 除法运算 + // 如果当前结果文本框中的值等于0 + if (getNumberFromText() == 0.0) { + operateValidFlag = false;// 操作不合法 + resultText.setText("除数不能为0"); + } else { + resultNum /= getNumberFromText(); + } + } else if (operator.equals("+")) { // 加法运算 + resultNum += getNumberFromText(); + } else if (operator.equals("-")) {// 减法运算 + resultNum -= getNumberFromText(); + } else if (operator.equals("*")) {// 乘法运算 + resultNum *=getNumberFromText(); + } + if (operator.equals("+/-")) {// 正负数运算 + resultNum = resultNum * (-1); + } else if (operator.equals("=")) { // 赋值运算 + resultNum = getNumberFromText(); + } + + if (operateValidFlag) { // 双精度浮点数的运算 + long t1; + double t2; + t1 = (long) resultNum; + t2 = resultNum - t1; + if (t2 == 0) { + resultText.setText(String.valueOf(t1)); + } else { + resultText.setText(String.valueOf(resultNum)); + } + } + // 运算符等于用户按的按钮 + operator = key; + firstDigit = true; + operateValidFlag = true; + } + //从结果文本框中获取数字 + private double getNumberFromText() { //得到结果 + double result = 0; + try { + result = Double.valueOf(resultText.getText()).doubleValue(); + } catch (NumberFormatException e) { + } + return result; + } + + public static void main(String args[]) { + Jsq jsq = new Jsq(); + jsq.setVisible(true);//窗口是否可见 + jsq.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置点击窗体右上角的关闭图标后,结束应用。 + } +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/Main.java b/java-basic/basic/src/main/java/cn/cunchang/Main.java new file mode 100644 index 00000000..15d95195 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/Main.java @@ -0,0 +1,60 @@ +package cn.cunchang; + +import com.alibaba.fastjson.JSON; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author kaisui + * @description + * @date 2022/12/26 + */ +public class Main { + static Map map = new HashMap<>(); + + /** + * 判断数组中的数是否可以组成另一个数 + * a*n+b*m=c + */ + public static void main(String[] args) { + // a*n+b*m=c + //1、n=1、m=1 || n=0||m==0 + Integer[] arr = {50, 10}; + int c = 60; + //2、n>1,m=1 || n=1,m>1 +// Integer[] arr = {50, 10}; +// int c = 110; + // + //3、n>1,m>1 +// Integer[] arr = {50, 90}; +// Integer[] arr = {50, 80}; +// int c = 260; + boolean xxxx = xxxx(arr, c); + if (xxxx) { + System.out.println("找到了:" + JSON.toJSONString(map)); + } else { + System.out.println("没找到"); + } + } + + private static boolean xxxx(Integer[] arr, int c) { + if (c == 0) { + return true; + } + if (c < 0) { + return false; + } + for (int i = 0; i < arr.length; i++) { + map.put(arr[i], map.getOrDefault(arr[i], 0) + 1); + c = c - arr[i]; + if (xxxx(arr, c)) { + return true; + } + // 回溯 + c = c + arr[i]; + map.put(arr[i], map.get(arr[i]) - 1); + } + return false; + } +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/README.md b/java-basic/basic/src/main/java/cn/cunchang/README.md new file mode 100644 index 00000000..637c7a4d --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/README.md @@ -0,0 +1,9 @@ + +- collection 集合相关操作 +- cpu 控制cpu的利用率 +- decimal decimal相关操作 +- packagesacn 扫包 +- regex 正则表达式 +- sugar java语法糖 +- sysproperty 系统变量 +- trycatch trycatch相关操作 \ No newline at end of file diff --git a/java-basic/basic/src/main/java/cn/cunchang/RandomTest.java b/java-basic/basic/src/main/java/cn/cunchang/RandomTest.java new file mode 100644 index 00000000..1351be61 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/RandomTest.java @@ -0,0 +1,36 @@ +package cn.cunchang; + +import java.util.Random; + +/** + * @author cunchang + * @date 2022/6/16 1:51 PM + */ +public class RandomTest { + + static int stock = 10000; + + public static void main(String[] args) { + Random random = new Random(); + + for (int i = 0; i < 1000000; i++) { + int nextInt = random.nextInt(100); + if (nextInt == 1) { + if (!deduct()) { + break; + } + System.out.println("用户" + i + "抢到了"); + } + } + } + + public static boolean deduct() { + if (stock < 0) { + System.out.println("抢完了"); + return false; + } + stock--; + return true; + } + +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/collection/ArraysTest.java b/java-basic/basic/src/main/java/cn/cunchang/collection/ArraysTest.java new file mode 100644 index 00000000..dceda74b --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/collection/ArraysTest.java @@ -0,0 +1,48 @@ +package cn.cunchang.collection; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +/** + * + * @author cunchang + * @date 2021/6/23 2:37 下午 + */ +public class ArraysTest { + + @Test + public void test1Arrays的坑(){ + // 一个参数 + int[] arr = {1,2,3}; + List list = Arrays.asList(arr); + System.out.println(list); + System.out.println(list.size()); + // 三个参数 + list = Arrays.asList(1,2,3); + System.out.println(list); + System.out.println(list.size()); + } + + @Test + public void test2Arrays的坑(){ + String[] arr = {"欢迎","关注","Java"}; + List list = Arrays.asList(arr); + System.out.println("arr="+Arrays.toString(arr)); + arr[1] = "爱上"; + list.set(2,"我"); + System.out.println("修改list,arr也会被修改="+Arrays.toString(arr)); + System.out.println("修改arr,list也会被修改="+list); + } + + @Test + public void test3Arrays的坑(){ + String[] arr = {"欢迎","关注","Java"}; + List list = Arrays.asList(arr); + System.out.println("arr="+Arrays.toString(arr)); + list.add("新增"); + list.remove("关注"); + } + +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/collection/Intersection.java b/java-basic/basic/src/main/java/cn/cunchang/collection/Intersection.java new file mode 100644 index 00000000..da13c826 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/collection/Intersection.java @@ -0,0 +1,59 @@ +package cn.cunchang.collection; + +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +/** + * 集合运算 - Java实现集合的交、并、差 + * @author cunchang + * @date 2020/7/22 11:43 + */ +public class Intersection { + + @Test + public void test1(){ + + } + + public static void main(String[] args) { + + HashSet set1 = new HashSet() { + private static final long serialVersionUID = 1L; + { + add(1); + add(2); + }}; + + HashSet set2 = new HashSet(){ + private static final long serialVersionUID = 1L; + { + add(2); + add(3); + }}; + System.out.println("set1:"+set1); + System.out.println("set2:"+set2); + + HashSet result = new HashSet(); + + //交集 + result.addAll(set1); + result.retainAll(set2); + System.out.println("交集:"+result);//交集:[2] + + //差集 + result.clear(); + result.addAll(set1); + result.removeAll(set2); + System.out.println("set1-set2,差集:"+result);//差集:[1] + + //并集 + result.clear(); + result.addAll(set1); + result.addAll(set2); + System.out.println("并集:"+result);//并集:[1, 2, 3] + + } + +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/collection/README.md b/java-basic/basic/src/main/java/cn/cunchang/collection/README.md new file mode 100644 index 00000000..b65e0c5d --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/collection/README.md @@ -0,0 +1,3 @@ + +- Arrays https://blog.csdn.net/AlbenXie/article/details/103051176 + diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/cpu/ControlCpu.java b/java-basic/basic/src/main/java/cn/cunchang/cpu/ControlCpu.java similarity index 93% rename from java-basic/interview/src/main/java/cn/lastwhisper/interview/cpu/ControlCpu.java rename to java-basic/basic/src/main/java/cn/cunchang/cpu/ControlCpu.java index 34dfc6d6..9af7cbba 100644 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/cpu/ControlCpu.java +++ b/java-basic/basic/src/main/java/cn/cunchang/cpu/ControlCpu.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.interview.cpu; +package cn.cunchang.cpu; /** * 控制cpu利用率 diff --git a/java-basic/basic/src/main/java/cn/cunchang/date/AggregateTypeEnum.java b/java-basic/basic/src/main/java/cn/cunchang/date/AggregateTypeEnum.java new file mode 100644 index 00000000..ad59cebf --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/date/AggregateTypeEnum.java @@ -0,0 +1,66 @@ +package cn.cunchang.date; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.time.LocalDate; +import java.time.temporal.IsoFields; + +/** + * 聚合类型 + * + * @author cunchang + * @date 2020/11/4 17:10 + */ +@Getter +@AllArgsConstructor +public enum AggregateTypeEnum { + + 月(1, "月", 1), + 季(2, "季", 3), + 半年(3, "半年", 6), + 年(4, "年", 12), + + ; + private Integer code; + private String desc; + /** + * 步长 + */ + private Integer step; + + + /** + * 输出格式化日期 + * + * @param localDate + * @return + */ + public String format(LocalDate localDate) { + String topCategoryName = null; + switch (this) { + case 月: + topCategoryName = localDate.getYear() + "年" + localDate.getMonthValue() + "月"; + break; + case 季: + int quarter = localDate.get(IsoFields.QUARTER_OF_YEAR); + topCategoryName = localDate.getYear() + "年" + "Q" + quarter; + break; + case 半年: + quarter = localDate.get(IsoFields.QUARTER_OF_YEAR); + if (quarter <= 2) { + topCategoryName = localDate.getYear() + "年" + "上半年"; + } + if (quarter >= 3) { + topCategoryName = localDate.getYear() + "年" + "下半年"; + } + break; + case 年: + topCategoryName = localDate.getYear() + "年"; + break; + default: + + } + return topCategoryName; + } +} \ No newline at end of file diff --git a/java-basic/basic/src/main/java/cn/cunchang/date/LocalDateTest.java b/java-basic/basic/src/main/java/cn/cunchang/date/LocalDateTest.java new file mode 100644 index 00000000..12675870 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/date/LocalDateTest.java @@ -0,0 +1,83 @@ +package cn.cunchang.date; + +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +import java.time.LocalDate; +import java.time.Period; +import java.util.List; + +/** + * @author cunchang + * @date 2021/7/14 11:31 上午 + */ +@Slf4j +public class LocalDateTest { + + /** + * 日期循环 + */ + @Test + public void test1() { + LocalDate startDate = LocalDateUtil.parse4YYYYMMdd("20210601"); + LocalDate endDate = LocalDateUtil.parse4YYYYMMdd("20210610"); + + // [20210601,20210610) +// while (startDate.isBefore(endDate)) { +// System.out.println(startDate); +// startDate = startDate.plusDays(1L); +// } + + // (20210601,20210610] +// while (endDate.isAfter(startDate)) { +// System.out.println(endDate); +// endDate = endDate.plusDays(-1L); +// } + + // [20210601,20210610] + while (!startDate.isAfter(endDate)) { + System.out.println(startDate); + startDate = startDate.plusDays(1L); + } + + // [20210601,20210610] +// while (!endDate.isBefore(startDate)) { +// System.out.println(endDate); +// endDate = endDate.plusDays(-1L); +// } + } + + /** + * 日期格式化 + */ + @Test + public void test2() { + log.info(AggregateTypeEnum.月.format(LocalDate.now())); + } + + /** + * 日期分割 + */ + @Test + public void test3() { + LocalDate startDate = LocalDateUtil.parseStr("20210101", LocalDateUtil.yyyyMMdd); + LocalDate endDate = LocalDateUtil.parseStr("20210630", LocalDateUtil.yyyyMMdd); + + AggregateTypeEnum aggregateTypeEnum = AggregateTypeEnum.月; + + // 分割日期 + List> regionDates = LocalDateUtil.splitByStep(startDate, endDate, aggregateTypeEnum.getStep()); + + log.info(JSONObject.toJSONString(regionDates)); + } + + @Test + public void test4() { + LocalDate startDate=LocalDate.now().plusDays(-1), endDate=LocalDate.now(); + // 日期之差 + Long dayDiv = endDate.toEpochDay() - startDate.toEpochDay(); + System.out.println("startDate:"+startDate+" endDate:"+endDate +" dayDiv:"+dayDiv); + } + +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/date/LocalDateUtil.java b/java-basic/basic/src/main/java/cn/cunchang/date/LocalDateUtil.java new file mode 100644 index 00000000..a0fb3b71 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/date/LocalDateUtil.java @@ -0,0 +1,287 @@ +package cn.cunchang.date; + + +import java.time.*; +import java.time.format.DateTimeFormatter; +import java.time.temporal.IsoFields; +import java.time.temporal.TemporalAdjusters; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Objects; + +public class LocalDateUtil { + /** + * yyyy-MM-dd HH:MM:ss + */ + public final static String yyyyMMddHHMMss = "yyyy-MM-dd HH:MM:ss"; + + /** + * yyyy-MM-dd HH:MM:ss + */ + public final static String yyyyMMddHHMMssTime = "yyyyMMddHHMMss"; + + /** + * yyyyMMdd + */ + public final static String yyyyMMdd = "yyyyMMdd"; + + /** + * yyyyMM + */ + public final static String yyyyMM = "yyyyMM"; + + /** + * yyyyMM + */ + public final static String yyMM = "yyMM"; + + public final static DateTimeFormatter YYYYMMDD_FORMATTER = DateTimeFormatter.ofPattern(yyyyMMdd); + + + /** + * 字符串转日期 + */ + public static LocalDate parseStr(String date, String pattern) { + if (Objects.isNull(pattern) || Objects.isNull(date)) { + return null; + } + return LocalDate.parse(date, DateTimeFormatter.ofPattern(pattern)); + } + + /** + * 获取日期对应的月份数字, + * + * @param billDate 格式20200405 + */ + public static Integer getMonth(Integer billDate) { + if (Objects.isNull(billDate)) { + return null; + } + //月账单时间格式202010 + String billMonth = String.valueOf(billDate).substring(0, 6); + return Integer.valueOf(billMonth); + } + + /** + * 字符串转日期 -yyyyMMdd + */ + public static LocalDate parse4YYYYMMdd(String date) { + if (Objects.isNull(date)) { + return null; + } + return LocalDate.parse(date, DateTimeFormatter.ofPattern(yyyyMMdd)); + } + + /** + * Date转换为LocalDateTime + */ + + public static LocalDateTime convertDateToLDT(Date date) { + if (Objects.isNull(date)) { + return null; + } + return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); + } + + /** + * Date转换为LocalDateTime + */ + + public static LocalDate convertDateToLD(Date date) { + if (Objects.isNull(date)) { + return null; + } + return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).toLocalDate(); + } + + /** + * LocalDateTime转换为Date + */ + public static Date convertLDTToDate(LocalDateTime time) { + if (Objects.isNull(time)) { + return null; + } + + return Date.from(time.atZone(ZoneId.systemDefault()).toInstant()); + } + + /** + * 获取指定日期的毫秒 + */ + public static Long getMilliByTime(LocalDateTime time) { + if (Objects.isNull(time)) { + return null; + } + return time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + } + + /** + * 获取指定日期的毫秒 + */ + public static Long getMilliByDate(LocalDate date) { + if (Objects.isNull(date)) { + return null; + } + return getMilliByTime(date.atStartOfDay()); + } + + /** + * 获取指定时间的指定格式 + */ + public static String formatTime(LocalDateTime time, String pattern) { + if (Objects.isNull(time) || Objects.isNull(pattern)) { + return null; + } + return time.format(DateTimeFormatter.ofPattern(pattern)); + } + + /** + * 获取指定时间的指定格式,返回格式20201112 + */ + public static Integer formatIntTime(LocalDate time) { + if (Objects.isNull(time)) { + return null; + } + String date = time.format(YYYYMMDD_FORMATTER); + return Integer.valueOf(date); + } + + /** + * 获取指定时间的指定格式 + */ + public static String formatTime(LocalDate time, String pattern) { + if (Objects.isNull(time) || Objects.isNull(pattern)) { + return null; + } + return time.format(DateTimeFormatter.ofPattern(pattern)); + } + + + /** + * 获取指定时间的指定格式 + */ + public static String formatTimeYYYYMMDD(LocalDate time) { + if (Objects.isNull(time)) { + return null; + } + return time.format(YYYYMMDD_FORMATTER); + } + + /** + * 获取当前时间的指定格式 + */ + public static String formatNow(String pattern) { + if (Objects.isNull(pattern)) { + return null; + } + return formatTime(LocalDateTime.now(), pattern); + } + + /** + * 获取一天的开始时间,2017,7,22 00:00 + */ + public static LocalDateTime getDayStart(LocalDateTime time) { + if (Objects.isNull(time)) { + return null; + } + return time.withHour(0) + .withMinute(0) + .withSecond(0); + } + + //获取一天的结束时间,2017,7,22 23:59:59.999999999 + public static LocalDateTime getDayEnd(LocalDateTime time) { + if (Objects.isNull(time)) { + return null; + } + return time.withHour(23) + .withMinute(59) + .withSecond(59); + } + + + /** + * 按步长分割日期 + *

+ * 20210101~20210630 =》 + * [2021-01-01=2021-01-31, 2021-02-01=2021-02-28, 2021-03-01=2021-03-31, + * 2021-04-01=2021-04-30, 2021-05-01=2021-05-31, 2021-06-01=2021-06-30, + * 2021-07-01=2021-07-31, 2021-08-01=2021-08-31, 2021-09-01=2021-09-30, + * 2021-10-01=2021-10-31, 2021-11-01=2021-11-30, 2021-12-01=2021-12-31, + * 2022-01-01=2022-01-31, 2022-02-01=2022-02-28, 2022-03-01=2022-03-31, + * 2022-04-01=2022-04-30, 2022-05-01=2022-05-31, 2022-06-01=2022-06-30, + * 2022-07-01=2022-07-31, 2022-08-01=2022-08-31, 2022-09-01=2022-09-30, + * 2022-10-01=2022-10-31, 2022-11-01=2022-11-30, 2022-12-01=2022-12-31] + * --------------- + * 20210101~20210630 =》 + * [2021-01-01=2021-03-31, 2021-04-01=2021-06-30, 2021-07-01=2021-09-30, 2021-10-01=2021-12-31, + * 2022-01-01=2022-03-31, 2022-04-01=2022-06-30, 2022-07-01=2022-09-30, 2022-10-01=2022-12-31] + * --------------- + * 20210101~20210630 =》 + * [2021-01-01=2021-06-30, 2021-07-01=2021-12-31, + * 2022-01-01=2022-06-30, 2022-07-01=2022-12-31] + * --------------- + * 20210101~20210630 =》 + * [2021-01-01=2021-12-31, 2022-01-01=2022-12-31] + * + * @param startDate 20210101 + * @param endDate 20210630 + * @param step 步长 {@link AggregateTypeEnum} + * @return <起始日期,结束日期> + */ + public static List> splitByStep(LocalDate startDate, LocalDate endDate, int step) { + LocalDate firstDayOfMonth = startDate.with(TemporalAdjusters.firstDayOfMonth()); + if(!Objects.equals(startDate, firstDayOfMonth)){ + throw new IllegalArgumentException(String.format("起始日期必须是月份第一天,startDate:%s", startDate)); + } + + LocalDate lastDayOfMonth = endDate.with(TemporalAdjusters.lastDayOfMonth()); + if(!Objects.equals(endDate, lastDayOfMonth)){ + throw new IllegalArgumentException(String.format("结束日期必须是月份最后一天,endDate:%s", endDate)); + } + + List> list = new ArrayList<>(); + + while (startDate.isBefore(endDate)) { + // 下一个步长减1的末尾日期 + LocalDate nextStartDate = startDate.plusMonths(step - 1).with(TemporalAdjusters.lastDayOfMonth()); + list.add(new Pair<>(startDate, nextStartDate)); + // 下一个月的起始日期 + startDate = nextStartDate.plusDays(1L); + } + + return list; + } + + public static String format(LocalDate localDate, AggregateTypeEnum aggregateTypeEnum) { + String topCategoryName = null; + switch (aggregateTypeEnum) { + case 月: + topCategoryName = localDate.getYear() + "年" + localDate.getMonthValue() + "月"; + break; + case 季: + int quarter = localDate.get(IsoFields.QUARTER_OF_YEAR); + topCategoryName = localDate.getYear() + "年" + "Q" + quarter; + break; + case 半年: + quarter = localDate.get(IsoFields.QUARTER_OF_YEAR); + if (quarter <= 2) { + topCategoryName = localDate.getYear() + "年" + "上半年"; + } + if (quarter >= 3) { + topCategoryName = localDate.getYear() + "年" + "下半年"; + } + break; + case 年: + topCategoryName = localDate.getYear() + "年"; + break; + default: + + } + return topCategoryName; + } + + + +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/date/Pair.java b/java-basic/basic/src/main/java/cn/cunchang/date/Pair.java new file mode 100644 index 00000000..736b6495 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/date/Pair.java @@ -0,0 +1,42 @@ +package cn.cunchang.date; + +import java.io.Serializable; +import java.util.Objects; + +public class Pair implements Serializable { + private static final long serialVersionUID = 1L; + private final K key; + private final V value; + + public Pair(K key, V value) { + this.key = key; + this.value = value; + } + + public K getKey() { + return this.key; + } + + public V getValue() { + return this.value; + } + + public String toString() { + return "Pair [key=" + this.key + ", value=" + this.value + "]"; + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (!(o instanceof Pair)) { + return false; + } else { + Pair pair = (Pair)o; + return Objects.equals(this.getKey(), pair.getKey()) && Objects.equals(this.getValue(), pair.getValue()); + } + } + + public int hashCode() { + return Objects.hashCode(this.key) ^ Objects.hashCode(this.value); + } +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/decimal/BigDecimalTest.java b/java-basic/basic/src/main/java/cn/cunchang/decimal/BigDecimalTest.java new file mode 100644 index 00000000..29b643dc --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/decimal/BigDecimalTest.java @@ -0,0 +1,83 @@ +package cn.cunchang.decimal; + +import org.junit.Test; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * @author cunchang + * @date 2021/3/11 4:00 下午 + */ +public class BigDecimalTest { + + @Test + public void testBigDecimal格式化输出() { + // 浮点数的打印 + System.out.println(String.valueOf(new BigDecimal("1234567891231234.1234"))); + // 普通的数字字符串 + // 100.000 + System.out.println(new BigDecimal("100.000").toString()); + // 去除末尾多余的0 + System.out.println(new BigDecimal("100.000").stripTrailingZeros().toString()); + // 避免输出科学计数法 + System.out.println(new BigDecimal("100.000").stripTrailingZeros().toPlainString()); + } + + /** + * 一定要用字符串形式的构造函数,否则会出现精度问题 + */ + @Test + public void test构造BigDecimal的坑() { + BigDecimal bigDecimal1 = new BigDecimal(1.23); + String str1 = bigDecimal1.toString(); + System.out.println(str1);// 1.229999999999999982236431605997495353221893310546875 + BigDecimal bigDecimal2 = new BigDecimal("1.23"); + String str2 = bigDecimal2.toString(); + System.out.println(str2);// 1.23 + } + + /** + * BigDecimal.setScale()方法用于格式化小数点 + * setScale(1)表示保留一位小数,默认用四舍五入方式 + * setScale(1,BigDecimal.ROUND_DOWN)直接删除多余的小数位,如2.35会变成2.3 + * setScale(1,BigDecimal.ROUND_UP)进位处理,2.35变成2.4 + * setScale(1,BigDecimal.ROUND_HALF_UP)四舍五入,2.35变成2.4 + * setScaler(1,BigDecimal.ROUND_HALF_DOWN)四舍五入,2.35变成2.3,如果是5则向下舍 + * setScaler(1,BigDecimal.ROUND_CEILING)接近正无穷大的舍入 + * setScaler(1,BigDecimal.ROUND_FLOOR)接近负无穷大的舍入,数字>0和ROUND_UP作用一样,数字<0和ROUND_DOWN作用一样 + * setScaler(1,BigDecimal.ROUND_HALF_EVEN)向最接近的数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。 + */ + @Test + public void test格式化小数点() { + BigDecimal bigDecimal = new BigDecimal("3.1415926572358452"); + + BigDecimal bigDecimal1 = bigDecimal.setScale(4, RoundingMode.DOWN); + // 保留四位,不会四舍五入 + System.out.println(bigDecimal1);// 3.1415 + + BigDecimal bigDecimal2 = bigDecimal.setScale(4, RoundingMode.HALF_UP); + // 保留四位,会四舍五入 + System.out.println(bigDecimal2);// 3.1416 + } + + /** + * 一定要使用compareTo + */ + @Test + public void test比较大小() { + System.out.println(new BigDecimal("0").compareTo(new BigDecimal("0")) <= 0); + System.out.println(new BigDecimal("1").compareTo(new BigDecimal("0")) <= 0); + } + + @Test + public void test3() { + BigDecimal taxAmount = new BigDecimal("0.001"); + BigDecimal originTaxAmount = new BigDecimal("0.001"); + BigDecimal exchangeRate = new BigDecimal("1"); + BigDecimal calOriginTaxAmount = taxAmount.divide(exchangeRate, + 5, BigDecimal.ROUND_HALF_UP); + System.out.println(calOriginTaxAmount.compareTo(originTaxAmount) != 0); + } + +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/guava/bloomfilter/TestBloomFilter.java b/java-basic/basic/src/main/java/cn/cunchang/guava/bloomfilter/TestBloomFilter.java new file mode 100644 index 00000000..c99178c4 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/guava/bloomfilter/TestBloomFilter.java @@ -0,0 +1,23 @@ +package cn.cunchang.guava.bloomfilter; + +import com.google.common.hash.BloomFilter; +import com.google.common.hash.Funnel; +import com.google.common.hash.Funnels; + +public class TestBloomFilter { + + public static void main(String[] args) { + Funnel funnel = Funnels.integerFunnel(); + int size = 1000_000; + double errorChance = 0.001; //错误率 + BloomFilter filter = BloomFilter.create(funnel, size, errorChance); + for (int i = 0; i < size; i++) { + filter.put(i); + } + for (int i = 0; i < size; i++) { + if (!filter.mightContain(i)) { + System.out.println("发现不存在的数据 : " + i); + } + } + } +} \ No newline at end of file diff --git a/java-basic/basic/src/main/java/cn/cunchang/guava/cache/TestCache.java b/java-basic/basic/src/main/java/cn/cunchang/guava/cache/TestCache.java new file mode 100644 index 00000000..04db32ca --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/guava/cache/TestCache.java @@ -0,0 +1,40 @@ +package cn.cunchang.guava.cache; + +import com.google.common.cache.*; +import org.junit.Test; + +import java.util.concurrent.TimeUnit; + +/** + * Guava的Cache + * @author lastwhisper + * @date 2020/6/2 + */ +public class TestCache { + + // https://github.com/zhuzhenke/common-caches + @Test + public void testCacheUse() throws Exception{ + + LoadingCache loadingCache = CacheBuilder.newBuilder() + .expireAfterAccess(10, TimeUnit.SECONDS) + .maximumSize(1000) + .removalListener(new RemovalListener() { + @Override + public void onRemoval(RemovalNotification notification) { + + } + }) + .build(new CacheLoader() { + @Override + public String load(String key) throws Exception { + return key; + } + }); + + System.out.println(loadingCache.get("key")); + + + } + +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/guava/collection/MapTest.java b/java-basic/basic/src/main/java/cn/cunchang/guava/collection/MapTest.java new file mode 100644 index 00000000..0ea90360 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/guava/collection/MapTest.java @@ -0,0 +1,282 @@ +package cn.cunchang.guava.collection; + +import com.google.common.collect.*; +import org.junit.Test; + +import java.util.*; + +/** + * 参考:https://mp.weixin.qq.com/s/LOZ-p6divRjO9ZTcus101A + * + * @author cunchang + * @date 2022/3/17 1:54 PM + */ +public class MapTest { + + /** + *

+ * 案例:记录员工每个月工作的天数 + * 使用hashmap的话,得两个嵌套 + */ + @Test + public void test双键Map() { + // java中的Map只允许有一个key和一个value存在。 + // guava中的Table允许一个value存在两个key。Table中的两个key分别被称为rowKey和columnKey,也就是行和列。 + Table table = HashBasedTable.create(); + //存放元素 + table.put("Hydra", "Jan", 20); + table.put("Hydra", "Feb", 28); + + table.put("Trunks", "Jan", 28); + table.put("Trunks", "Feb", 16); + + //取出元素 + Integer dayCount = table.get("Hydra", "Feb"); + System.out.println("取出元素:" + dayCount); + +// 1、获得key或value的集合 + //rowKey或columnKey的集合 + System.out.println("---rowKey或columnKey的集合"); + Set rowKeys = table.rowKeySet(); + Set columnKeys = table.columnKeySet(); + //value集合 + Collection values = table.values(); + System.out.println("rowKeys:" + rowKeys); + System.out.println("columnKeys:" + columnKeys); + System.out.println("values:" + values); + +// 2、计算key对应的所有value的和 + // 以统计所有rowKey对应的value之和为例: + System.out.println("---统计所有rowKey对应的value之和"); + for (String key : table.rowKeySet()) { + Set> rows = table.row(key).entrySet(); + int total = 0; + for (Map.Entry row : rows) { + total += row.getValue(); + } + System.out.println(key + ": " + total); + } +// 3、转换rowKey和columnKey + // 行和列的转置,直接调用Tables的静态方法transpose + System.out.println("---行和列的转置"); + Table table2 = Tables.transpose(table); + Set> cells = table2.cellSet(); + cells.forEach(cell -> + System.out.println(cell.getRowKey() + "," + cell.getColumnKey() + ":" + cell.getValue()) + ); + +// 4、转为嵌套的Map + // 将数据还原成嵌套Map的那种形式,使用Table的rowMap或columnMap方法就可以实现了 + System.out.println("---转为嵌套的Map"); + Map> rowMap = table.rowMap(); + Map> columnMap = table.columnMap(); + System.out.println("rowMap: " + rowMap); + System.out.println("columnMap: " + columnMap); + } + + /** + * 在普通Map中,如果要想根据value查找对应的key,没什么简便的办法,无论是使用for循环还是迭代器,都需要遍历整个Map。 + */ + @Test + public void test双向Map() { + HashBiMap biMap = HashBiMap.create(); + biMap.put("Hydra", "Programmer"); + biMap.put("Tony", "IronMan"); + biMap.put("Thanos", "Titan"); + //使用key获取value + System.out.println("使用key获取value:" + biMap.get("Tony")); + + BiMap inverse = biMap.inverse(); + //使用value获取key + System.out.println("使用value获取key:" + inverse.get("Titan")); + } + + /** + * 上面我们用inverse方法反转了原来BiMap的键值映射,但是这个反转后的BiMap并不是一个新的对象, + * 它实现了一种视图的关联,所以对反转后的BiMap执行的所有操作会作用于原先的BiMap上。 + */ + @Test + public void test双向Map_坑_反转后操作的影响() { + HashBiMap biMap = HashBiMap.create(); + biMap.put("Hydra", "Programmer"); + biMap.put("Tony", "IronMan"); + biMap.put("Thanos", "Titan"); + BiMap inverse = biMap.inverse(); + + // 原先值为IronMan时对应的键是Tony,虽然没有直接修改,但是现在键变成了Stark + inverse.put("IronMan", "Stark"); + System.out.println(biMap); + } + + @Test + public void test双向Map_坑_value不可重复() { + // 双向的BiMap,key和value都不允许重复 + HashBiMap biMap = HashBiMap.create(); + biMap.put("Tony", "IronMan"); + // java.lang.IllegalArgumentException: value already present: IronMan + biMap.put("Stark", "IronMan"); + } + + @Test + public void test双向Map_坑_value不可重复2() { + // 把新的key映射到已有的value上,使用forcePut方法强制替换掉原有的key + HashBiMap biMap = HashBiMap.create(); + biMap.put("Tony", "IronMan"); + biMap.forcePut("Stark", "IronMan"); + // 由于BiMap的value是不允许重复的,因此它的values方法返回的是没有重复的Set,而不是普通Collection: + Set values = biMap.values(); + } + + /** + * 将一个键映射到多个值 + */ + @Test + public void test多值Map() { + Multimap multimap = ArrayListMultimap.create(); + multimap.put("day", 1); + multimap.put("day", 2); + multimap.put("day", 8); + multimap.put("month", 3); + // {month=[3], day=[1, 2, 8]} + System.out.println(multimap); + + // 1、获取值的集合 + System.out.println("---获取值的集合"); + Collection day = multimap.get("day"); + // 如果在创建时指定为ArrayListMultimap类型,那么get方法将返回一个List: + // 同理,你还可以创建HashMultimap、TreeMultimap等类型的Multimap。 + ArrayListMultimap multimap2 = ArrayListMultimap.create(); + List day2 = multimap2.get("day"); + // Multimap的get方法会返回一个非null的集合,但是这个集合的内容可能是空,看一下下面的例子: + List day22 = multimap2.get("day"); + List year2 = multimap2.get("year"); + System.out.println(day22); + System.out.println(year2); + + } + + /** + * 和BiMap的使用类似,使用get方法返回的集合也不是一个独立的对象, + * 可以理解为集合视图的关联,对这个新集合的操作仍然会作用于原始的Multimap上 + */ + @Test + public void test多值Map_操作get后的集合() { + ArrayListMultimap multimap = ArrayListMultimap.create(); + multimap.put("day", 1); + multimap.put("day", 2); + multimap.put("day", 8); + multimap.put("month", 3); + + List day = multimap.get("day"); + List month = multimap.get("month"); + + System.out.println("before:" + multimap); + day.remove(0);//这个0是下标 + month.add(12); + System.out.println("after:" + multimap); + } + + /** + * 使用asMap方法,可以将Multimap转换为Map的形式, + * 同样这个Map也可以看做一个关联的视图,在这个Map上的操作会作用于原始的Multimap + */ + @Test + public void test多值Map_转换为Map() { + Multimap multimap = ArrayListMultimap.create(); + multimap.put("day", 1); + multimap.put("day", 2); + multimap.put("day", 8); + multimap.put("month", 3); + + Map> map = multimap.asMap(); + for (String key : map.keySet()) { + System.out.println(key + " : " + map.get(key)); + } + map.get("day").add(20); + System.out.println(multimap); + } + + @Test + public void test多值Map_坑_数量问题() { + Multimap multimap = ArrayListMultimap.create(); + multimap.put("day", 1); + multimap.put("day", 2); + multimap.put("day", 8); + multimap.put("month", 3); + + for (Map.Entry entry : multimap.entries()) { + System.out.println(entry.getKey() + "," + entry.getValue()); + } + + // size()方法返回的是所有key到单个value的映射,因此结果为4,entries()方法同理 + System.out.println(multimap.size()); + System.out.println(multimap.entries().size()); + // 但是它的keySet中保存的是不同的key的个数,例如下面这行代码打印的结果就会是2 + System.out.println(multimap.keySet().size()); + } + + public static String getRank(int score) { + if (0 <= score && score < 60) + return "fail"; + else if (60 <= score && score <= 90) + return "satisfactory"; + else if (90 < score && score <= 100) + return "excellent"; + return null; + } + + /** + * 要根据分数对考试成绩进行分类 + * guava中的RangeMap描述了一种从区间到特定值的映射关系,让我们能够以更为优雅的方法来书写代码 + */ + @Test + public void test范围Map() { + RangeMap rangeMap = TreeRangeMap.create(); + rangeMap.put(Range.closedOpen(0, 60), "fail"); + rangeMap.put(Range.closed(60, 90), "satisfactory"); + rangeMap.put(Range.openClosed(90, 100), "excellent"); + + System.out.println(rangeMap.get(59)); + System.out.println(rangeMap.get(60)); + System.out.println(rangeMap.get(90)); + System.out.println(rangeMap.get(91)); + + rangeMap.remove(Range.closed(70, 80)); + System.out.println(rangeMap.get(75)); + } + + /** + * ClassToInstanceMap相对普通Map + * 1、取出对象时省去了复杂的强制类型转换 + * 2、通过泛型保证value要符合key所对应的类型 + */ + @Test + public void test实例Map() { + ClassToInstanceMap instanceMap = MutableClassToInstanceMap.create(); + HashMap hashMap = new HashMap<>(); + TreeMap treeMap = new TreeMap<>(); + ArrayList list = new ArrayList<>(); + + instanceMap.putInstance(HashMap.class, hashMap); + instanceMap.putInstance(TreeMap.class, treeMap); + // HashMap和TreeMap都集成了Map父类,但是如果想放入其他类型,就会编译报错 +// instanceMap.putInstance(ArrayList.class,list); + } + + @Test + public void test实例Map对比普通Map() { + Map map = new HashMap<>(); + + HashMap hashMap = new HashMap<>(); + TreeMap treeMap = new TreeMap<>(); + ArrayList list = new ArrayList<>(); + + map.put(HashMap.class, hashMap); + map.put(TreeMap.class, treeMap); + // 1、类型转换 + treeMap = (TreeMap) map.get(TreeMap.class); + // 2、无法限制只存某些Class + map.put(ArrayList.class, list); + } + +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/guava/limit/TestRateLimiter.java b/java-basic/basic/src/main/java/cn/cunchang/guava/limit/TestRateLimiter.java new file mode 100644 index 00000000..f23faf1c --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/guava/limit/TestRateLimiter.java @@ -0,0 +1,39 @@ +package cn.cunchang.guava.limit; + +import com.google.common.util.concurrent.RateLimiter; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Guava的RateLimiter限流基于令牌桶算法 + * @author lastwhisper + */ +public class TestRateLimiter { + + /** + * 单机全局限流器(限制QPS为1)(放入拦截器,对HTTP接口限流) + */ + private static RateLimiter limiter = RateLimiter.create(1.0); + + /** + * 固定10个线程,模拟十个用户并发 + */ + private static ExecutorService pool = Executors.newFixedThreadPool(10); + + static class Task implements Runnable { + @Override + public void run() { + limiter.acquire(); // 对应web项目,就是在业务代码之前执行(拦截器、AOP) + System.out.println(System.currentTimeMillis()); + } + } + + public static void main(String[] args) { + for (int i = 0; i < 50; i++) { + pool.submit(new Task()); + } + } + + +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/guava/limit/TokenBucket.java b/java-basic/basic/src/main/java/cn/cunchang/guava/limit/TokenBucket.java new file mode 100644 index 00000000..aff3dee6 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/guava/limit/TokenBucket.java @@ -0,0 +1,39 @@ +package cn.cunchang.guava.limit; + +// 因为令牌桶对业务有一定的容忍度 +public class TokenBucket { + + private int bucketNums = 100; // 桶的容量 + private int rate = 1; // 流入速度 + private int nowTokens; // 当前令牌数量 + private long timestamp = getNowTime(); // 时间 + + private long getNowTime() { + return System.currentTimeMillis(); + } + + private int min(int tokens) { + return Math.min(bucketNums, tokens); + } + + public boolean getToken() { + // 记录来拿令牌的时间 + long nowTime = getNowTime(); + // 添加令牌【判断该有多少个令牌】 + nowTokens = nowTokens + (int) ((nowTime - timestamp) * rate); + // 添加以后的令牌数量与桶的容量那个小 + nowTokens = min(nowTokens); + System.out.println("当前令牌数量" + nowTokens); + // 修改拿令牌的时间 + timestamp = nowTime; + // 判断令牌是否足够 + if (nowTokens < 1) { + return false; + } else { + nowTokens -= 1; + return true; + } + } + + +} \ No newline at end of file diff --git a/java-basic/basic/src/main/java/cn/cunchang/hutool/IDUtilTest.java b/java-basic/basic/src/main/java/cn/cunchang/hutool/IDUtilTest.java new file mode 100644 index 00000000..16714272 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/hutool/IDUtilTest.java @@ -0,0 +1,17 @@ +package cn.cunchang.hutool; + +import cn.hutool.core.util.IdUtil; + +/** + * @author cunchang + * @date 2022/5/15 11:43 PM + */ +public class IDUtilTest { + + public static void main(String[] args) { + System.out.println(IdUtil.getSnowflakeNextId()); +// System.out.println(IdUtil.objectId()); + + + } +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/hutool/ZipUtilTest.java b/java-basic/basic/src/main/java/cn/cunchang/hutool/ZipUtilTest.java new file mode 100644 index 00000000..8f1df9a0 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/hutool/ZipUtilTest.java @@ -0,0 +1,24 @@ +package cn.cunchang.hutool; + +import cn.hutool.core.util.ZipUtil; + +import java.io.File; + +/** + * 解压文件 + * @author cunchang + * @date 2022/5/9 2:51 PM + */ +public class ZipUtilTest { + + public static void main(String[] args) { + //将test.zip解压到e:\\aaa目录下,返回解压到的目录 + File unzip = ZipUtil.unzip("/Users/cunchang/Downloads/1.zip", "/Users/cunchang/Downloads/receipt"); + System.out.println(unzip.getAbsoluteFile()); + String[] filePaths = unzip.list(); + for (String filePath : filePaths) { + System.out.println(unzip.getAbsoluteFile()+"/"+filePath); + } + } + +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/json/FeatureComment.java b/java-basic/basic/src/main/java/cn/cunchang/json/FeatureComment.java new file mode 100644 index 00000000..60edd3cc --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/json/FeatureComment.java @@ -0,0 +1,77 @@ +package cn.cunchang.json; + +public enum FeatureComment { + + /** + * 这个特性,决定了解析器是否将自动关闭那些不属于parser自己的输入源。 如果禁止,则调用应用不得不分别去关闭那些被用来创建parser的基础输入流InputStream和reader;如果允许,parser只要自己需要获取closed方法(当遇到输入流结束,或者parser自己调用 JsonParder#close方法),就会处理流关闭。 + * 注意:这个属性默认是true,即允许自动关闭流 + */ + AutoCloseSource, + + /** + * 该特性决定parser将是否允许解析使用Java/C++ 样式的注释(包括'/'+'*' 和'//' 变量)。 由于JSON标准说明书上面没有提到注释是否是合法的组成,所以这是一个非标准的特性;尽管如此,这个特性还是被广泛地使用。 + * 注意:该属性默认是false,因此必须显式允许,即通过JsonParser.Feature.ALLOW_COMMENTS 配置为true。 + */ + AllowComment, + + /** + * 这个特性决定parser是否将允许使用非双引号属性名字, (这种形式在Javascript中被允许,但是JSON标准说明书中没有)。 + * 注意:由于JSON标准上需要为属性名称使用双引号,所以这也是一个非标准特性,默认是false的。 + * 同样,需要设置JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES为true,打开该特性。 + */ + AllowUnQuotedFieldNames, + + /** + * 该特性决定parser是否允许单引号来包住属性名称和字符串值。 + * 注意:默认下,该属性也是关闭的。需要设置JsonParser.Feature.ALLOW_SINGLE_QUOTES为true + */ + AllowSingleQuotes, + + /** + * 该特性决定JSON对象属性名称是否可以被String#intern 规范化表示。如果允许,则JSON所有的属性名将会 intern() ;如果不设置,则不会规范化,默认下,该属性是开放的。此外,必须设置CANONICALIZE_FIELD_NAMES为true + * 关于intern方法作用:当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串 (该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String + * 对象添加到池中, 并且返回此 String 对象的引用。 + */ + InternFieldNames, + + //这个设置为true则遇到字符串符合ISO8601格式的日期时,会直接转换成日期类。 + AllowISO8601DateFormat, + + //允许多重逗号,如果设为true,则遇到多个逗号会直接跳过; + AllowArbitraryCommas, + + //这个设置为true则用BigDecimal类来装载数字,否则用的是double; + UseBigDecimal, + + //忽略不匹配 + IgnoreNotMatch, + + //如果你用fastjson序列化的文本,输出的结果是按照fieldName排序输出的,parser时也能利用这个顺序进行优化读取。这种情况下,parser能够获得非常好的性能 + SortFeidFastMatch, + + //禁用ASM + DisableASM, + + //禁用循环引用检测 + DisableCircularReferenceDetect, + + //对于没有值得字符串属性设置为空串 + InitStringFieldAsEmpty, + + //支持数组to对象 + SupportArrayToBean, + + //属性保持原来的顺序 + OrderedField, + + //禁用特殊字符检查 + DisableSpecialKeyDetect, + + //使用对象数组 + UseObjectArray, + + + ; + + +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/json/JSONObjectTest.java b/java-basic/basic/src/main/java/cn/cunchang/json/JSONObjectTest.java new file mode 100644 index 00000000..4f4120de --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/json/JSONObjectTest.java @@ -0,0 +1,48 @@ +package cn.cunchang.json; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.TypeReference; +import com.alibaba.fastjson.parser.Feature; +import org.junit.Test; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author cunchang + * @date 2021/6/24 10:37 上午 + */ +public class JSONObjectTest { + + + @Test + public void testOrder() { + String str = "{\"S0209\":\"#S0201#+#S0203#+#S0205#+#S0207#\",\"S0210\":\"#S0202#+#S0204#+#S0206#+#S0208#\",\"S0212\":\"#S0211#/#S0210#\",\"S0213\":\"#S0210#+#S0211#\",\"S0214\":\"#S0213#/#S0209#\"}"; + JSONObject jsonObject = JSONObject.parseObject(str, Feature.OrderedField); +// JSONObject jsonObject = JSONObject.parseObject(str); + for (Map.Entry entry : jsonObject.entrySet()) { + System.out.println(entry); + } + } + + @Test + public void test2() { + Map> map2 = new HashMap<>(); + String jsonMap2 = "{\"BUSINESS_CONTACT\":[{\"sourceTypes\":[\"XXX1\",\"XXX2\"],\"supplierList\":[\"1\",\"2\"]},{\"sourceTypes\":[\"AAA1\",\"AAA2\"],\"supplierList\":[\"4\",\"5\"]}]}"; + JSONObject jsonObject = JSONObject.parseObject(jsonMap2); + String jsonArrStr = jsonObject.getString("BUSINESS_CONTACT"); + List>> list1 = JSONObject.parseObject(jsonArrStr, new TypeReference>>>() { + }); + for (Map> kvList : list1) { + List sourceTypes = kvList.get("sourceTypes"); + for (String sourceType : sourceTypes) { + map2.put(sourceType, kvList.get("supplierList")); + } + } + System.out.println(JSON.toJSONString(map2)); + } + + +} \ No newline at end of file diff --git a/java-basic/basic/src/main/java/cn/cunchang/json/biz/Biz.java b/java-basic/basic/src/main/java/cn/cunchang/json/biz/Biz.java new file mode 100644 index 00000000..9271782b --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/json/biz/Biz.java @@ -0,0 +1,99 @@ +package cn.cunchang.json.biz; + +import cn.cunchang.json.dto.ContractExceedDTO; +import cn.cunchang.json.dto.ContractRiskApproveRuleDTO; +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author kaisui + * @description + * @date 2022/12/8 + */ +@Slf4j +public class Biz { + + static String jsonConfig="{\"isDeleted\":\"n\",\"conditions\":[{\"order\":0,\"isDeleted\":\"n\",\"approveType\":\"TYPE_LEVEL_BY_LEVEL_TO_PRESIDENT_DD\",\"ruleType\":\"overdue\",\"approveNodeTip\":\"OVER_DUE_STEP_BY_STEP\",\"detailTip\":\"CONTRACT_OVERDUE\",\"desc\":\"合同过期,采购经理逐级封顶到总裁DD。\"},{\"ratioExpression\":\"ratio>1\",\"contractTypeSet\":[\"common_frame\"],\"order\":1,\"isDeleted\":\"n\",\"approveType\":\"TYPE_LEVEL_BY_LEVEL_TO_PRESIDENT_DD\",\"ruleType\":\"overratio\",\"approveNodeTip\":\"OVERRATIO_STEP_BY_STEP_100\",\"detailTip\":\"CONTRACT_OVERRATIO_100\",\"desc\":\"单项目合同超框,采购经理逐级封顶到总裁DD。\"},{\"ratioExpression\":\"ratio>1.2\",\"contractTypeSet\":[\"price_frame\"],\"purchaseCategoryNotContainSet\":[\"OXM\"],\"order\":2,\"isDeleted\":\"n\",\"approveType\":\"TYPE_LEVEL_BY_LEVEL_TO_PRESIDENT_DD\",\"ruleType\":\"overratio\",\"approveNodeTip\":\"OVERRATIO_STEP_BY_STEP_120\",\"detailTip\":\"CONTRACT_OVERRATIO_120\",\"desc\":\"框架合同超框120%(大于)且非OXM类目,采购经理逐级封顶到总裁DD。\"},{\"ratioExpression\":\"ratio>1.5\",\"contractTypeSet\":[\"price_frame\"],\"purchaseCategorySet\":[\"OXM\"],\"order\":3,\"isDeleted\":\"n\",\"approveType\":\"TYPE_LEVEL_BY_LEVEL_TO_PRESIDENT_DD\",\"ruleType\":\"overratio\",\"approveNodeTip\":\"OVERRATIO_STEP_BY_STEP_150\",\"detailTip\":\"CONTRACT_OVERRATIO_150\",\"desc\":\"框架合同超框150%(大于)且为OXM类目,采购经理逐级封顶到总裁DD。\"},{\"ratioExpression\":\"1 matchRule(ContractExceedDTO contractExceedDTO) { + Map result = new HashMap<>(); + ContractRiskApproveRuleDTO contractRiskApproveRule = JSON.parseObject(jsonConfig,ContractRiskApproveRuleDTO.class); + List conditions = contractRiskApproveRule.getConditions(); + if (CollectionUtils.isEmpty(conditions)) { + log.warn("matchRule() 合同过期超框规则为空 => 【contractRiskApproveRule = {}】", JSON.toJSONString(contractRiskApproveRule)); + return result; + } + for (ContractRiskApproveRuleDTO.Condition condition : conditions) { + if (condition.getRuleType().equals(RuleTypeEnum.OVER_DUE.getCode())) { + if (!contractExceedDTO.getOverdue()) { + log.info("matchRule() 合同过期规则未匹配上,因为当前合同未过期 => 【contractExceedVO = {}】,【condition ={}】", + JSON.toJSONString(contractExceedDTO), JSON.toJSONString(condition)); + continue; + } + } else if (condition.getRuleType().equals(RuleTypeEnum.OVER_RATIO.getCode())) { + if(StringUtils.isNotBlank(condition.getRatioExpression())){ + String ratioExpression = condition.getRatioExpression().replaceAll("ratio", contractExceedDTO.getRatio().toString()); + if(Boolean.FALSE.equals(expressionParser.parseExpression(ratioExpression).getValue(Boolean.class))){ + log.info("matchRule() 合同超框规则未匹配上,因为当前比率:{}不满足规则比率:{} => 【contractExceedVO = {}】,【condition ={}】", contractExceedDTO.getRatio(),condition.getRatioExpression(), + JSON.toJSONString(contractExceedDTO), JSON.toJSONString(condition)); + continue; + } + } + if(!condition.getContractTypeSet().contains(contractExceedDTO.getContractType())){ + log.info("matchRule() 合同超框规则未匹配上,因为当前合同类型:{}不满足规则合同类型:{} => 【contractExceedVO = {}】,【condition ={}】", contractExceedDTO.getContractType(),JSON.toJSONString(condition.getContractTypeSet()), + JSON.toJSONString(contractExceedDTO), JSON.toJSONString(condition)); + continue; + } + if (CollectionUtils.isNotEmpty(condition.getPurchaseCategorySet())) { + // po 1、2、4;规则 4、5、6 + Set rulePurchaseCategorySet = new HashSet<>(condition.getPurchaseCategorySet()); + rulePurchaseCategorySet.removeAll(contractExceedDTO.getCurrentPoPurchaseCategory()); + if (rulePurchaseCategorySet.size() == condition.getPurchaseCategorySet().size()) { + log.info("matchRule() 合同超框规则未匹配上,因为当前po的采购类目:{}不匹配规则采购类目:{} => 【contractExceedVO = {}】,【condition ={}】", JSON.toJSONString(contractExceedDTO.getCurrentPoPurchaseCategory()), JSON.toJSONString(condition.getPurchaseCategorySet()), + JSON.toJSONString(contractExceedDTO), JSON.toJSONString(condition)); + continue; + } + } + if (CollectionUtils.isNotEmpty(condition.getPurchaseCategoryNotContainSet())) { + // po 1、2、4;not Contain 规则 4、5、6 + Set rulePurchaseCategoryNotContainSet = new HashSet<>(condition.getPurchaseCategoryNotContainSet()); + rulePurchaseCategoryNotContainSet.removeAll(contractExceedDTO.getCurrentPoPurchaseCategory()); + if (rulePurchaseCategoryNotContainSet.size() != condition.getPurchaseCategoryNotContainSet().size()) { + log.info("matchRule() 合同超框规则未匹配上,因为当前po的采购类目:{}不匹配规则采购类目:{} => 【contractExceedVO = {}】,【condition ={}】", JSON.toJSONString(contractExceedDTO.getCurrentPoPurchaseCategory()), JSON.toJSONString(condition.getPurchaseCategorySet()), + JSON.toJSONString(contractExceedDTO), JSON.toJSONString(condition)); + continue; + } + } + } + log.info("matchRule() 合同超框规则匹配成功 => 【contractExceedVO = {}】,【condition ={}】", + JSON.toJSONString(contractExceedDTO), JSON.toJSONString(condition)); + ContractRiskApproveRuleDTO.Condition existCondition = result.get(condition.getRuleType()); + if(existCondition!=null){ + log.error("matchRule() 合同超框规则匹配异常,匹配到了两个相同类型的规则 => 【contractExceedVO = {}】,【existCondition ={}】,【newCondition ={}】", + JSON.toJSONString(contractExceedDTO), JSON.toJSONString(existCondition), JSON.toJSONString(condition)); + } + result.put(condition.getRuleType(),condition); + } + return result; + } + + public static void main(String[] args) { + ContractRiskApproveRuleDTO contractRiskApproveRule = JSON.parseObject(jsonConfig,ContractRiskApproveRuleDTO.class); + List conditions = contractRiskApproveRule.getConditions().stream() + .filter(condition -> Objects.equals(condition.getIsDeleted(), "n")) + +// .sorted(Comparator.comparingInt(ContractRiskApproveRuleDTO.Condition::getOrder)).collect(Collectors.toList()); + + .sorted().collect(Collectors.toList()); + + } +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/json/biz/BizTest.java b/java-basic/basic/src/main/java/cn/cunchang/json/biz/BizTest.java new file mode 100644 index 00000000..7dc53aa1 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/json/biz/BizTest.java @@ -0,0 +1,113 @@ +package cn.cunchang.json.biz; + +import cn.cunchang.json.dto.ContractExceedDTO; +import cn.cunchang.json.dto.ContractRiskApproveRuleDTO; +import com.google.common.collect.Sets; +import org.apache.commons.collections.MapUtils; +import org.junit.Assert; +import org.junit.Test; + +import java.math.BigDecimal; +import java.util.Map; + +/** + * @author kaisui + * @description + * @date 2022/12/8 + */ +public class BizTest { + + Biz biz = new Biz(); + + // 单项目未过期 + @Test + public void test1(){ + ContractExceedDTO contractExceedDTO = new ContractExceedDTO(); + contractExceedDTO.setContractCode("1"); + contractExceedDTO.setContractType("common_frame"); + contractExceedDTO.setPoNumber("1"); + contractExceedDTO.setCurrentPoPurchaseCategory(Sets.newHashSet("PS1")); + contractExceedDTO.setOverdue(false); + contractExceedDTO.setRatio(new BigDecimal("1")); + + Map matchRuleMap = biz.matchRule(contractExceedDTO); + Assert.assertTrue(MapUtils.isEmpty(matchRuleMap)); + } + // 单项目过期 + @Test + public void test2(){ + ContractExceedDTO contractExceedDTO = new ContractExceedDTO(); + contractExceedDTO.setContractCode("1"); + contractExceedDTO.setContractType("common_frame"); + contractExceedDTO.setPoNumber("1"); + contractExceedDTO.setCurrentPoPurchaseCategory(Sets.newHashSet("PS1")); + contractExceedDTO.setOverdue(true); + contractExceedDTO.setRatio(new BigDecimal("1")); + + Map matchRuleMap = biz.matchRule(contractExceedDTO); + Assert.assertEquals(0, (int) matchRuleMap.get(RuleTypeEnum.OVER_DUE.getCode()).getOrder()); + Assert.assertNull(matchRuleMap.get(RuleTypeEnum.OVER_RATIO.getCode())); + } + + // 单项目超框 + @Test + public void test3(){ + ContractExceedDTO contractExceedDTO = new ContractExceedDTO(); + contractExceedDTO.setContractCode("1"); + contractExceedDTO.setContractType("common_frame"); + contractExceedDTO.setPoNumber("1"); + contractExceedDTO.setCurrentPoPurchaseCategory(Sets.newHashSet("PS1")); + contractExceedDTO.setOverdue(false); + contractExceedDTO.setRatio(new BigDecimal("1.0000001")); + + Map matchRuleMap = biz.matchRule(contractExceedDTO); + Assert.assertEquals(1, (int) matchRuleMap.get(RuleTypeEnum.OVER_RATIO.getCode()).getOrder()); + Assert.assertNull(matchRuleMap.get(RuleTypeEnum.OVER_DUE.getCode())); + } + + // 单项目过期+超框1.0000001 + @Test + public void test4(){ + ContractExceedDTO contractExceedDTO = new ContractExceedDTO(); + contractExceedDTO.setContractCode("1"); + contractExceedDTO.setContractType("common_frame"); + contractExceedDTO.setPoNumber("1"); + contractExceedDTO.setCurrentPoPurchaseCategory(Sets.newHashSet("PS1")); + contractExceedDTO.setOverdue(true); + contractExceedDTO.setRatio(new BigDecimal("1.0000001")); + + Map matchRuleMap = biz.matchRule(contractExceedDTO); + Assert.assertEquals(0, (int) matchRuleMap.get(RuleTypeEnum.OVER_DUE.getCode()).getOrder()); + Assert.assertEquals(1, (int) matchRuleMap.get(RuleTypeEnum.OVER_RATIO.getCode()).getOrder()); + } + // 框架合同过期 + @Test + public void test5(){ + ContractExceedDTO contractExceedDTO = new ContractExceedDTO(); + contractExceedDTO.setContractCode("1"); + contractExceedDTO.setContractType("price_frame"); + contractExceedDTO.setPoNumber("1"); + contractExceedDTO.setCurrentPoPurchaseCategory(Sets.newHashSet("PS1")); + contractExceedDTO.setOverdue(true); + contractExceedDTO.setRatio(new BigDecimal("1.0000000")); + + Map matchRuleMap = biz.matchRule(contractExceedDTO); + Assert.assertEquals(0, (int) matchRuleMap.get(RuleTypeEnum.OVER_DUE.getCode()).getOrder()); + Assert.assertNull(matchRuleMap.get(RuleTypeEnum.OVER_RATIO.getCode())); + } + // 框架合同过期+超框1.0000001 + @Test + public void test6(){ + ContractExceedDTO contractExceedDTO = new ContractExceedDTO(); + contractExceedDTO.setContractCode("1"); + contractExceedDTO.setContractType("price_frame"); + contractExceedDTO.setPoNumber("1"); + contractExceedDTO.setCurrentPoPurchaseCategory(Sets.newHashSet("PS1")); + contractExceedDTO.setOverdue(true); + contractExceedDTO.setRatio(new BigDecimal("1.0000001")); + + Map matchRuleMap = biz.matchRule(contractExceedDTO); + Assert.assertEquals(0, (int) matchRuleMap.get(RuleTypeEnum.OVER_DUE.getCode()).getOrder()); + Assert.assertNull(matchRuleMap.get(RuleTypeEnum.OVER_RATIO.getCode())); + } +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/json/biz/RuleTypeEnum.java b/java-basic/basic/src/main/java/cn/cunchang/json/biz/RuleTypeEnum.java new file mode 100644 index 00000000..c43634e1 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/json/biz/RuleTypeEnum.java @@ -0,0 +1,33 @@ +package cn.cunchang.json.biz; +/** + * + * @author kaisui + * @date 2022/11/24 + **/ +public enum RuleTypeEnum { + /** + * + */ + OVER_DUE("overdue", "超期"), + /** + * + */ + OVER_RATIO("overratio", "超框"), + + ; + private String code; + private String desc; + + RuleTypeEnum(String code, String desc) { + this.code = code; + this.desc = desc; + } + + public String getCode() { + return code; + } + + public String getDesc() { + return desc; + } + } diff --git a/java-basic/basic/src/main/java/cn/cunchang/packagesacn/ClasspathPackageScanner.java b/java-basic/basic/src/main/java/cn/cunchang/packagesacn/ClasspathPackageScanner.java new file mode 100644 index 00000000..b36dafcc --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/packagesacn/ClasspathPackageScanner.java @@ -0,0 +1,131 @@ +package cn.cunchang.packagesacn; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; + +public class ClasspathPackageScanner implements PackageScanner { + private Logger log = LoggerFactory.getLogger(ClasspathPackageScanner.class); + private String basePackage; + private ClassLoader cl; + + /** + * 初始化 + * + * @param basePackage + */ + public ClasspathPackageScanner(String basePackage) { + this.basePackage = basePackage; + this.cl = getClass().getClassLoader(); + } + + public ClasspathPackageScanner(String basePackage, ClassLoader cl) { + this.basePackage = basePackage; + this.cl = cl; + } + + /** + * 获取指定包下的所有字节码文件的全类名 + */ + @Override + public List getFullyQualifiedClassNameList() throws IOException { + log.info("开始扫描包{}下的所有类", basePackage); + return doScan(basePackage, new ArrayList()); + } + + /** + * doScan函数 + * + * @param basePackage + * @param nameList + * @return + * @throws IOException + */ + private List doScan(String basePackage, List nameList) throws IOException { + String splashPath = StringUtil.dotToSplash(basePackage); + URL url = cl.getResource(splashPath); //file:/D:/WorkSpace/java/ScanTest/target/classes/com/scan + String filePath = StringUtil.getRootPath(url); + List names = null; // contains the name of the class file. e.g., Apple.class will be stored as "Apple" + if (isJarFile(filePath)) {// 先判断是否是jar包,如果是jar包,通过JarInputStream产生的JarEntity去递归查询所有类 + log.debug("{} 是一个JAR包", filePath); + names = readFromJarFile(filePath, splashPath); + } else { + log.debug("{} 是一个目录", filePath); + names = readFromDirectory(filePath); + } + for (String name : names) { + if (isClassFile(name)) { + nameList.add(toFullyQualifiedName(name, basePackage)); + } else { + doScan(basePackage + "." + name, nameList); + } + } + for (String n : nameList) { + log.debug("找到{}", n); + } + return nameList; + } + + private String toFullyQualifiedName(String shortName, String basePackage) { + StringBuilder sb = new StringBuilder(basePackage); + sb.append('.'); + sb.append(StringUtil.trimExtension(shortName)); + //打印出结果 + System.out.println(sb.toString()); + return sb.toString(); + } + + private List readFromJarFile(String jarPath, String splashedPackageName) throws IOException { + log.debug("从JAR包中读取类: {}", jarPath); + JarInputStream jarIn = new JarInputStream(new FileInputStream(jarPath)); + JarEntry entry = jarIn.getNextJarEntry(); + List nameList = new ArrayList(); + while (null != entry) { + String name = entry.getName(); + if (name.startsWith(splashedPackageName) && isClassFile(name)) { + nameList.add(name); + } + + entry = jarIn.getNextJarEntry(); + } + + return nameList; + } + + private List readFromDirectory(String path) { + File file = new File(path); + String[] names = file.list(); + + if (null == names) { + return null; + } + + return Arrays.asList(names); + } + + private boolean isClassFile(String name) { + return name.endsWith(".class"); + } + + private boolean isJarFile(String name) { + return name.endsWith(".jar"); + } + + /** + * For test purpose. + */ + public static void main(String[] args) throws Exception { + // https://www.cnblogs.com/juncaoit/p/7591778.html + PackageScanner scan = new ClasspathPackageScanner("cn.cunchang"); + scan.getFullyQualifiedClassNameList(); + } +} \ No newline at end of file diff --git a/java-basic/basic/src/main/java/cn/cunchang/packagesacn/PackageScanner.java b/java-basic/basic/src/main/java/cn/cunchang/packagesacn/PackageScanner.java new file mode 100644 index 00000000..151df0f4 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/packagesacn/PackageScanner.java @@ -0,0 +1,10 @@ +package cn.cunchang.packagesacn; + +import java.io.IOException; +import java.util.List; + +public interface PackageScanner { + + List getFullyQualifiedClassNameList() throws IOException; + +} \ No newline at end of file diff --git a/java-basic/basic/src/main/java/cn/cunchang/packagesacn/StringUtil.java b/java-basic/basic/src/main/java/cn/cunchang/packagesacn/StringUtil.java new file mode 100644 index 00000000..6a676848 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/packagesacn/StringUtil.java @@ -0,0 +1,59 @@ +package cn.cunchang.packagesacn; + +import java.net.URL; + +public class StringUtil { + private StringUtil() { + + } + + /** + * "file:/home/whf/cn/fh" -> "/home/whf/cn/fh" + * "jar:file:/home/whf/foo.jar!cn/fh" -> "/home/whf/foo.jar" + */ + public static String getRootPath(URL url) { + String fileUrl = url.getFile(); + int pos = fileUrl.indexOf('!'); + + if (-1 == pos) { + return fileUrl; + } + + return fileUrl.substring(5, pos); + } + + /** + * "cn.fh.lightning" -> "cn/fh/lightning" + * + * @param name + * @return + */ + public static String dotToSplash(String name) { + return name.replaceAll("\\.", "/"); + } + + /** + * "Apple.class" -> "Apple" + */ + public static String trimExtension(String name) { + int pos = name.indexOf('.'); + if (-1 != pos) { + return name.substring(0, pos); + } + + return name; + } + + /** + * /application/home -> /home + * + * @param uri + * @return + */ + public static String trimURI(String uri) { + String trimmed = uri.substring(1); + int splashIndex = trimmed.indexOf('/'); + + return trimmed.substring(splashIndex); + } +} \ No newline at end of file diff --git a/java-basic/basic/src/main/java/cn/cunchang/pinyin4j/DeCode.java b/java-basic/basic/src/main/java/cn/cunchang/pinyin4j/DeCode.java new file mode 100644 index 00000000..ae9c02ea --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/pinyin4j/DeCode.java @@ -0,0 +1,20 @@ +package cn.cunchang.pinyin4j; + +/** + * + * @author lastwhisper + * @date 2020/6/8 + */ +public class DeCode { + + public static void main(String[] args) { + final String words = "原谅女儿离开父亲 昨日看到急报提示 " + + "阴祸氏突袭数据库 然后立刻离开城门 " + + "发现事情并不单纯 于是就跟随他来此 " + + "如果我没法再找寻 根据这追踪器书信 " + + "一定就会发现原因 "; + String binary = PinYinUtil.word2Tonal(words); + System.out.println(PinYinUtil.binary2Ascii(binary)); + } + +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/pinyin4j/PinYinUtil.java b/java-basic/basic/src/main/java/cn/cunchang/pinyin4j/PinYinUtil.java new file mode 100644 index 00000000..c6c80146 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/pinyin4j/PinYinUtil.java @@ -0,0 +1,171 @@ +package cn.cunchang.pinyin4j; + +import net.sourceforge.pinyin4j.PinyinHelper; +import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; +import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat; +import net.sourceforge.pinyin4j.format.HanyuPinyinToneType; +import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType; +import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; + +import static net.sourceforge.pinyin4j.format.HanyuPinyinCaseType.LOWERCASE; +import static net.sourceforge.pinyin4j.format.HanyuPinyinToneType.WITHOUT_TONE; +import static net.sourceforge.pinyin4j.format.HanyuPinyinToneType.WITH_TONE_NUMBER; +import static net.sourceforge.pinyin4j.format.HanyuPinyinVCharType.WITH_V; + +/** + * @author lastwhisper + */ +public class PinYinUtil { + + /** + * @param words 汉字字符串 + */ + public static String words2Pinyin(String words) { + return words2Pinyin(words, getDefaultPinyinFormat()); + } + + /** + * @param words 汉字字符串 + * @param pinyinFormat 汉字转拼音格式化模式 + */ + public static String words2Pinyin(String words, HanyuPinyinOutputFormat pinyinFormat) { + return words2Pinyin(words.toCharArray(), pinyinFormat); + } + + /** + * @param chars 汉字字符数组 + * @param pinyinFormat 汉字转拼音格式化模式 + */ + public static String words2Pinyin(char[] chars, HanyuPinyinOutputFormat pinyinFormat) { + StringBuilder pinyinBuilder = new StringBuilder(); + try { + for (char word : chars) { + //是否为汉字字符 + if (Character.toString(word).matches("[\\u4E00-\\u9FA5]+")) { + // 多音字 + String[] py = PinyinHelper.toHanyuPinyinStringArray(word, pinyinFormat); + pinyinBuilder.append(py[0]); + } else { + pinyinBuilder.append(word); + } + } + } catch (BadHanyuPinyinOutputFormatCombination e) { + e.printStackTrace(); + } + return pinyinBuilder.toString(); + } + + /** + * 小写、音标无声调无音符、v表示ü + * @return net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat + */ + public static HanyuPinyinOutputFormat getDefaultPinyinFormat() { + return getPinyinFormat(LOWERCASE, WITHOUT_TONE, WITH_V); + } + + /** + * 小写、音标有声调无音符、v表示ü + * @return net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat + */ + public static HanyuPinyinOutputFormat getToneNumberPinyinFormat() { + return getPinyinFormat(LOWERCASE, WITH_TONE_NUMBER, WITH_V); + } + + /** + * 获取汉语拼音格式化器 + * @param caseType 大小写 + * @see HanyuPinyinCaseType + * UPPERCASE:大写 (ZHONG) + * LOWERCASE:小写 (zhong) + * @param toneType 音标格式 + * @see HanyuPinyinToneType + * WITHOUT_TONE:无音标 (zhong) + * WITH_TONE_NUMBER:1-4数字表示英标 (zhong4) + * WITH_TONE_MARK:直接用音标符(必须WITH_U_UNICODE否则异常) (zhòng) + * @param charType charType + * @see HanyuPinyinVCharType + * WITH_V:用v表示ü (nv) + * WITH_U_AND_COLON:用"u:"表示ü (nu:) + * WITH_U_UNICODE:直接用ü (nü) + * @return net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat + */ + public static HanyuPinyinOutputFormat getPinyinFormat(HanyuPinyinCaseType caseType, HanyuPinyinToneType toneType, HanyuPinyinVCharType charType) { + HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat(); + format.setCaseType(caseType); + format.setToneType(toneType); + format.setVCharType(charType); + return format; + } + + /** + * 汉字串转声调 + * @param words 字符串 + * @return java.lang.String 声调串 + * 1,2,3,4 + */ + public static String word2ToneNumber(String words) { + String tones = words2Pinyin(words, getToneNumberPinyinFormat()); + StringBuilder toneNumBuilder = new StringBuilder(); + for (int i = 0; i < tones.length(); i++) { + char c = tones.charAt(i); + if (isTonal(c)) { + toneNumBuilder.append(c); + } + } + return toneNumBuilder.toString(); + } + + private static boolean isTonal(char c) { + return isLow(c) || isHeight(c); + } + + private static boolean isLow(char c) { + return c == 49 || c == 50; + } + + private static boolean isHeight(char c) { + return c == 51 || c == 52; + } + + /** + * 汉字串转平仄 + * @param words 字符串 + * @return java.lang.String 平仄 + * 1,2:平、3,4:仄 + * 平:0、仄:1 + */ + public static String word2Tonal(String words) { + String tones = words2Pinyin(words, getToneNumberPinyinFormat()); + StringBuilder tonalNumBuilder = new StringBuilder(); + for (int i = 0; i < tones.length(); i++) { + char c = tones.charAt(i); + if (isLow(c)) { + tonalNumBuilder.append(0); + } else if (isHeight(c)) { + tonalNumBuilder.append(1); + } + } + return tonalNumBuilder.toString(); + } + + /** + * @param binary 二进制串 + * @return java.lang.String 对应的ASCII + */ + public static String binary2Ascii(String binary) { + StringBuilder asciiBuilder = new StringBuilder(); + for (int i = 0; i < binary.length(); i += 8) { + asciiBuilder.append((char) Integer.parseInt(binary.substring(i, i + 8), 2)); + } + return asciiBuilder.toString(); + } + + public static void main(String[] args) { + String words = "原谅女儿离开父亲 昨日看到急报提示 "; + String tonal = word2Tonal(words); + System.out.println(tonal); + String str = binary2Ascii(tonal); + System.out.println(str); + } + +} \ No newline at end of file diff --git a/java-basic/basic/src/main/java/cn/cunchang/regex/RegExTest.java b/java-basic/basic/src/main/java/cn/cunchang/regex/RegExTest.java new file mode 100644 index 00000000..c3bcc629 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/regex/RegExTest.java @@ -0,0 +1,143 @@ +package cn.cunchang.regex; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Java 正则表达式 + * + * @author lastwhisper + * @date 2020/5/29 + */ +public class RegExTest { + + @Test + public void testPhone() { + // 按指定模式在字符串查找 + String[] lines = {"13812345678"}; + // 138、166、198、199 + String regEx = "^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\\d{8}$"; + match(regEx, lines); + } + + @Test + public void testLetter() { + String[] lines = {"13812345abc", "13812345ABC", "13812345;", "13812345】"}; + String regEx = "[a-zA-Z]"; + match(regEx, lines); + } + + @Test + public void testRegExSplit() { + String[] lines = {"pop-upu*123214/asd44"}; + String regEx = "[^a-zA-Z0-9]"; + match(regEx, lines); + } + + @Test + public void testIllegal() { + // 按指定模式在字符串查找 + String[] lines = {"13812345abc", "13812345哈哈", "aaa13812345;", "13812345】"}; + String regEx = "[^0-9]"; + match(regEx, lines); + } + + /** + * 名称允许汉字、字母、数字,域名只允许英文域名 + */ + @Test + public void testEmail1() { + // 按指定模式在字符串查找 + String[] lines = {"杨元庆001Abc@lenovo.com.cn"}; + // 138、166、198、199 + String regEx = "^[A-Za-z0-9\\u4e00-\\u9fa5]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$"; + match(regEx, lines); + } + + /** + * 只允许英文字母、数字、下划线、英文句号、以及中划线组成 + */ + @Test + public void testEmail2() { + // 按指定模式在字符串查找 + String[] lines = {"zhangsan-001@gmail.com"}; + String regEx = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$"; + match(regEx, lines); + } + + @Test + public void test1() { + String[] lines = {"${asdasdasd}"}; + String regEx = "\\$\\{(.*?)\\}"; + match(regEx, lines); + } + + private void match(String regEx, String[] lines) { + // 创建 Pattern 对象,这个类的实例是不可变的,可以安全地被多个并发线程使用。 + Pattern pattern = Pattern.compile(regEx); + for (String line : lines) { + Matcher m = pattern.matcher(line); + // matches()是全部匹配 + if (m.matches()) { + System.out.println("Found value:" + m.group(0)); + } else { + System.out.println("NO MATCH"); + } + } + } + + + /** + * 学习正则api + */ + @Test + public void test正则api() { + Pattern p = Pattern.compile("\\d+"); + Matcher m = p.matcher("aaa2223bb"); + System.out.println(m.find());//匹配2223,返回true + System.out.println(m.start());//返回3,返回的是2223起始的索引号 + System.out.println(m.end());//返回7,返回的是2223结束的索引号 + System.out.println(m.group());//返回2223 + Matcher m2 = p.matcher("2223bb"); + System.out.println(m2.lookingAt()); //匹配2223,返回true + System.out.println(m2.start()); //返回0,由于lookingAt()只能匹配前面的字符串,所以当使用lookingAt()匹配时,start()方法总是返回0 + System.out.println(m2.end()); //返回4 + System.out.println(m2.group()); //返回2223 + Matcher m3 = p.matcher("2223"); //如果Matcher m3=p.matcher("2223bb"); 那么下面的方法出错,因为不匹配返回false + System.out.println(m3.matches()); //匹配整个字符串,返回true + System.out.println(m3.start()); //返回0 + System.out.println(m3.end()); //返回3,原因相信大家也清楚了,因为matches()需要匹配所有字符串 + System.out.println(m3.group()); //返回2223 + } + + @Test + public void test匹配所有数字() { + Pattern p = Pattern.compile("\\d+"); +// Matcher matcher = p.matcher("请问奥所,啊啊啊12356789101,999956789101阿萨德");// 2个12位数字 + Matcher matcher = p.matcher("请问奥所,啊啊啊123567891011,999956789101阿萨德");// 13 12 +// Matcher matcher = p.matcher("请问奥所,啊啊啊123567891011阿萨德");// 13位数字 +// Matcher matcher = p.matcher("请问奥所,啊啊啊 阿萨德"); + List list = new ArrayList<>(); + while (matcher.find()) { + list.add(matcher.group()); + } + System.out.println(list); + } + + @Test + public void test匹配表达式() { + String str = "#10110#+#10120#+#10130#+#10140#+#10150#"; + Pattern p = Pattern.compile("\\d+"); + Matcher matcher = p.matcher(str); + List list = new ArrayList<>(); + while (matcher.find()) { + list.add(matcher.group()); + } + System.out.println(list); + } + +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/spring/SpringELTest.java b/java-basic/basic/src/main/java/cn/cunchang/spring/SpringELTest.java new file mode 100644 index 00000000..611b6773 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/spring/SpringELTest.java @@ -0,0 +1,37 @@ +package cn.cunchang.spring; + +import org.junit.Test; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; + +import java.math.BigDecimal; + +/** + * + * org.springframework + * spring-expression + * 5.2.7.RELEASE + * + * + * @author kaisui + * @description + * @date 2022/11/16 + */ +public class SpringELTest { + + // spring el解析表达式 + @Test + public void test1() { + ExpressionParser parser = new SpelExpressionParser(); + BigDecimal ratio = new BigDecimal("1.1"); + String compareExpression = "1 + System.out.println("TaskInfo:"+sw.getTaskName()+" TimeMillis:"+ + sw.getTimeMillis()+" TimeSeconds:"+sw.getTimeSeconds())); + // 在start()方法和stop()方法间时,isRunning()返回true + System.out.println("isRunning:"+stopWatch.isRunning()); + System.out.println("prettyPrint:\n"+stopWatch.prettyPrint());//打印详细信息 + System.out.println("shortSummary:\n"+stopWatch.shortSummary());//打印简要信息 + } +} + + diff --git a/java-basic/basic/src/main/java/cn/cunchang/str/StringTest.java b/java-basic/basic/src/main/java/cn/cunchang/str/StringTest.java new file mode 100644 index 00000000..8cb7f245 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/str/StringTest.java @@ -0,0 +1,26 @@ +package cn.cunchang.str; + +import org.junit.Test; + +/** + * @author cunchang + * @date 2022/5/9 3:23 PM + */ +public class StringTest { + + public static void main(String[] args) { +// String fileName = "819882007410001_20200309-20200309_0010387011560_KV691300131099C.pdf"; +// String REFNBR = fileName.substring(fileName.lastIndexOf("_") + 1, fileName.lastIndexOf(".")); +// System.out.println(REFNBR); + String srts = "1,"; + String[] arrs = srts.split(","); + for (String arr : arrs) { + System.out.println(arr); + } + } + + @Test + public void formatTest() { + System.out.println(String.format("百分百%s%",111)); + } +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/sugar/type/A.java b/java-basic/basic/src/main/java/cn/cunchang/sugar/type/A.java new file mode 100644 index 00000000..9f985b81 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/sugar/type/A.java @@ -0,0 +1,11 @@ +package cn.cunchang.sugar.type; + +// A.jar +//A.java有类A,A调了B的方法add(int i),这时传的是个原始类型, 完美匹配 +public class A { + public static void main(String[] args) { + // add(int i) ,1不会进行拆装箱 + // add(Integer i),1会进行拆装箱 + B.add(1); + } +} diff --git a/java-basic/basic/src/main/java/cn/cunchang/sugar/type/B.java b/java-basic/basic/src/main/java/cn/cunchang/sugar/type/B.java new file mode 100644 index 00000000..c613dd13 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/sugar/type/B.java @@ -0,0 +1,13 @@ +package cn.cunchang.sugar.type; + +// B.jar +//B.java +public class B { +// public static void add(int i) { +// System.out.println(i); +// } + + public static void add(Integer i) { + System.out.println(i); + } +} \ No newline at end of file diff --git a/java-basic/basic/src/main/java/cn/cunchang/sugar/type/README.md b/java-basic/basic/src/main/java/cn/cunchang/sugar/type/README.md new file mode 100644 index 00000000..f6cf4ace --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/sugar/type/README.md @@ -0,0 +1,6 @@ + +自动拆装箱的坑 + +Java自动拆装箱为什么不起作用了 - 鸿缘的文章 - 知乎 +https://zhuanlan.zhihu.com/p/26650204 + diff --git a/java-basic/basic/src/main/java/cn/cunchang/sysproperty/SystemProperty.java b/java-basic/basic/src/main/java/cn/cunchang/sysproperty/SystemProperty.java new file mode 100644 index 00000000..d9a47e38 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/sysproperty/SystemProperty.java @@ -0,0 +1,56 @@ +package cn.cunchang.sysproperty; + +import org.junit.Test; + +import java.util.Properties; + +public class SystemProperty { + + @Test + public void properties() { + Properties props = System.getProperties(); + System.out.println("Java的执行环境版本号:" + props.getProperty("java.version")); + System.out.println("Java的执行环境供应商:" + props.getProperty("java.vendor")); + System.out.println("Java供应商的URL:" + props.getProperty("java.vendor.url")); + System.out.println("Java的安装路径:" + props.getProperty("java.home")); + System.out.println("Java的虚拟机规范版本号:" + props.getProperty("java.vm.specification.version")); + System.out.println("Java的虚拟机规范供应商:" + props.getProperty("java.vm.specification.vendor")); + System.out.println("Java的虚拟机规范名称:" + props.getProperty("java.vm.specification.name")); + System.out.println("Java的虚拟机实现版本号:" + props.getProperty("java.vm.version")); + System.out.println("Java的虚拟机实现供应商:" + props.getProperty("java.vm.vendor")); + System.out.println("Java的虚拟机实现名称:" + props.getProperty("java.vm.name")); + System.out.println("Java执行时环境规范版本号:" + props.getProperty("java.specification.version")); + System.out.println("Java执行时环境规范供应商:" + props.getProperty("java.specification.vender")); + System.out.println("Java执行时环境规范名称:" + props.getProperty("java.specification.name")); + System.out.println("Java的类格式版本号号:" + props.getProperty("java.class.version")); + System.out.println("Java的类路径:" + props.getProperty("java.class.path")); + System.out.println("载入库时搜索的路径列表:" + props.getProperty("java.library.path")); + System.out.println("默认的暂时文件路径:" + props.getProperty("java.io.tmpdir")); + System.out.println("一个或多个扩展文件夹的路径:" + props.getProperty("java.ext.dirs")); + // 操作系统 输出 + // linux Linux + // windows Windows XP + // mac Mac OS X + System.out.println("操作系统的名称:" + props.getProperty("os.name")); + System.out.println("操作系统的构架:" + props.getProperty("os.arch")); + System.out.println("操作系统的版本号:" + props.getProperty("os.version")); + System.out.println("文件分隔符:" + props.getProperty("file.separator")); + //在 unix 系统中是"/" + System.out.println("路径分隔符:" + props.getProperty("path.separator")); + //在 unix 系统中是":" + System.out.println("行分隔符:" + props.getProperty("line.separator")); + //在 unix 系统中是"/n" + System.out.println("用户的账户名称:" + props.getProperty("user.name")); + System.out.println("用户的主文件夹:" + props.getProperty("user.home")); + System.out.println("用户的当前工作文件夹:" + props.getProperty("user.dir")); + } + + @Test + public void dynamicPath() { + String userHome = System.getProperty("user.home"); + System.out.println(userHome+"/upload"); + } + + + +} \ No newline at end of file diff --git a/java-basic/basic/src/main/java/cn/cunchang/trycatch/ForTryFinallyTest.java b/java-basic/basic/src/main/java/cn/cunchang/trycatch/ForTryFinallyTest.java new file mode 100644 index 00000000..65342d70 --- /dev/null +++ b/java-basic/basic/src/main/java/cn/cunchang/trycatch/ForTryFinallyTest.java @@ -0,0 +1,39 @@ +package cn.cunchang.trycatch; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author cunchang + * @date 2020/12/29 3:06 下午 + */ +public class ForTryFinallyTest { + + public static void main(String[] args) { + List list = new ArrayList<>(); + list.add(1); + list.add(2); + list.add(3); + list.add(4); + for (Integer num : list) { + try { + if (num == 2) { + continue; + } + if (num == 3) { + break; + } + System.out.println("正常执行 " + num); + } finally { + if (num == 2) { + System.out.println("for循环,try里面continue会执行finally " + num); + } + if (num == 3) { + System.out.println("for循环,try里面break会执行finally " + num); + } + } + } + } + + +} diff --git a/java-basic/basic/src/main/resources/log4j2.xml b/java-basic/basic/src/main/resources/log4j2.xml new file mode 100644 index 00000000..0fed87ee --- /dev/null +++ b/java-basic/basic/src/main/resources/log4j2.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java-basic/concurrent/README.md b/java-basic/concurrent/README.md new file mode 100644 index 00000000..19b37306 --- /dev/null +++ b/java-basic/concurrent/README.md @@ -0,0 +1,4 @@ +1. jmm-specification +2. thread-syncronized +3. thread-current +4. \ No newline at end of file diff --git a/java-basic/concurrent/jmm-specification/README.md b/java-basic/concurrent/jmm-specification/README.md new file mode 100644 index 00000000..0b33e62e --- /dev/null +++ b/java-basic/concurrent/jmm-specification/README.md @@ -0,0 +1,7 @@ + + +AsIfSerialSample AsIfSerial语义 +Jmm01_HappensBefore HappensBefore +Jmm05_CodeReorder 指令重排序 +Jmm06_MemoryBarrier 内存屏障 + diff --git a/java-basic/concurrent/jmm-specification/pom.xml b/java-basic/concurrent/jmm-specification/pom.xml new file mode 100644 index 00000000..825ba9af --- /dev/null +++ b/java-basic/concurrent/jmm-specification/pom.xml @@ -0,0 +1,19 @@ + + + + concurrent + cn.lastwhisper + 1.0-SNAPSHOT + + 4.0.0 + + jmm-specification + + + 11 + 11 + + + \ No newline at end of file diff --git a/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/AsIfSerialSample.java b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/AsIfSerialSample.java new file mode 100644 index 00000000..ca36ab8e --- /dev/null +++ b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/AsIfSerialSample.java @@ -0,0 +1,25 @@ +package cn.lastwhisper; + +/** + * @author : + * @date:2019/7/18 + * @version: V1.0 + * @slogan: 天下风云出我辈,一入代码岁月催 + * @description : + */ +public class AsIfSerialSample { + + public static void main(String[] args) { + /** + * as-if-serial语义的意思是:不管怎么重排序(编译器和处理器为了提高并行度),(单线程) + * 程序的执行结果不能被改变。编译器、runtime和处理器都必须遵守as-if-serial语义。 + * + * 以下例子当中1、2步存在指令重排行为,但是1、2不能与第三步指令重排 + * 也就是第3步不可能先于1、2步执行,否则将改变程序的执行结果 + */ + double p = 3.14; //1 + double r = 1.0; //2 + double area = p * r * r; //3计算面积 + } + +} diff --git a/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm01_HappensBefore.java b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm01_HappensBefore.java new file mode 100644 index 00000000..3313e95c --- /dev/null +++ b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm01_HappensBefore.java @@ -0,0 +1,27 @@ +package cn.lastwhisper; + +/** + * @date :Created in 2020/4/29 13:58 + * @version: V1.0 + * @slogan: 天下风云出我辈,一入代码岁月催 + * @description: + **/ +public class Jmm01_HappensBefore { + public static volatile int r = 3; + + public static int g=6; + + public static volatile double pai = 3.14; + + public static volatile double area; + + public static void caculate(){ + int a = r; + int b = g; + area = a * b * pai; + } + + public static void main(String[] args) { + caculate(); + } +} diff --git a/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm02_CpuCache.java b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm02_CpuCache.java new file mode 100644 index 00000000..f7bc3229 --- /dev/null +++ b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm02_CpuCache.java @@ -0,0 +1,64 @@ +package cn.lastwhisper; + +/** + * ,;,,; + * ,;;'( 社 + * __ ,;;' ' \ 会 + * /' '\'~~'~' \ /'\.) 主 + * ,;( ) / |. 义 + *,;' \ /-.,,( ) \ 码 + * ) / ) / )| 农 + * || || \) + * (_\ (_\ + * + * @date :Created in 2020/4/29 14:00 + * @version: V1.0 + * @slogan: 天下风云出我辈,一入代码岁月催 + * @description: + **/ +public class Jmm02_CpuCache { + private static final int RUNS = 10; + private static final int DIMENSION_1 = 1024 * 1024; + private static final int DIMENSION_2 = 6; + + private static long[][] longs; + + public static void main(String[] args) throws Exception { + /* + * 初始化数组 + */ + longs = new long[DIMENSION_1][]; + for (int i = 0; i < DIMENSION_1; i++) { + longs[i] = new long[DIMENSION_2]; + for (int j = 0; j < DIMENSION_2; j++) { + longs[i][j] = 1L; + } + } + System.out.println("初始化完毕...."); + + long sum = 0L; + long start = System.currentTimeMillis(); + for (int r = 0; r < RUNS; r++) { + for (int i = 0; i < DIMENSION_1; i++) {//DIMENSION_1=1024*1024 + for (int j=0;j{ + while (!initFlag){ + //System.out.println("runing"); + counter++; + } + log.info("线程:" + Thread.currentThread().getName() + + "当前线程嗅探到initFlag的状态的改变"); + },"threadA"); + threadA.start(); + + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + Thread threadB = new Thread(()->{ + refresh(); + },"threadB"); + threadB.start(); + } +} diff --git a/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm04_CodeAtomic.java b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm04_CodeAtomic.java new file mode 100644 index 00000000..700f3bad --- /dev/null +++ b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm04_CodeAtomic.java @@ -0,0 +1,51 @@ +package cn.lastwhisper; + +import com.sun.xml.internal.ws.developer.MemberSubmissionAddressingFeature; + +import javax.security.sasl.SaslServer; + +/** + * ,;,,; + * ,;;'( 社 + * __ ,;;' ' \ 会 + * /' '\'~~'~' \ /'\.) 主 + * ,;( ) / |. 义 + * ,;' \ /-.,,( ) \ 码 + * ) / ) / )| 农 + * || || \) + * (_\ (_\ + * + * + * @date :Created in 2020/4/29 + * @version: V1.0 + * @slogan: 天下风云出我辈,一入代码岁月催 + * @description: + **/ +public class Jmm04_CodeAtomic { + + private volatile static int counter = 0; + static Object object = new Object(); + + public static void main(String[] args) { + + for (int i = 0; i < 10; i++) { + Thread thread = new Thread(()->{ + for (int j = 0; j < 1000; j++) { + synchronized (object){ + counter++;//分三步- 读,自加,写回 + } + } + }); + thread.start(); + } + + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + System.out.println(counter); + + } +} diff --git a/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm05_CodeReorder.java b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm05_CodeReorder.java new file mode 100644 index 00000000..9da86070 --- /dev/null +++ b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm05_CodeReorder.java @@ -0,0 +1,50 @@ +package cn.lastwhisper; + +public class Jmm05_CodeReorder { + private static int x = 0, y = 0; + private static int a = 0, b = 0; + + public static void main(String[] args) throws InterruptedException { + int i = 0; + for (; ; ) { + i++; + x = 0; + y = 0; + a = 0; + b = 0; + Thread t1 = new Thread(new Runnable() { + @Override + public void run() { + a = 1; + x = b; + } + }); + + Thread t2 = new Thread(new Runnable() { + @Override + public void run() { + b = 1; + y = a; + } + }); + + t1.start(); + t2.start(); + // 阻塞主线程,直到t1执行完 + t1.join(); + // 阻塞主线程,直到t2执行完 + t2.join(); + // 第12627次 (0,0) + // 第951620次 (0,0) + // 出现指令重排: 第22648505次 (0,0) + String result = "第" + i + "次 (" + x + "," + y + ")"; + if (x == 0 && y == 0) { + System.out.println("出现指令重排: " + result); + break; + } else { + System.out.println(result); + } + } + + } +} diff --git a/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm06_MemoryBarrier.java b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm06_MemoryBarrier.java new file mode 100644 index 00000000..76416a50 --- /dev/null +++ b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm06_MemoryBarrier.java @@ -0,0 +1,35 @@ +package cn.lastwhisper; + +/** + * ,;,,; + * ,;;'( 社 + * __ ,;;' ' \ 会 + * /' '\'~~'~' \ /'\.) 主 + * ,;( ) / |. 义 + * ,;' \ /-.,,( ) \ 码 + * ) / ) / )| 农 + * || || \) + * (_\ (_\ + * + * + * @date :Created in 2020/4/29 + * @version: V1.0 + * @slogan: 天下风云出我辈,一入代码岁月催 + * @description: + **/ +public class Jmm06_MemoryBarrier { + int a; + public volatile int m1 = 1; + public volatile int m2 = 2; + + public void readAndWrite() { + int i = m1; // 第一个volatile读 + int j = m2; // 第二个volatile读 + + a = i + j; // i,j普通读,a普通写 + + m1 = i + 1; // 第一个volatile写 + m2 = j * 2; // 第二个 volatile写 + } + +} diff --git a/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm07_ByteCodeJitDump.java b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm07_ByteCodeJitDump.java new file mode 100644 index 00000000..5907c948 --- /dev/null +++ b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/Jmm07_ByteCodeJitDump.java @@ -0,0 +1,43 @@ +package cn.lastwhisper; + +/** + * ,;,,; + * ,;;'( 社 + * __ ,;;' ' \ 会 + * /' '\'~~'~' \ /'\.) 主 + * ,;( ) / |. 义 + *,;' \ /-.,,( ) \ 码 + * ) / ) / )| 农 + * || || \) + * (_\ (_\ + * + * @date :Created in 2020/4/29 14:12 + * @version: V1.0 + * @slogan: 天下风云出我辈,一入代码岁月催 + * @description: -server -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:CompileCommand=compileonly,*Jmm07_ByteCodeJitDump.refresh + **/ +public class Jmm07_ByteCodeJitDump { + private volatile static int c = 1; + + public static int refresh(){ + int a = 0; + int b = 1; + int sub = a + b + c; + return sub; + } + + public static void main(String[] args) throws InterruptedException { + + Thread thread0 = new Thread(()->{ + System.out.println(String.format("sub0:%d",refresh())); + }); + + thread0.start(); + + Thread thread1 = new Thread(()->{ + System.out.println(String.format("sub1:%d",refresh())); + }); + + thread1.start(); + } +} diff --git a/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/JmmCausalityCase16Test.java b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/JmmCausalityCase16Test.java new file mode 100644 index 00000000..8317bbbb --- /dev/null +++ b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/JmmCausalityCase16Test.java @@ -0,0 +1,51 @@ +package cn.lastwhisper; + +public class JmmCausalityCase16Test { + private static int x = 0; + private static int r1 = 0, r2 = 0; + + public static void main(String[] args) throws InterruptedException { + int i = 0; + for (; ; ) { + i++; + x = 0; + r1 = 0; + r2 = 0; + Thread t1 = new Thread(new Runnable() { + @Override + public void run() { + r1 = x; + x = 1; + } + }); + + Thread t2 = new Thread(new Runnable() { + @Override + public void run() { + r2 = x; + x = 2; + } + }); + + t1.start(); + t2.start(); + // 阻塞主线程,直到t1执行完 + t1.join(); + // 阻塞主线程,直到t2执行完 + t2.join(); + String result = "第" + i + "次 (" + r1 + "," + r2 + ")"; + // t1/t2 => r1=0;r2=1——(0,1) + // t2/t1 => r1=2;r2=0——(2,0) + + // x=2,r1=x(2);x=1,r2=x(1) => r1=2;r2=1——(2,1)概率极小 + // 第23339610次 (0,1) + if (r1 == 2 && r2 == 1) { + System.out.println("出现指令重排: " + result); + break; + } else { + System.out.println(result); + } + } + + } +} diff --git a/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/dcl/Singleton.java b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/dcl/Singleton.java new file mode 100644 index 00000000..45ae9a41 --- /dev/null +++ b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/dcl/Singleton.java @@ -0,0 +1,36 @@ +package cn.lastwhisper.dcl; + +/** + * @author : + * @date:2019/7/10 + * @version: V1.0 + * @slogan:天下风云出我辈,一入代码岁月催 + * @description + */ +public class Singleton { + + /** + * 查看汇编指令 + * -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly + */ + private volatile static Singleton myinstance; + + /** + * 双重锁机制保证单例安全 + * @return + */ + public static Singleton getInstance() { + if (myinstance == null) { + synchronized (Singleton.class) { + if (myinstance == null) { + myinstance = new Singleton(); + } + } + } + return myinstance; + } + + public static void main(String[] args) { + Singleton.getInstance(); + } +} diff --git a/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/tmodel/ThreadModel.java b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/tmodel/ThreadModel.java new file mode 100644 index 00000000..c0e47997 --- /dev/null +++ b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/tmodel/ThreadModel.java @@ -0,0 +1,30 @@ +package cn.lastwhisper.tmodel; + +/** + * + * @date :Created in 2020/8/2 + * @version: V1.0 + * @slogan: 天下风云出我辈,一入代码岁月催 + * @description: + **/ +public class ThreadModel { + + public static void main(String[] args) { + + for (int i=0;i<200;i++){ + new Thread(new Runnable() { + @Override + public void run() { + while(true){ + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + }).start(); + } + } + +} diff --git a/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/util/UnsafeInstance.java b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/util/UnsafeInstance.java new file mode 100644 index 00000000..1996ed15 --- /dev/null +++ b/java-basic/concurrent/jmm-specification/src/main/java/cn/lastwhisper/util/UnsafeInstance.java @@ -0,0 +1,27 @@ +package cn.lastwhisper.util; + +import sun.misc.Unsafe; + +import java.lang.reflect.Field; + +/** + * @author : + * @date:2019/7/14 + * @version: V1.0 + * @slogan: 天下风云出我辈,一入代码岁月催 + * @description : + */ +public class UnsafeInstance { + + public static Unsafe reflectGetUnsafe() { + try { + Field field = Unsafe.class.getDeclaredField("theUnsafe"); + field.setAccessible(true); + return (Unsafe) field.get(null); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/java-basic/concurrent/pom.xml b/java-basic/concurrent/pom.xml index ef8a3f9f..fc832c9f 100644 --- a/java-basic/concurrent/pom.xml +++ b/java-basic/concurrent/pom.xml @@ -2,27 +2,46 @@ - - java-basic - cn.lastwhisper - 1.0-SNAPSHOT - + 4.0.0 cn.lastwhisper concurrent + pom + 1.0-SNAPSHOT + + jmm-specification + + - - com.google.guava - guava - 27.0.1-jre + org.springframework.boot + spring-boot-starter-web + 2.1.7.RELEASE org.projectlombok lombok 1.18.8 + + junit + junit + 4.13 + + + + org.openjdk.jol + jol-core + 0.10 + + + + com.alibaba + transmittable-thread-local + 2.12.6 + + \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/ExecuteCaught.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/ExecuteCaught.java new file mode 100644 index 00000000..1c53072e --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/ExecuteCaught.java @@ -0,0 +1,14 @@ +package cn.lastwhisper.concurrent.UncaughtExceptionHandler; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class ExecuteCaught { + public static void main(String[] args) { + ExecutorService exec = Executors.newCachedThreadPool(); + Thread thread = new Thread(new Task()); + thread.setUncaughtExceptionHandler(new ExceptionHandler()); + exec.execute(thread); + exec.shutdown(); + } +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/ExecuteCaught2.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/ExecuteCaught2.java new file mode 100644 index 00000000..1c44db12 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/ExecuteCaught2.java @@ -0,0 +1,22 @@ +package cn.lastwhisper.concurrent.UncaughtExceptionHandler; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class ExecuteCaught2 { + public static void main(String[] args) { + ExecutorService exec = Executors.newCachedThreadPool(); + exec.execute(new ThreadPoolTask()); + exec.shutdown(); + } +} + +class ThreadPoolTask implements Runnable { + @Override + public void run() { + Thread.currentThread().setUncaughtExceptionHandler(new ExceptionHandler()); + System.out.println(3 / 2); + System.out.println(3 / 0); + System.out.println(3 / 1); + } +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/InitiativeCaught.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/InitiativeCaught.java new file mode 100644 index 00000000..2936b077 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/InitiativeCaught.java @@ -0,0 +1,33 @@ +package cn.lastwhisper.concurrent.UncaughtExceptionHandler; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class InitiativeCaught { + public void threadDeal(Runnable r, Throwable t) { + System.out.println("==Exception: " + t.getMessage()); + } + + class InitialtiveThread implements Runnable { + @Override + public void run() { + Throwable thrown = null; + try { + System.out.println(3 / 2); + System.out.println(3 / 0); + System.out.println(3 / 1); + } catch (Throwable e) { + thrown = e; + } finally { + threadDeal(this, thrown); + } + } + } + + public static void main(String[] args) { + ExecutorService exec = Executors.newCachedThreadPool(); + exec.execute(new InitiativeCaught().new InitialtiveThread()); + exec.shutdown(); + } + +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/NoCaughtThread.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/NoCaughtThread.java new file mode 100644 index 00000000..d0301798 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/NoCaughtThread.java @@ -0,0 +1,14 @@ +package cn.lastwhisper.concurrent.UncaughtExceptionHandler; + +public class NoCaughtThread { + public static void main(String[] args) { + try { + Thread thread = new Thread(new Task()); + thread.start(); + } catch (Exception e) { + System.out.println("==Exception: " + e.getMessage()); + } + } + +} + diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/README.md b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/README.md new file mode 100644 index 00000000..a1adad8d --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/README.md @@ -0,0 +1,3 @@ + +JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止 +https://blog.csdn.net/u013256816/article/details/50417822 diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/Task.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/Task.java new file mode 100644 index 00000000..a6f3b917 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/Task.java @@ -0,0 +1,10 @@ +package cn.lastwhisper.concurrent.UncaughtExceptionHandler; + +public class Task implements Runnable { + @Override + public void run() { + System.out.println(3 / 2); + System.out.println(3 / 0); + System.out.println(3 / 1); + } + } \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/WitchCaughtThread.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/WitchCaughtThread.java new file mode 100644 index 00000000..b12127fe --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/UncaughtExceptionHandler/WitchCaughtThread.java @@ -0,0 +1,18 @@ +package cn.lastwhisper.concurrent.UncaughtExceptionHandler; + +import java.lang.Thread.UncaughtExceptionHandler; + +public class WitchCaughtThread { + public static void main(String args[]) { + Thread thread = new Thread(new Task()); + thread.setUncaughtExceptionHandler(new ExceptionHandler()); + thread.start(); + } +} + +class ExceptionHandler implements UncaughtExceptionHandler { + @Override + public void uncaughtException(Thread t, Throwable e) { + System.out.println("==Exception: " + e.getMessage()); + } +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Daemon.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Daemon.java new file mode 100644 index 00000000..21fd8394 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Daemon.java @@ -0,0 +1,30 @@ +package cn.lastwhisper.concurrent.basic; + +public class Daemon { + /** + * Daemon线程是一种支持型线程,因为它主要被用作程序中后台调度以及支持性工作。这 + * 意味着,当一个Java虚拟机中不存在非Daemon线程的时候,Java虚拟机将会退出。可以通过调 + * 用Thread.setDaemon(true)将线程设置为Daemon线程。 + * + * 虚拟机没有非Daemon线程,虚拟机需要退出,此时所有Daemon线程都需要立即终止, + * 因此DaemonRunner立即终止,但是DaemonRunner中的finally块并没有执行。 + * @param args + */ + public static void main(String[] args) { + Thread thread = new Thread(new DaemonRunner(), + "DaemonRunner"); + thread.setDaemon(true); + thread.start(); + } + + static class DaemonRunner implements Runnable { + @Override + public void run() { + try { + SleepUtils.second(10); + } finally { + System.out.println("DaemonThread finally run."); + } + } + } +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Deprecated.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Deprecated.java new file mode 100644 index 00000000..e08b3f42 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Deprecated.java @@ -0,0 +1,41 @@ +package cn.lastwhisper.concurrent.basic; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.concurrent.TimeUnit; + +public class Deprecated { + public static void main(String[] args) throws Exception { + DateFormat format = new SimpleDateFormat("HH:mm:ss"); + Thread printThread = new Thread(new Runner(), + "PrintThread"); + printThread.setDaemon(true); + printThread.start(); + TimeUnit.SECONDS.sleep(3); + // 将PrintThread进行暂停,输出内容工作停止 + printThread.suspend(); + System.out.println("main suspend PrintThread at " + format.format(new Date())); + TimeUnit.SECONDS.sleep(3); + // 将PrintThread进行恢复,输出内容继续 + printThread.resume(); + System.out.println("main resume PrintThread at " + format.format(new Date())); + TimeUnit.SECONDS.sleep(3); + // 将PrintThread进行终止,输出内容停止 + printThread.stop(); + System.out.println("main stop PrintThread at " + format.format(new Date())); + TimeUnit.SECONDS.sleep(3); + } + + static class Runner implements Runnable { + @Override + public void run() { + DateFormat format = new SimpleDateFormat("HH:mm:ss"); + while (true) { + System.out.println(Thread.currentThread().getName() + " Run at " + + format.format(new Date())); + SleepUtils.second(1); + } + } + } +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptLockSupportDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptLockSupportDemo.java new file mode 100644 index 00000000..f7bfcc90 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptLockSupportDemo.java @@ -0,0 +1,18 @@ +package cn.lastwhisper.concurrent.basic.Interrupted; + +import java.util.concurrent.locks.LockSupport; + +public class InterruptLockSupportDemo { + public static void main(String[] args) throws InterruptedException { + Thread t1 = new Thread(() -> { + System.out.println("t1 come in"); + LockSupport.park(); + System.out.println("t1 go out"); + }, "t1"); + t1.start(); + + Thread.sleep(1000); + t1.interrupt(); + Thread.sleep(1000); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptNotAliveDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptNotAliveDemo.java new file mode 100644 index 00000000..75378fc7 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptNotAliveDemo.java @@ -0,0 +1,24 @@ +package cn.lastwhisper.concurrent.basic.Interrupted; + +public class InterruptNotAliveDemo { + private static class A extends Thread { + @Override + public void run() { + } + } + + public static void test() throws InterruptedException { + A a = new A(); + a.interrupt(); + System.out.println(a.isInterrupted()); + + a.start(); + Thread.sleep(100); + a.interrupt(); + System.out.println(a.isInterrupted()); + } + + public static void main(String[] args) throws InterruptedException { + test(); + } +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptReadCancelDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptReadCancelDemo.java new file mode 100644 index 00000000..da20d31c --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptReadCancelDemo.java @@ -0,0 +1,36 @@ +package cn.lastwhisper.concurrent.basic.Interrupted; + +import java.io.IOException; + +public class InterruptReadCancelDemo { + private static class A extends Thread { + @Override + public void run() { + while (!Thread.currentThread().isInterrupted()) { + try { + System.out.println("a线程等待输入:"); + System.out.println(System.in.read());//wait input + } catch (IOException e) { + e.printStackTrace(); + } + } + System.out.println("a线程 exit"); + } + + public void cancel() { + try { + System.in.close(); + } catch (IOException e) { + } + interrupt(); + } + } + + public static void main(String[] args) throws InterruptedException { + A t = new A(); + t.start(); + Thread.sleep(100); + System.out.println("main线程对a线程input进行close"); + t.cancel(); + } +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptReadDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptReadDemo.java new file mode 100644 index 00000000..ab690710 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptReadDemo.java @@ -0,0 +1,28 @@ +package cn.lastwhisper.concurrent.basic.Interrupted; + +import java.io.IOException; + +public class InterruptReadDemo { + private static class A extends Thread { + @Override + public void run() { + while (!Thread.currentThread().isInterrupted()) { + try { + System.out.println("a线程等待输入:"); + System.out.println(System.in.read());//wait input + } catch (IOException e) { + e.printStackTrace(); + } + } + System.out.println("a线程 exit"); + } + } + + public static void main(String[] args) throws InterruptedException { + A a = new A(); + a.start(); + Thread.sleep(100); + System.out.println("main线程对a线程发起中断信号"); + a.interrupt(); + } +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptRunnableDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptRunnableDemo.java new file mode 100644 index 00000000..f74134ac --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptRunnableDemo.java @@ -0,0 +1,23 @@ +package cn.lastwhisper.concurrent.basic.Interrupted; + +public class InterruptRunnableDemo extends Thread { + @Override + public void run() { + while (!Thread.currentThread().isInterrupted()) { + // ... 单次循环代码 + System.out.println("loop..."); + } + System.out.println("done "); + } + + /** + * 如果线程在运行中,interrupt()只是会设置线程的中断标志位,没有任何其它作用。 + * 线程应该在运行过程中合适的位置检查中断标志位,比如说,如果主体代码是一个循环,可以在循环开始处进行检查 + */ + public static void main(String[] args) throws InterruptedException { + Thread thread = new InterruptRunnableDemo(); + thread.start(); + Thread.sleep(1000); + thread.interrupt(); + } +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptSynchronizedDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptSynchronizedDemo.java new file mode 100644 index 00000000..0c155cd8 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptSynchronizedDemo.java @@ -0,0 +1,32 @@ + +package cn.lastwhisper.concurrent.basic.Interrupted; + +public class InterruptSynchronizedDemo { + private static final Object lock = new Object();//monitor + private static class BlockedThread extends Thread { + @Override + public void run() { + //等待lock锁 + synchronized (lock) { + //等待标志位被置为true + while (!Thread.currentThread().isInterrupted()) { + } + } + System.out.println("exit"); + } + } + public static void test() throws InterruptedException { + synchronized (lock) {//获取锁 + BlockedThread blockedThread = new BlockedThread(); + blockedThread.start(); + Thread.sleep(1000); + //blockedThread在等待lock锁,interrupt 无法中断 + blockedThread.interrupt(); + //blockedThread线程加入当前线程,main线程等待blockedThread执行完毕,才会继续往下执行 + blockedThread.join(); + } + } + public static void main(String[] args) throws InterruptedException { + test(); + } +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptWaitingDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptWaitingDemo.java new file mode 100644 index 00000000..959e5ad3 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/InterruptWaitingDemo.java @@ -0,0 +1,37 @@ +package cn.lastwhisper.concurrent.basic.Interrupted; + +public class InterruptWaitingDemo extends Thread { + + //抛出中断异常,由调用者捕获 + public void interruptibleMethod() throws InterruptedException{ + // ... 包含wait, join 或 sleep 方法 + Thread.sleep(1000); + } + + // 中断异常,由自己捕获,自己处理 + @Override + public void run() { + while (!Thread.currentThread().isInterrupted()) { + try { + // 模拟任务代码 + Thread.sleep(2000); + } catch (InterruptedException e) { + // ... 清理操作 + System.out.println("当前线程执行中,发生中断异常,当前Interrupted:"+ isInterrupted());//false + // 重设中断标志位为true + Thread.currentThread().interrupt(); + } + } + System.out.println("当前线程执行即将结束,当前Interrupted:"+isInterrupted());//true + } + + public static void main(String[] args) { + InterruptWaitingDemo thread = new InterruptWaitingDemo(); + thread.start(); + try { + Thread.sleep(100); + } catch (InterruptedException e) { + } + thread.interrupt(); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/README.md b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/README.md new file mode 100644 index 00000000..aba045c6 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/README.md @@ -0,0 +1,45 @@ +# 线程不同状态对中断的反应 + +## RUNNABLE + +线程在运行或具备运行条件只是在等待操作系统调度 +案例:InterruptRunnableDemo; +如果线程在RUNNABLE,interrupt()只是会设置线程的中断标志位,没有任何其它作用。 + +## WAITING/TIMED_WAITING: + +线程在等待某个条件或超时 +1、案例:InterruptWaitingDemo + +在这些状态时,对线程对象调用interrupt()会使得该线程抛出InterruptedException,抛出异常后,中断标志位会被清空(线程的中断标志位会由true重置为false,因为线程为了处理异常已经重新处于就绪状态。 + +捕获到InterruptedException,通常表示希望结束该线程,线程大概有两种处理方式: +(1)向上传递该异常,这使得该方法也变成了一个可中断的方法,需要调用者进行处理 +(2)有些情况,不能向上传递异常,比如Thread的run方法,它的声明是固定的,不能抛出任何受检异常,这时,应该捕获异常,进行合适的清理操作,清理后,一般应该调用Thread的interrupt方法再次设置中断标志位,使得当前线程知道自己发生了中断。 + +2、案例:InterruptLockSupportDemo +LockSupport的线程被中断后直接唤醒放行 + +## BLOCKED + +线程在等待锁,试图进入同步块 +案例:InterruptSynchronizedDemo +如果线程在等待锁,对线程对象调用interrupt()只是会设置线程的中断标志位,线程依然会处于BLOCKED状态,也就是说,interrupt()并不能使一个在等待锁的线程真正”中断”。 + +## NEW/TERMINATED + +线程还未启动或已结束 +如果线程尚未启动(NEW),或者已经结束(TERMINATED),则调用interrupt()对它没有任何效果,中断标志位也不会被设置。 + +## 特殊的RUNNABLE +案例: +- InterruptReadDemo 无法通过中断取消 +- InterruptReadCancelDemo +Java线程在进行io操作时,在java中的状态也是RUNNABLE + +1. 实现java.nio.channels.InterruptibleChannel接口的通道是可中断的:如果某个线程在可中断通道上因调用某个阻塞的 I/O 操作(常见的操作一般有这些:serverSocketChannel. accept()、socketChannel.connect、socketChannel.open、socketChannel.read、socketChannel.write、fileChannel.read、fileChannel.write)而进入阻塞状态,而另一个线程又调用了该阻塞线程的 interrupt 方法,这将导致该通道被关闭,并且已阻塞线程接将会收到ClosedByInterruptException,并且设置已阻塞线程的中断状态。另外,如果已设置某个线程的中断状态并且它在通道上调用某个阻塞的 I/O 操作,则该通道将关闭并且该线程立即接收到 ClosedByInterruptException;并仍然设置其中断状态。 +2. 如果线程阻塞于Selector调用,则线程的中断标志位会被设置,同时,阻塞的调用会立即返回。 +3. InputStream的read调用,该操作是不可中断的,如果流中没有数据,read会阻塞 (但线程状态依然是RUNNABLE),且不响应interrupt(),与synchronized类似,调用interrupt()只会设置线程的中断标志,同时由于read阻塞,当前线程也无法检测中断标志。 + + + diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/Shutdown.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/Shutdown.java new file mode 100644 index 00000000..48e7d1c0 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/Interrupted/Shutdown.java @@ -0,0 +1,32 @@ +package cn.lastwhisper.concurrent.basic.Interrupted; + +public class Shutdown { + + public static void main(String[] args) throws InterruptedException { + Thread t1 = new Thread(new Runnable() { + @Override + public void run() { + while (true) { + // 中断的比stop更为强劲。如果在循环体中,出现了类似于wait()方法或者sleep(方法这样的操作,则只能通过中断来识别了。 + if (Thread.currentThread().isInterrupted()) { + System.out.println("Interrupted!"); + break; + } + try { + // 当线程在waiting、time_waiting时,如果被中断,就会产生InterruptedException + Thread.sleep(2000); + } catch (InterruptedException e) { + System.out.println("Interrupted When Sleep"); + // 设置中断状态 + Thread.currentThread().interrupt(); + } + } + } + }, "Shutdown"); + + t1.start(); + Thread.sleep(2000); + t1.interrupt(); + } + +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/JoinDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/JoinDemo.java deleted file mode 100644 index eb841168..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/JoinDemo.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.lastwhisper.concurrent.basic; - -public class JoinDemo { - static class A extends Thread { - @Override - public void run() { - System.out.println("A"); - } - } - - static class B extends Thread { - private A a; - - B(A a) { - this.a = a; - } - - @Override - public void run() { - try { - a.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("B"); - } - } - - public void test() { - A a = new A(); - B b = new B(a); - b.start(); - a.start(); - } - - public static void main(String[] args) { - JoinDemo example = new JoinDemo(); - example.test(); - } -} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/README.md b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/README.md new file mode 100644 index 00000000..ad215bfa --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/README.md @@ -0,0 +1,10 @@ +# basic +1. communicate ;线程通信相关 +2. createthread;线程创建相关 +3. Interrupted ;线程中断相关 +4. state ;线程状态相关 +5. syncronized ;线程锁、锁升级相关 +6. threadlocal ; +7. DeadLockDemo;死锁 demo +8. Daemon;守护线程 +9. Deprecated;线程暂停、恢复和停止对应线程Thread的API就是suspend()、resume()和stop(),这些方法已经被废弃 \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/SleepUtils.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/SleepUtils.java new file mode 100644 index 00000000..1c37fb47 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/SleepUtils.java @@ -0,0 +1,13 @@ +package cn.lastwhisper.concurrent.basic; + +import java.util.concurrent.TimeUnit; + +public class SleepUtils { + public static void second(long seconds) { + try { + TimeUnit.SECONDS.sleep(seconds); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/TestThread8Monitor.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/TestThread8Monitor.java deleted file mode 100644 index bcfdfd6e..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/TestThread8Monitor.java +++ /dev/null @@ -1,61 +0,0 @@ -package cn.lastwhisper.concurrent.basic; - -/** - * 前置知识: - * 对象锁: - * 1)对象锁也叫方法锁,是针对一个对象实例的,它只在该对象的某个内存位置声明一个标识该对象是否拥有锁,所有它只会锁住当前的对象,而并不会对其他对象实例的锁产生任何影响,不同对象访问同一个被synchronized修饰的方法的时候不会阻塞 - * 2)synchronized修饰的非静态方法,即非静态同步方法 - * 3)synchronized(this),即非静态同步代码块 - * 类锁: - * 1)synchronized static 修饰的静态方法,即静态同步方法 - * 2)synchronized(类名.class),即静态同步代码块 - * 题目:判断打印的 1 or 2 or 3? - * 1. 两个普通同步方法,两个线程,打印? //one two - * 2. 新增 Thread.sleep() 给 getOne() ,打印? //one two - * 3. 新增普通方法 getThree() , 打印? //three one two - * 4. 两个普通同步方法,两个 Number 对象,打印? //two one - * 5. 修改 getOne() 为静态同步方法,打印? //two one - * 6. 修改两个方法均为静态同步方法,一个 Number 对象? //one two - * 7. 一个静态同步方法,一个非静态同步方法,两个 Number 对象? //two one - * 8. 两个静态同步方法,两个 Number 对象? //one two - * @author lastwhisper - */ -public class TestThread8Monitor { - public static void main(String[] args) { - Number number1 = new Number(); - Number number2 = new Number(); - - new Thread(new Runnable() { - @Override - public void run() { - number1.getOne(); - } - }).start(); - - new Thread(new Runnable() { - @Override - public void run() { - number2.getTwo(); - } - }).start(); - } -} - -class Number { - public static synchronized void getOne(){ - try { - Thread.sleep(50); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("one"); - } - - public void getTwo() { - System.out.println("two"); - } - - public void getThree() { - System.out.println("three"); - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/ThreadDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/ThreadDemo.java deleted file mode 100644 index 2cdc5fec..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/ThreadDemo.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.lastwhisper.concurrent.basic; - -/** - * @author lastwhisper - */ -public class ThreadDemo { - public static void main(String[] args){ - // 继承Thread - // 实现Runnable - // 实现Callable - // - System.out.println(Runtime.getRuntime().availableProcessors()); - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/communicate/Join.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/communicate/Join.java new file mode 100644 index 00000000..3cbd2128 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/communicate/Join.java @@ -0,0 +1,32 @@ +package cn.lastwhisper.concurrent.basic.communicate; + +public class Join { + public static void main(String[] args){ + System.out.println("MainThread run start."); + + //启动一个子线程 + Thread lock = new Thread(new Runnable() { + @Override + public void run() { + System.out.println("threadA run start."); + try { + Thread.sleep(1000); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println("threadA run finished."); + } + }); + lock.start(); + + System.out.println("MainThread join before"); + try { + // main持有lock线程的锁,lock.wait() 阻塞main线程 + // lock线程执行完了,会调用lock.notify_all(thread),唤醒main线程 + lock.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("MainThread run finished."); + } +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/communicate/Piped.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/communicate/Piped.java new file mode 100644 index 00000000..129d1eef --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/communicate/Piped.java @@ -0,0 +1,44 @@ +package cn.lastwhisper.concurrent.basic.communicate; + +import java.io.IOException; +import java.io.PipedReader; +import java.io.PipedWriter; + +public class Piped { + + public static void main(String[] args) throws Exception { + PipedWriter out = new PipedWriter(); + PipedReader in = new PipedReader(); + // 将输出流和输入流进行连接,否则在使用时会抛出IOException + out.connect(in); + + Thread printThread = new Thread(new Print(in), "PrintThread"); + printThread.start(); + int receive = 0; + try { + while ((receive = System.in.read()) != -1) { + out.write(receive); + } + } finally { + out.close(); + } + } + + static class Print implements Runnable { + private PipedReader in; + + public Print(PipedReader in) { + this.in = in; + } + + public void run() { + int receive = 0; + try { + while ((receive = in.read()) != -1) { + System.out.print((char) receive); + } + } catch (IOException ex) { + } + } + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/communicate/README.md b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/communicate/README.md new file mode 100644 index 00000000..b27131a7 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/communicate/README.md @@ -0,0 +1,5 @@ +# 线程间通信 +1. WaitNotify +2. Join +3. Piped;管道输入/输出流和普通的文件输入/输出流或者网络输入/输出流不同之处在于,它主要 + 用于线程之间的数据传输,而传输的媒介为内存。 diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/communicate/WaitNotify.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/communicate/WaitNotify.java new file mode 100644 index 00000000..38a6dd1e --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/communicate/WaitNotify.java @@ -0,0 +1,61 @@ +package cn.lastwhisper.concurrent.basic.communicate; + +import cn.lastwhisper.concurrent.basic.SleepUtils; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.concurrent.TimeUnit; + +public class WaitNotify { + static boolean flag = true; + static final Object lock = new Object(); + + public static void main(String[] args) throws Exception { + Thread waitThread = new Thread(new Wait(), "WaitThread"); + waitThread.start(); + TimeUnit.SECONDS.sleep(1); + + Thread notifyThread = new Thread(new Notify(), "NotifyThread"); + notifyThread.start(); + } + + static class Wait implements Runnable { + public void run() { + // 加锁,拥有lock的Monitor + synchronized (lock) { + // 当条件不满足时,继续wait,同时释放了lock的锁 + while (flag) { + try { + System.out.println(Thread.currentThread() + " flag is true. wait @ " + + new SimpleDateFormat("HH:mm:ss").format(new Date())); + lock.wait(); + } catch (InterruptedException e) { + } + } + // 条件满足时,完成工作 + System.out.println(Thread.currentThread() + " flag is false. running @ " + + new SimpleDateFormat("HH:mm:ss").format(new Date())); + } + } + } + + static class Notify implements Runnable { + public void run() { + // 加锁,拥有lock的Monitor + synchronized (lock) { + // 获取lock的锁,然后进行通知,通知时不会释放lock的锁, + // 直到当前线程释放了lock后,WaitThread才能从wait方法中返回 + System.out.println(Thread.currentThread() + " hold lock. notify @ " + new SimpleDateFormat("HH:mm:ss").format(new Date())); + lock.notifyAll(); + flag = false; + SleepUtils.second(5); + } + // 再次加锁 + synchronized (lock) { + System.out.println(Thread.currentThread() + " hold lock again. sleep @ " + + new SimpleDateFormat("HH:mm:ss").format(new Date())); + SleepUtils.second(5); + } + } + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/TestCallable.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/createthread/TestCallable.java similarity index 95% rename from java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/TestCallable.java rename to java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/createthread/TestCallable.java index 3ea39b55..2ffa2e07 100644 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/TestCallable.java +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/createthread/TestCallable.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.concurrent.juc.executor; +package cn.lastwhisper.concurrent.basic.createthread; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/state/ThreadState.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/state/ThreadState.java new file mode 100644 index 00000000..28399a08 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/state/ThreadState.java @@ -0,0 +1,107 @@ +package cn.lastwhisper.concurrent.basic.state; + +import cn.lastwhisper.concurrent.basic.SleepUtils; +import org.apache.tomcat.util.http.fileupload.IOUtils; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Scanner; + +/** + * 线程状态 + * + * @author cunchang + * @date 2022/4/4 10:26 PM + */ +public class ThreadState { + + public static void main(String[] args) { + new Thread(new TimeWaiting(), "TimeWaitingThread-TIMED_WAITING").start(); + new Thread(new Waiting(), "WaitingThread-WAITING").start(); + // 使用两个Blocked线程,一个获取锁成功,另一个被阻塞 + new Thread(new Blocked(), "BlockedThread-1").start(); + new Thread(new Blocked(), "BlockedThread-2").start(); + new Thread(new IOBlockedState(), "IOBlockedThread-RUNNABLE").start(); + new Thread(new SocketBlockedState(), "SocketBlockedThread-RUNNABLE").start(); + } + + // 该线程不断地进行睡眠 + static class TimeWaiting implements Runnable { + @Override + public void run() { + while (true) { + SleepUtils.second(100); + } + } + } + + // 该线程在Waiting.class实例上等待 + static class Waiting implements Runnable { + @Override + public void run() { + while (true) { + synchronized (Waiting.class) { + try { + Waiting.class.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + } + + // 该线程在Blocked.class实例上加锁后,不会释放该锁 + static class Blocked implements Runnable { + @Override + public void run() { + synchronized (Blocked.class) { + while (true) { + SleepUtils.second(100); + } + } + } + } + + // os io阻塞 + static class IOBlockedState implements Runnable { + Scanner in = new Scanner(System.in); + @Override + public void run() { + try { + // 命令行中的阻塞读 + String input = in.nextLine(); + System.out.println(input); + } catch (Exception e) { + e.printStackTrace(); + } finally { + IOUtils.closeQuietly(in); + } + } + } + + static class SocketBlockedState implements Runnable { + @Override + public void run() { + ServerSocket serverSocket = null; + try { + serverSocket = new ServerSocket(10086); + while (true) { + // 阻塞的accept方法 + Socket socket = serverSocket.accept(); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + serverSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/state/jstack.txt b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/state/jstack.txt new file mode 100644 index 00000000..87c6875b --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/state/jstack.txt @@ -0,0 +1,62 @@ + +"SocketBlockedThread-RUNNABLE" #15 prio=5 os_prio=31 tid=0x00007f86ae0c4000 nid=0x9a13 runnable [0x0000000305f92000] + java.lang.Thread.State: RUNNABLE + at java.net.PlainSocketImpl.socketAccept(Native Method) + at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409) + at java.net.ServerSocket.implAccept(ServerSocket.java:545) + at java.net.ServerSocket.accept(ServerSocket.java:513) + at cn.lastwhisper.concurrent.basic.state.ThreadState$SocketBlockedState.run(ThreadState.java:92) + at java.lang.Thread.run(Thread.java:748) + +"IOBlockedThread-RUNNABLE" #14 prio=5 os_prio=31 tid=0x00007f86ae0c3000 nid=0x9c1f runnable [0x0000000305e8f000] + java.lang.Thread.State: RUNNABLE + at java.io.FileInputStream.readBytes(Native Method) + at java.io.FileInputStream.read(FileInputStream.java:255) + at java.io.BufferedInputStream.read1(BufferedInputStream.java:284) + at java.io.BufferedInputStream.read(BufferedInputStream.java:345) + - locked <0x000000076ab21a38> (a java.io.BufferedInputStream) + at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) + at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) + at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) + - locked <0x000000076abde010> (a java.io.InputStreamReader) + at java.io.InputStreamReader.read(InputStreamReader.java:184) + at java.io.Reader.read(Reader.java:100) + at java.util.Scanner.readInput(Scanner.java:804) + at java.util.Scanner.findWithinHorizon(Scanner.java:1685) + at java.util.Scanner.nextLine(Scanner.java:1538) + at cn.lastwhisper.concurrent.basic.state.ThreadState$IOBlockedState.run(ThreadState.java:74) + at java.lang.Thread.run(Thread.java:748) + +"BlockedThread-2" #13 prio=5 os_prio=31 tid=0x00007f86ae0b5800 nid=0x6303 waiting for monitor entry [0x0000000305d8c000] + java.lang.Thread.State: BLOCKED (on object monitor) + at cn.lastwhisper.concurrent.basic.state.ThreadState$Blocked.run(ThreadState.java:61) + - waiting to lock <0x000000076abd3f90> (a java.lang.Class for cn.lastwhisper.concurrent.basic.state.ThreadState$Blocked) + at java.lang.Thread.run(Thread.java:748) + +"BlockedThread-1" #12 prio=5 os_prio=31 tid=0x00007f86ae0b4800 nid=0x6203 waiting on condition [0x0000000305c89000] + java.lang.Thread.State: TIMED_WAITING (sleeping) + at java.lang.Thread.sleep(Native Method) + at java.lang.Thread.sleep(Thread.java:340) + at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386) + at cn.lastwhisper.concurrent.basic.state.SleepUtils.second(SleepUtils.java:8) + at cn.lastwhisper.concurrent.basic.state.ThreadState$Blocked.run(ThreadState.java:61) + - locked <0x000000076abd3f90> (a java.lang.Class for cn.lastwhisper.concurrent.basic.state.ThreadState$Blocked) + at java.lang.Thread.run(Thread.java:748) + +"WaitingThread" #11 prio=5 os_prio=31 tid=0x00007f86be835000 nid=0x9f23 in Object.wait() [0x0000000305b86000] + java.lang.Thread.State: WAITING (on object monitor) + at java.lang.Object.wait(Native Method) + - waiting on <0x000000076abcf4d8> (a java.lang.Class for cn.lastwhisper.concurrent.basic.state.ThreadState$Waiting) + at java.lang.Object.wait(Object.java:502) + at cn.lastwhisper.concurrent.basic.state.ThreadState$Waiting.run(ThreadState.java:45) + - locked <0x000000076abcf4d8> (a java.lang.Class for cn.lastwhisper.concurrent.basic.state.ThreadState$Waiting) + at java.lang.Thread.run(Thread.java:748) + +"TimeWaitingThread" #10 prio=5 os_prio=31 tid=0x00007f86be0bf800 nid=0xa05f waiting on condition [0x0000000305a83000] + java.lang.Thread.State: TIMED_WAITING (sleeping) + at java.lang.Thread.sleep(Native Method) + at java.lang.Thread.sleep(Thread.java:340) + at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386) + at cn.lastwhisper.concurrent.basic.state.SleepUtils.second(SleepUtils.java:8) + at cn.lastwhisper.concurrent.basic.state.ThreadState$TimeWaiting.run(ThreadState.java:33) + at java.lang.Thread.run(Thread.java:748) diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/Juc_PrintMarkWord.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/Juc_PrintMarkWord.java new file mode 100644 index 00000000..b714be92 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/Juc_PrintMarkWord.java @@ -0,0 +1,38 @@ +package cn.lastwhisper.concurrent.basic.synchronized1; + +import org.openjdk.jol.info.ClassLayout; + +/** + * + * @author cunchang + * @date 2022/3/2 8:26 PM + */ +public class Juc_PrintMarkWord { + + public static void main(String[] args) throws InterruptedException { + // 需要sleep一段时间,因为java对于偏向锁的启动是在启动几秒之后才激活。 + // 因为jvm启动的过程中会有大量的同步块,且这些同步块都有竞争,如果一启动就启动 + // 偏向锁,会出现很多没有必要的锁撤销 + Thread.sleep(5000); + T t = new T(); + //未出现任何获取锁的时候 + System.out.println(ClassLayout.parseInstance(t).toPrintable()); + synchronized (t){ + // 获取一次锁之后 + System.out.println(ClassLayout.parseInstance(t).toPrintable()); + } + // 输出hashcode + System.out.println("hashCode:"+t.hashCode()); + // 计算了hashcode之后,将导致锁的升级 + // 锁已经释放了,输出无锁markword + System.out.println(ClassLayout.parseInstance(t).toPrintable()); + synchronized (t){ + // 再次获取锁,锁升级,轻量级锁 + System.out.println(ClassLayout.parseInstance(t).toPrintable()); + } + } +} + +class T{ + int i = 0; +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/README.md b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/README.md new file mode 100644 index 00000000..ac8baff2 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/README.md @@ -0,0 +1,8 @@ +# synchronize原理 + +使用jol-core + +1. T0_ObjectSize;无锁、可偏向锁 +2. T0_BasicLock;偏向锁-》轻量级锁 +3. T0_heavyWeightMonitor;自旋锁后未获得到锁,升级重量级锁, +4. Juc_PrintMarkWord;对象处在偏向锁,调用hashcode,会升级为轻量级锁,因为偏向锁无法记录hashcode。 diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/T0_BasicLock.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/T0_BasicLock.java new file mode 100644 index 00000000..41dde330 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/T0_BasicLock.java @@ -0,0 +1,37 @@ +package cn.lastwhisper.concurrent.basic.synchronized1; + +import lombok.extern.slf4j.Slf4j; +import org.openjdk.jol.info.ClassLayout; + + +@Slf4j +public class T0_BasicLock { + public static void main(String[] args) { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + Object o = new Object(); + log.info(ClassLayout.parseInstance(o).toPrintable()); + + new Thread(()->{ + synchronized (o){ + log.info(ClassLayout.parseInstance(o).toPrintable()); + } + }).start(); + + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + log.info(ClassLayout.parseInstance(o).toPrintable()); + new Thread(()->{ + synchronized (o){ + log.info(ClassLayout.parseInstance(o).toPrintable()); + } + }).start(); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/T0_ObjectSize.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/T0_ObjectSize.java new file mode 100644 index 00000000..a32c3d8c --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/T0_ObjectSize.java @@ -0,0 +1,37 @@ +package cn.lastwhisper.concurrent.basic.synchronized1; + +import org.openjdk.jol.info.ClassLayout; + +import java.util.concurrent.TimeUnit; + +/** + * 打印object信息 + * + * @author cunchang + * @date 2022/3/2 8:26 PM + */ +public class T0_ObjectSize { + + public static void main(String[] args) throws InterruptedException { + // 1、无锁;未启用偏向锁 +// Object o = new Object(); +// System.out.println(ClassLayout.parseInstance(o).toPrintable()); + // 2、有锁;未启用偏向锁 + // 偏向锁会延迟使用,所以无锁直接升级为轻量级锁 +// Object o = new Object(); +// System.out.println(ClassLayout.parseInstance(o).toPrintable()); +// synchronized (o) { +// System.out.println(ClassLayout.parseInstance(o).toPrintable()); +// } + // 3、有锁;启用偏向锁 + // 延迟执行,让jvm启动偏向锁 + TimeUnit.SECONDS.sleep(5); + Object object = new Object(); + object.notify(); + object.notifyAll(); + System.out.println(ClassLayout.parseInstance(object).toPrintable()); + synchronized (object){ + System.out.println(ClassLayout.parseInstance(object).toPrintable()); + } + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/T0_ObjectStackAlloc.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/T0_ObjectStackAlloc.java new file mode 100644 index 00000000..30aaf532 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/T0_ObjectStackAlloc.java @@ -0,0 +1,44 @@ +package cn.lastwhisper.concurrent.basic.synchronized1; + + +public class T0_ObjectStackAlloc { + + /** + * 进行两种测试 + * 关闭逃逸分析,同时调大堆空间,避免堆内GC的发生,如果有GC信息将会被打印出来 + * VM运行参数:-Xmx4G -Xms4G -XX:-DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError + * + * 开启逃逸分析 + * VM运行参数:-Xmx4G -Xms4G -XX:+DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError + * + * 执行main方法后 + * jps 查看进程 + * jmap -histo 进程ID + */ + public static void main(String[] args) { + long start = System.currentTimeMillis(); + for (int i = 0; i < 500000; i++) { + alloc(); + } + long end = System.currentTimeMillis(); + //查看执行时间 + System.out.println("cost-time " + (end - start) + " ms"); + try { + Thread.sleep(100000); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + } + + private static TulingStudent alloc() { + //Jit对编译时会对代码进行 逃逸分析 + //并不是所有对象存放在堆区,有的一部分存在线程栈空间 + TulingStudent student = new TulingStudent(); + return student; + } + + static class TulingStudent { + private String name; + private int age; + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/T0_heavyWeightMonitor.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/T0_heavyWeightMonitor.java new file mode 100644 index 00000000..27470c8d --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/synchronized1/T0_heavyWeightMonitor.java @@ -0,0 +1,45 @@ +package cn.lastwhisper.concurrent.basic.synchronized1; + +import org.openjdk.jol.info.ClassLayout; + + +public class T0_heavyWeightMonitor { + + public static void main(String[] args) throws InterruptedException { + Thread.sleep(5000); + Object a = new Object(); + + Thread thread1 = new Thread(){ + @Override + public void run() { + synchronized (a){ + System.out.println("thread1 locking"); + System.out.println(ClassLayout.parseInstance(a).toPrintable()); + try { + //让线程晚点儿死亡,造成锁的竞争 + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + }; + Thread thread2 = new Thread(){ + @Override + public void run() { + synchronized (a){ + System.out.println("thread2 locking"); + System.out.println(ClassLayout.parseInstance(a).toPrintable()); + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + }; + thread1.start(); + thread2.start(); + } + +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/AlibabaThreadLocalDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/AlibabaThreadLocalDemo.java new file mode 100644 index 00000000..faa2e44f --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/AlibabaThreadLocalDemo.java @@ -0,0 +1,62 @@ +package cn.lastwhisper.concurrent.basic.threadlocal; + +import com.alibaba.ttl.TransmittableThreadLocal; +import com.alibaba.ttl.TtlRunnable; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * @author cunchang + * @date 2022/4/28 7:54 PM + */ +public class AlibabaThreadLocalDemo { + public static void main(String[] args) throws InterruptedException { + final TransmittableThreadLocal context = new TransmittableThreadLocal<>(); + context.set(new Span("xiexiexie")); + //输出 xiexiexie + Object o = context.get(); + System.out.println("main get Span:"+o); + Runnable runnable = new Runnable() { + @Override + public void run() { + System.out.println("========"); + Object o = context.get(); + System.out.println("t get Span:"+o); + context.set(new Span("zhangzhangzhang")); + o = context.get(); + System.out.println("t update Span:"+o); + } + }; + + ExecutorService executorService = Executors.newFixedThreadPool(1); + executorService.submit(TtlRunnable.get(runnable)); + TimeUnit.SECONDS.sleep(1); + executorService.submit(TtlRunnable.get(runnable)); + TimeUnit.SECONDS.sleep(1); + System.out.println("========"); + Span span = context.get(); + System.out.println("main last again get Span:"+o); + + + executorService.shutdown(); + } + + static class Span { + public String name; + public int age; + + public Span(String name) { + this.name = name; + } + + @Override + public String toString() { + return "Span{" + + "name='" + name + '\'' + + ", age=" + age + + '}'; + } + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/InheritableThreadLocalDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/InheritableThreadLocalDemo.java new file mode 100644 index 00000000..bf0f72ec --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/InheritableThreadLocalDemo.java @@ -0,0 +1,49 @@ +package cn.lastwhisper.concurrent.basic.threadlocal; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * @author cunchang + * @date 2022/4/28 7:54 PM + */ +public class InheritableThreadLocalDemo { + public static void main(String[] args) throws InterruptedException { + final InheritableThreadLocal inheritableThreadLocal = new InheritableThreadLocal(); + inheritableThreadLocal.set(new Span("xiexiexie")); + //输出 xiexiexie + Object o = inheritableThreadLocal.get(); + System.out.println("main get Span:"+o); + Thread thread = new Thread() { + @Override + public void run() { + System.out.println("========"); + Object o = inheritableThreadLocal.get(); + System.out.println("t get Span:"+o); + inheritableThreadLocal.set(new Span("zhangzhangzhang")); + o = inheritableThreadLocal.get(); + System.out.println("t update Span:"+o); + } + }; + thread.start(); + thread.join(); + } + + static class Span { + public String name; + public int age; + + public Span(String name) { + this.name = name; + } + + @Override + public String toString() { + return "Span{" + + "name='" + name + '\'' + + ", age=" + age + + '}'; + } + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/InheritableThreadLocalDemo2.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/InheritableThreadLocalDemo2.java new file mode 100644 index 00000000..11e71889 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/InheritableThreadLocalDemo2.java @@ -0,0 +1,59 @@ +package cn.lastwhisper.concurrent.basic.threadlocal; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * @author cunchang + * @date 2022/4/28 7:54 PM + */ +public class InheritableThreadLocalDemo2 { + public static void main(String[] args) throws InterruptedException { + final InheritableThreadLocal inheritableThreadLocal = new InheritableThreadLocal(); + inheritableThreadLocal.set(new Span("xiexiexie")); + //输出 xiexiexie + Object o = inheritableThreadLocal.get(); + System.out.println("main get Span:"+o); + Runnable runnable = new Runnable() { + @Override + public void run() { + System.out.println("========"); + Object o = inheritableThreadLocal.get(); + System.out.println("t get Span:"+o); + inheritableThreadLocal.set(new Span("zhangzhangzhang")); + o = inheritableThreadLocal.get(); + System.out.println("t update Span:"+o); + } + }; + + ExecutorService executorService = Executors.newFixedThreadPool(1); + executorService.submit(runnable); + TimeUnit.SECONDS.sleep(1); + executorService.submit(runnable); + TimeUnit.SECONDS.sleep(1); + System.out.println("========"); + Span span = inheritableThreadLocal.get(); + System.out.println("main last again get Span:"+o); + + + executorService.shutdown(); + } + + static class Span { + public String name; + public int age; + + public Span(String name) { + this.name = name; + } + + @Override + public String toString() { + return "Span{" + + "name='" + name + '\'' + + ", age=" + age + + '}'; + } + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/README.md b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/README.md new file mode 100644 index 00000000..9b994f20 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/README.md @@ -0,0 +1,7 @@ + + +1. ThreadLocalDemo;的用法 +2. ThreadLocalDemo2;一个线程多个local +3. InheritableThreadLocalDemo;InheritableThreadLocal解决父子线程local传递问题 +4. InheritableThreadLocalDemo2;InheritableThreadLocal在线程池中的窘境 +5. AlibabaThreadLocalDemo;通过修饰runnable解决InheritableThreadLocal的问题 diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/ThreadLocalDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/ThreadLocalDemo.java index 67cc4549..6db17541 100644 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/ThreadLocalDemo.java +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/ThreadLocalDemo.java @@ -11,7 +11,7 @@ * @author lastwhisper */ public class ThreadLocalDemo { - //private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); static ThreadLocal tl = new ThreadLocal<>(); public static class ParseDate implements Runnable{ @@ -23,10 +23,10 @@ public ParseDate(int i) { @Override public void run() { try { - //Date t = sdf.parse("2015-03-28 19:15:" + i % 60); if(tl.get()==null){ tl.set(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); } +// Date t = sdf.parse("2015-03-28 19:15:" + i % 60); Date t = tl.get().parse("2015-03-28 19:15:" + i % 60); System.out.println(i+"\t"+t); } catch (ParseException e) { @@ -40,6 +40,6 @@ public static void main(String[] args){ for (int i = 0; i < 10; i++) { pool.execute(new ParseDate(i)); } - + pool.shutdown(); } } diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/ThreadLocalDemo2.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/ThreadLocalDemo2.java new file mode 100644 index 00000000..f92b9e27 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/ThreadLocalDemo2.java @@ -0,0 +1,22 @@ +package cn.lastwhisper.concurrent.basic.threadlocal; + +/** + * ThreadLocal原理 + * + * @author lastwhisper + */ +public class ThreadLocalDemo2 { + + static ThreadLocal tl1 = new ThreadLocal<>(); + static ThreadLocal tl2 = new ThreadLocal<>(); + + public static void main(String[] args){ + tl1.set(1); + System.out.println(tl1.get()); + System.out.println(tl2.get()); + tl2.set(2); + System.out.println(tl1.get()); + System.out.println(tl2.get()); + } + +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/ThreadLocalNotSafe.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/ThreadLocalNotSafe.java deleted file mode 100644 index b28c41c1..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/threadlocal/ThreadLocalNotSafe.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.lastwhisper.concurrent.basic.threadlocal; - -/** - * @author lastwhisper - */ -public class ThreadLocalNotSafe { - static class Container { - int num; - } - - public static void main(String[] args) throws InterruptedException { - ThreadLocal tl = new ThreadLocal<>(); - tl.set(new Container()); // 先set下ThreadLocal - - Container container = tl.get(); - Runnable task = () -> { - for (int i = 0; i < 10000; i++) { - container.num++; - } - }; - - //Thread t1 = new Thread(task); - Thread t2 = new Thread(task); - - //t1.start(); - t2.start(); - //t1.join(); - t2.join(); - - System.out.println(tl.get().num); - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/volatileDemo/VolatileDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/volatileDemo/VolatileDemo.java index 82b308bb..1fcd5094 100644 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/volatileDemo/VolatileDemo.java +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/volatileDemo/VolatileDemo.java @@ -5,6 +5,10 @@ */ public class VolatileDemo implements Runnable { + /** + * 无volatile程序不会结束,主线程无法感知update线程修改的值 + * + */ private volatile boolean[] flag = {false}; @Override @@ -24,7 +28,7 @@ public boolean isFlag() { public static void main(String[] args) throws InterruptedException { VolatileDemo runnable = new VolatileDemo(); - new Thread(runnable).start(); + new Thread(runnable,"update thread").start(); while (true) { if (runnable.isFlag()) { System.out.println("-----------------"); diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/README.md b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/README.md new file mode 100644 index 00000000..e9d4f929 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/README.md @@ -0,0 +1,5 @@ +# 线程的一些案例 +1. future;手写future +2. alternate;线程交替打印ABCABC +3. productconsumer;生产者消费者 + diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/future/FutureData.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/future/FutureData.java index 07359b69..a85f622e 100644 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/future/FutureData.java +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/future/FutureData.java @@ -3,25 +3,25 @@ //当有线程想要获取RealData时候,程序会被阻塞。等到RealData被注入才会使用getReal()方法 public class FutureData extends Data { - private boolean FLAG = false; + private boolean isReady = false; private RealData realData; //读取data数据 public synchronized void setRealData(RealData realData) { //读取结果 - if (FLAG) { //true 说明已经获取到结果了 如果获取到则直接返回结果 - System.out.println("FLAG:" + FLAG); + if (isReady) { //true 说明已经获取到结果了 如果获取到则直接返回结果 + System.out.println("FLAG:" + isReady); } //如果flag是false,没有获取到数据,传递realData对象 this.realData = realData; - FLAG = true; //获取到执行结果 改为true - notify();//唤醒 + isReady = true; //获取到执行结果 改为true + notifyAll();//唤醒 } @Override public synchronized String getRequest() { - while (!FLAG) { //如果false 一直等待 + while (!isReady) { //如果false 一直等待 try { wait(); } catch (InterruptedException e) { diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/future/README.md b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/future/README.md new file mode 100644 index 00000000..4e106898 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/future/README.md @@ -0,0 +1 @@ +手写future diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/future/RealData.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/future/RealData.java index 6cba16f7..03a59f95 100644 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/future/RealData.java +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/future/RealData.java @@ -6,14 +6,14 @@ public class RealData extends Data { private String requestData; public RealData(String requestData) { - System.out.println("正在使用data进行网络请求,data" + requestData + "开始"); + System.out.println("RealData——————正在使用requestData进行网络请求,requestData:[" + requestData + "],开始"); try { //模拟执行业务逻辑耗时时间 Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } - System.out.println("操作执行完毕...获取结果"); + System.out.println("RealData——————操作执行完毕...获取结果"); //获取返回结果 this.requestData = "结果"; } diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/v3/ProdConsumer_BlockQueueDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/blockqueue/ProdConsumer_BlockQueueDemo.java similarity index 97% rename from java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/v3/ProdConsumer_BlockQueueDemo.java rename to java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/blockqueue/ProdConsumer_BlockQueueDemo.java index 7b669b41..cb630ee6 100644 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/v3/ProdConsumer_BlockQueueDemo.java +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/blockqueue/ProdConsumer_BlockQueueDemo.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.concurrent.example.productconsumer.v3; +package cn.lastwhisper.concurrent.example.productconsumer.blockqueue; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/v2/TestProductAndConsumerForLock.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/lockcondition/TestProductAndConsumerForLock.java similarity index 97% rename from java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/v2/TestProductAndConsumerForLock.java rename to java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/lockcondition/TestProductAndConsumerForLock.java index 7e50c76f..93d97fdf 100644 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/v2/TestProductAndConsumerForLock.java +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/lockcondition/TestProductAndConsumerForLock.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.concurrent.example.productconsumer.v2; +package cn.lastwhisper.concurrent.example.productconsumer.lockcondition; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/v1/TestProductAndConsumer.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/waitnotify/TestProductAndConsumer.java similarity index 85% rename from java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/v1/TestProductAndConsumer.java rename to java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/waitnotify/TestProductAndConsumer.java index c465b731..ce518640 100644 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/v1/TestProductAndConsumer.java +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/waitnotify/TestProductAndConsumer.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.concurrent.example.productconsumer.v1; +package cn.lastwhisper.concurrent.example.productconsumer.waitnotify; /** * 生产者消费者案例(等待唤醒机制),使用synchronize+Object的wait和notify; @@ -17,8 +17,8 @@ public class TestProductAndConsumer { public static void main(String[] args) { Clerk clerk = new Clerk(); - new Thread(new Product(clerk), "生产者").start(); - new Thread(new Consumer(clerk), "消费者").start(); + new Thread(new Product(clerk), "生产者A").start(); + new Thread(new Consumer(clerk), "消费者B").start(); } } @@ -27,9 +27,9 @@ class Clerk { private int product = 0; //进货(生产者线程调用) - public synchronized void get() {//循环次数:2——》1 + public synchronized void stock() {//循环次数:2——》1 if (product >= 1) { - System.out.println("货物已满!"); +// System.out.println("货物已满!"); try { //货物满了之后生产者等待 this.wait(); @@ -37,7 +37,7 @@ public synchronized void get() {//循环次数:2——》1 e.printStackTrace(); } } else { - System.out.println(Thread.currentThread().getName() + " : " + ++product); + System.out.println(Thread.currentThread().getName() + "添加商品,剩余数量" + ++product); //生产货物之后唤醒消费者 this.notifyAll(); } @@ -46,7 +46,7 @@ public synchronized void get() {//循环次数:2——》1 //销售(消费者线程调用) public synchronized void sale() {//product:0——》1,循环次数:1——》0 if (product <= 0) { - System.out.println("货物为空!"); +// System.out.println("货物为空!"); try { //货物为空之后消费者等待 this.wait(); @@ -54,7 +54,7 @@ public synchronized void sale() {//product:0——》1,循环次数:1— e.printStackTrace(); } } else { - System.out.println(Thread.currentThread().getName() + " : " + --product); + System.out.println(Thread.currentThread().getName() + "销售商品,剩余数量" + --product); //消费货物之后唤醒生产者 this.notifyAll(); } @@ -77,7 +77,7 @@ public void run() { } catch (InterruptedException e) { e.printStackTrace(); } - clerk.get(); + clerk.stock(); } } } diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/v1/TestProductAndConsumer2.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/waitnotify/TestProductAndConsumer2.java similarity index 89% rename from java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/v1/TestProductAndConsumer2.java rename to java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/waitnotify/TestProductAndConsumer2.java index 6d5bdd6e..c9898d19 100644 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/v1/TestProductAndConsumer2.java +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/example/productconsumer/waitnotify/TestProductAndConsumer2.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.concurrent.example.productconsumer.v1; +package cn.lastwhisper.concurrent.example.productconsumer.waitnotify; /** * 生产者消费者案例(等待唤醒机制),使用synchronize+Object的wait和notify; @@ -38,7 +38,7 @@ class Clerk2 { //进货(生产者线程调用) public synchronized void get() { while (product >= 1) { - System.out.println("货物已满!"); +// System.out.println("货物已满!"); try { //货物满了之后生产者等待 this.wait(); @@ -46,7 +46,7 @@ public synchronized void get() { e.printStackTrace(); } } - System.out.println(Thread.currentThread().getName() + " : " + ++product); + System.out.println(Thread.currentThread().getName() + "添加商品,剩余数量" + ++product); //生产货物之后唤醒消费者 this.notifyAll(); } @@ -54,7 +54,7 @@ public synchronized void get() { //销售(消费者线程调用) public synchronized void sale() { while (product <= 0) { - System.out.println("货物为空!"); +// System.out.println("货物为空!"); try { //货物为空之后消费者等待 this.wait(); @@ -62,7 +62,7 @@ public synchronized void sale() { e.printStackTrace(); } } - System.out.println(Thread.currentThread().getName() + " : " + --product); + System.out.println(Thread.currentThread().getName() + "销售商品,剩余数量" + --product); //消费货物之后唤醒生产者 this.notifyAll(); diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/guava/TestRateLimiter.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/guava/TestRateLimiter.java deleted file mode 100644 index 460ab5a8..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/guava/TestRateLimiter.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.lastwhisper.concurrent.guava; - -import com.google.common.util.concurrent.RateLimiter; - -/** - * Guava的RateLimiter限流基于令牌桶算法 - * @author lastwhisper - */ -public class TestRateLimiter { - private static RateLimiter limiter = RateLimiter.create(3); - - public static class Task implements Runnable { - @Override - public void run() { - System.out.println(System.currentTimeMillis()); - } - } - - public static void main(String[] args) { - for (int i = 0; i < 50; i++) { - limiter.acquire(); - new Thread(new Task()).start(); - } - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/guava/TokenBucket.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/guava/TokenBucket.java deleted file mode 100644 index 74efa87c..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/guava/TokenBucket.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.lastwhisper.concurrent.guava; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -// 因为令牌桶对业务有一定的容忍度 -public class TokenBucket { - - private int bucketNums = 100; // 桶的容量 - private int rate = 1; // 流入速度 - private int nowTokens; // 当前令牌数量 - private long timestamp = getNowTime(); // 时间 - - private long getNowTime() { - return System.currentTimeMillis(); - } - - private int min(int tokens) { - return Math.min(bucketNums, tokens); - } - - public boolean getToken() { - // 记录来拿令牌的时间 - long nowTime = getNowTime(); - // 添加令牌【判断该有多少个令牌】 - nowTokens = nowTokens + (int) ((nowTime - timestamp) * rate); - // 添加以后的令牌数量与桶的容量那个小 - nowTokens = min(nowTokens); - System.out.println("当前令牌数量" + nowTokens); - // 修改拿令牌的时间 - timestamp = nowTime; - // 判断令牌是否足够 - if (nowTokens < 1) { - return false; - } else { - nowTokens -= 1; - return true; - } - } - -} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/README.md b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/README.md new file mode 100644 index 00000000..b2a51333 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/README.md @@ -0,0 +1,13 @@ +# locks 锁相关 +# aqs aqs相关 +# tools +# executor +# blockingqueue +# lockfree 无锁 + + +locksupport waiting当前线程 +future 获取异步执行的结果 +completefuture 获取异步执行的结果 + + diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/AQSDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/AQSDemo.java new file mode 100644 index 00000000..7ed60546 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/AQSDemo.java @@ -0,0 +1,59 @@ +package cn.lastwhisper.concurrent.juc.aqs; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; + +/** + * + * on 2020/11/11 18:08 + */ +public class AQSDemo { + + public static void main(String[] args) { + + ReentrantLock lock = new ReentrantLock(); + + //带入一个银行办理业务的案例来模拟我们的AQS如何进行线程的管理和通知唤醒机制 + + // 3个线程模拟3个银行网点,受理窗口办理业务的客户 + + // A 顾客就是每一个顾客,此时受理窗口没有任何人,A可以直接办理 + new Thread(() -> { + try { + lock.lock(); + System.out.println("----------A thread come in"); + //暂停几秒钟线程 + try { + TimeUnit.MINUTES.sleep(20); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } finally { + lock.unlock(); + } + }, "A").start(); + + //第二个顾客,第2个线程 ---》,由于受理业务的窗口只有一个(只能一个线程持有锁),些时B只能等待 + //进入候客区 + new Thread(() -> { + try { + lock.lock(); + System.out.println("----------B thread come in"); + } finally { + lock.unlock(); + } + }, "B").start(); + + //第三个顾客,第3个线程 ---》,由于受理业务的窗口只有一个(只能一个线程持有锁),些时C只能等待 + //进入候客区 + new Thread(() -> { + try { + lock.lock(); + System.out.println("----------C thread come in"); + } finally { + lock.unlock(); + } + }, "C").start(); + + } +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/README.md b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/README.md new file mode 100644 index 00000000..f125cd53 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/README.md @@ -0,0 +1,4 @@ +1. ThreadNoSafe 线程不安全 +2. ThreadSafe 通过互斥保证线程安全 +3. mylock1 手动实现Lock,通过synchronized和wait、notify +4. mylock2 手动实现Lock,通过aqs \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/ThreadNoSafe.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/ThreadNoSafe.java new file mode 100644 index 00000000..8f2e8223 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/ThreadNoSafe.java @@ -0,0 +1,24 @@ +package cn.lastwhisper.concurrent.juc.aqs; + +/** + * @author lastwhisper + */ +public class ThreadNoSafe { + private static int m = 0; + + public static void main(String[] args) throws InterruptedException { + Thread[] threads = new Thread[100]; + for (int i = 0; i < threads.length; i++) { + threads[i] = new Thread(() -> { + for (int j = 0; j < 10000; j++) { + m++; + } + }); + } + + for (Thread t : threads) t.start(); + for (Thread t : threads) t.join();//等待所有线程运行结束 +// Thread.sleep(1000); + System.out.println(m); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/ThreadSafe.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/ThreadSafe.java new file mode 100644 index 00000000..a80302f2 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/ThreadSafe.java @@ -0,0 +1,36 @@ +package cn.lastwhisper.concurrent.juc.aqs; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * @author lastwhisper + */ +public class ThreadSafe { + private static int m = 0; + private static ReentrantLock lock = new ReentrantLock(); + + public static void main(String[] args) throws InterruptedException { + Thread[] threads = new Thread[100]; + for (int i = 0; i < threads.length; i++) { + threads[i] = new Thread(() -> { +// synchronized (Main.class) { +// for (int j = 0; j < 1000; j++) { +// m++; +// } +// } + try { + lock.lock(); + for (int j = 0; j < 1000; j++) m++; + } finally { + lock.unlock(); + } + }); + } + + for (Thread t : threads) t.start(); + for (Thread t : threads) t.join();//等待所有线程运行结束 + + System.out.println(m); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/mylock1/MLock.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/mylock1/MLock.java new file mode 100644 index 00000000..44e0b4db --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/mylock1/MLock.java @@ -0,0 +1,63 @@ +package cn.lastwhisper.concurrent.juc.aqs.mylock1; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; + +/** + * 正确 + * + * @author lastwhisper + */ +public class MLock implements Lock { + private volatile int i = 0; + + /** + * t1进来i=1; + * t2进来this.wait(); + * t3进来synchronized blocked + */ + @Override + public synchronized void lock() { + while (i != 0) { + try { + this.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + i = 1; + } + + @Override + public synchronized void lockInterruptibly() throws InterruptedException { + while (i != 0) { + this.wait(); + } + i = 1; + } + + @Override + public boolean tryLock() { + return false; + } + + @Override + public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { + return false; + } + + /** + * 这里用notify就够了,因为只有一个线程wait + */ + @Override + public synchronized void unlock() { + i = 0; + this.notify(); + } + + @Override + public Condition newCondition() { + return null; + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/mylock1/Main.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/mylock1/Main.java new file mode 100644 index 00000000..f5608356 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/mylock1/Main.java @@ -0,0 +1,31 @@ +package cn.lastwhisper.concurrent.juc.aqs.mylock1; + +import java.util.concurrent.locks.Lock; + +/** + * @author lastwhisper + */ +public class Main { + private static int m = 0; + private static Lock lock = new MLock(); + + public static void main(String[] args) throws InterruptedException { + Thread[] threads = new Thread[100]; + for (int i = 0; i < threads.length; i++) { + threads[i] = new Thread(() -> { + try { + lock.lock(); + for (int j = 0; j < 10000; j++) m++; + } finally { + lock.unlock(); + } + + }); + } + + for (Thread t : threads) t.start(); + for (Thread t : threads) t.join();//等待所有线程运行结束 + + System.out.println(m); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/mylock2/MLock.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/mylock2/MLock.java new file mode 100644 index 00000000..c0b9dc1b --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/mylock2/MLock.java @@ -0,0 +1,75 @@ +package cn.lastwhisper.concurrent.juc.aqs.mylock2; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.AbstractQueuedSynchronizer; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; + +/** + * 正确 + * 独占锁 + * @author lastwhisper + */ +public class MLock implements Lock { + private Sync sync = new Sync(); + + // 静态内部类,自定义同步器 + private class Sync extends AbstractQueuedSynchronizer { + // 当状态为0的时候获取锁 + @Override + protected boolean tryAcquire(int arg) { + assert arg == 1; + if (compareAndSetState(0, 1)) { + setExclusiveOwnerThread(Thread.currentThread());// 设置互斥锁 + return true; + } + return false; + } + // 释放锁,将状态设置为0 + @Override + protected boolean tryRelease(int arg) { + assert arg == 1; + if (!isHeldExclusively()) throw new IllegalMonitorStateException(); + setExclusiveOwnerThread(null); + setState(0); + return true; + } + + @Override + protected boolean isHeldExclusively() { + // 拿到当前排他线程是不是和当前线程一样,如果一样才释放 + return getExclusiveOwnerThread() == Thread.currentThread(); + } + } + + @Override + public void lock() { + sync.acquire(1); + } + + @Override + public void lockInterruptibly() throws InterruptedException { + + } + + @Override + public boolean tryLock() { + return false; + } + + @Override + public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { + return false; + } + + @Override + public void unlock() { + sync.release(1); + } + + @Override + public Condition newCondition() { + return null; + } + +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/mylock2/Main.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/mylock2/Main.java new file mode 100644 index 00000000..5914b363 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/mylock2/Main.java @@ -0,0 +1,31 @@ +package cn.lastwhisper.concurrent.juc.aqs.mylock2; + +import java.util.concurrent.locks.Lock; + +/** + * @author lastwhisper + */ +public class Main { + private static int m = 0; + private static Lock lock = new MLock(); + + public static void main(String[] args) throws InterruptedException { + Thread[] threads = new Thread[100]; + for (int i = 0; i < threads.length; i++) { + threads[i] = new Thread(() -> { + try { + lock.lock(); + for (int j = 0; j < 100; j++) m++; + } finally { + lock.unlock(); + } + + }); + } + + for (Thread t : threads) t.start(); + for (Thread t : threads) t.join();//等待所有线程运行结束 + + System.out.println(m); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s01/Main.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s01/Main.java deleted file mode 100644 index 8ecde27b..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s01/Main.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.lastwhisper.concurrent.juc.aqs.s01; - -/** - * @author lastwhisper - */ -public class Main { - private static int m = 0; - - public static void main(String[] args) throws InterruptedException { - Thread[] threads = new Thread[100]; - for (int i = 0; i < threads.length; i++) { - threads[i] = new Thread(() -> { - for (int j = 0; j < 100; j++) { - m++; - } - }); - } - - for (Thread t : threads) t.start(); - for (Thread t : threads) t.join();//等待所有线程运行结束 - - System.out.println(m); - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s02/Main.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s02/Main.java deleted file mode 100644 index f327dd8d..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s02/Main.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.lastwhisper.concurrent.juc.aqs.s02; - -import cn.lastwhisper.concurrent.juc.aqs.s04.MLock; - -import java.util.concurrent.locks.Lock; - -/** - * @author lastwhisper - */ -public class Main { - private static int m = 0; - private static Lock lock = new MLock(); - - public static void main(String[] args) throws InterruptedException { - Thread[] threads = new Thread[100]; - for (int i = 0; i < threads.length; i++) { - threads[i] = new Thread(() -> { - synchronized (Main.class) { - for (int j = 0; j < 100; j++) { - m++; - } - } - }); - } - - for (Thread t : threads) t.start(); - for (Thread t : threads) t.join();//等待所有线程运行结束 - - System.out.println(m); - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s03/Main.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s03/Main.java deleted file mode 100644 index 99f5a245..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s03/Main.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.lastwhisper.concurrent.juc.aqs.s03; - -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * @author lastwhisper - */ -public class Main { - private static int m = 0; - private static Lock lock = new ReentrantLock(); - - public static void main(String[] args) throws InterruptedException { - Thread[] threads = new Thread[100]; - for (int i = 0; i < threads.length; i++) { - threads[i] = new Thread(() -> { - try { - lock.lock(); - for (int j = 0; j < 100; j++) m++; - } finally { - lock.unlock(); - } - - }); - } - - for (Thread t : threads) t.start(); - for (Thread t : threads) t.join();//等待所有线程运行结束 - - System.out.println(m); - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s04/MLock.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s04/MLock.java deleted file mode 100644 index 6232ebff..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s04/MLock.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.lastwhisper.concurrent.juc.aqs.s04; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; - -/** - * 错误 - * @author lastwhisper - */ -public class MLock implements Lock { - private volatile int i = 0; - - @Override - public void lock() { - synchronized (this) { - i = 1; - } - } - - @Override - public void lockInterruptibly() throws InterruptedException { - - } - - @Override - public boolean tryLock() { - return false; - } - - @Override - public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { - return false; - } - - @Override - public void unlock() { - synchronized (this) { - i = 0; - } - } - - @Override - public Condition newCondition() { - return null; - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s04/Main.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s04/Main.java deleted file mode 100644 index 948a91d2..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s04/Main.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.lastwhisper.concurrent.juc.aqs.s04; - -import java.util.concurrent.locks.Lock; - -/** - * @author lastwhisper - */ -public class Main { - private static int m = 0; - private static Lock lock = new MLock(); - - public static void main(String[] args) throws InterruptedException { - Thread[] threads = new Thread[100]; - for (int i = 0; i < threads.length; i++) { - threads[i] = new Thread(() -> { - try { - lock.lock(); - for (int j = 0; j < 100; j++) m++; - } finally { - lock.unlock(); - } - - }); - } - - for (Thread t : threads) t.start(); - for (Thread t : threads) t.join();//等待所有线程运行结束 - - System.out.println(m); - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s05/MLock.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s05/MLock.java deleted file mode 100644 index 2e822b34..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s05/MLock.java +++ /dev/null @@ -1,55 +0,0 @@ -package cn.lastwhisper.concurrent.juc.aqs.s05; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; - -/** - * 正确 - * @author lastwhisper - */ -public class MLock implements Lock { - private volatile int i = 0; - - @Override - public void lock() { - synchronized (this) { - while (i != 0) { - try { - this.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - i = 1; - } - } - - @Override - public void lockInterruptibly() throws InterruptedException { - - } - - @Override - public boolean tryLock() { - return false; - } - - @Override - public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { - return false; - } - - @Override - public void unlock() { - synchronized (this) { - i = 0; - this.notify(); - } - } - - @Override - public Condition newCondition() { - return null; - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s05/Main.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s05/Main.java deleted file mode 100644 index f8912a78..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s05/Main.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.lastwhisper.concurrent.juc.aqs.s05; - -import java.util.concurrent.locks.Lock; - -/** - * @author lastwhisper - */ -public class Main { - private static int m = 0; - private static Lock lock = new MLock(); - - public static void main(String[] args) throws InterruptedException { - Thread[] threads = new Thread[100]; - for (int i = 0; i < threads.length; i++) { - threads[i] = new Thread(() -> { - try { - lock.lock(); - for (int j = 0; j < 100; j++) m++; - } finally { - lock.unlock(); - } - - }); - } - - for (Thread t : threads) t.start(); - for (Thread t : threads) t.join();//等待所有线程运行结束 - - System.out.println(m); - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s06/MLock.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s06/MLock.java deleted file mode 100644 index 8aafadee..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s06/MLock.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.lastwhisper.concurrent.juc.aqs.s06; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; - -/** - * 错误 - * @author lastwhisper - */ -public class MLock implements Lock { - private volatile int i = 0; - - @Override - public void lock() { - } - - @Override - public void lockInterruptibly() throws InterruptedException { - - } - - @Override - public boolean tryLock() { - return false; - } - - @Override - public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { - return false; - } - - @Override - public void unlock() { - } - - @Override - public Condition newCondition() { - return null; - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s06/Main.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s06/Main.java deleted file mode 100644 index 93508846..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s06/Main.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.lastwhisper.concurrent.juc.aqs.s06; - -import java.util.concurrent.locks.Lock; - -/** - * @author lastwhisper - */ -public class Main { - private static int m = 0; - private static Lock lock = new MLock(); - - public static void main(String[] args) throws InterruptedException { - Thread[] threads = new Thread[100]; - for (int i = 0; i < threads.length; i++) { - threads[i] = new Thread(() -> { - try { - lock.lock(); - for (int j = 0; j < 100; j++) m++; - } finally { - lock.unlock(); - } - - }); - } - - for (Thread t : threads) t.start(); - for (Thread t : threads) t.join();//等待所有线程运行结束 - - System.out.println(m); - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s06/Sync.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s06/Sync.java deleted file mode 100644 index 526399c3..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s06/Sync.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.lastwhisper.concurrent.juc.aqs.s06; - -import java.util.concurrent.locks.AbstractQueuedSynchronizer; - -/** - * 错误 - * @author lastwhisper - */ -public class Sync extends AbstractQueuedSynchronizer { - - @Override - protected boolean tryAcquire(int arg) { - if (compareAndSetState(0, 1)) { - setExclusiveOwnerThread(Thread.currentThread());// 设置互斥锁 - return true; - } - return false; - } - - @Override - protected boolean tryRelease(int arg) { - setExclusiveOwnerThread(null); - setState(0); - return true; - } - - @Override - protected boolean isHeldExclusively() { - return getState()==1; - } - - -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s07/MLock.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s07/MLock.java deleted file mode 100644 index b39dbea1..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s07/MLock.java +++ /dev/null @@ -1,69 +0,0 @@ -package cn.lastwhisper.concurrent.juc.aqs.s07; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.AbstractQueuedSynchronizer; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; - -/** - * 错误 - * @author lastwhisper - */ -public class MLock implements Lock { - private volatile int i = 0; - - private class Sync extends AbstractQueuedSynchronizer { - @Override - protected boolean tryAcquire(int arg) { - if (compareAndSetState(0, 1)) { - setExclusiveOwnerThread(Thread.currentThread());// 设置互斥锁 - return true; - } - return false; - } - - @Override - protected boolean tryRelease(int arg) { - setExclusiveOwnerThread(null); - setState(0); - return true; - } - - @Override - protected boolean isHeldExclusively() { - return getState() == 1; - } - } - - - @Override - public void lock() { - - } - - @Override - public void lockInterruptibly() throws InterruptedException { - - } - - @Override - public boolean tryLock() { - return false; - } - - @Override - public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { - return false; - } - - @Override - public void unlock() { - - } - - @Override - public Condition newCondition() { - return null; - } - -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s07/Main.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s07/Main.java deleted file mode 100644 index 6ab8d435..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s07/Main.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.lastwhisper.concurrent.juc.aqs.s07; - -import java.util.concurrent.locks.Lock; - -/** - * @author lastwhisper - */ -public class Main { - private static int m = 0; - private static Lock lock = new MLock(); - - public static void main(String[] args) throws InterruptedException { - Thread[] threads = new Thread[100]; - for (int i = 0; i < threads.length; i++) { - threads[i] = new Thread(() -> { - try { - lock.lock(); - for (int j = 0; j < 100; j++) m++; - } finally { - lock.unlock(); - } - - }); - } - - for (Thread t : threads) t.start(); - for (Thread t : threads) t.join();//等待所有线程运行结束 - - System.out.println(m); - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s08/MLock.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s08/MLock.java deleted file mode 100644 index 7fe43fbc..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s08/MLock.java +++ /dev/null @@ -1,74 +0,0 @@ -package cn.lastwhisper.concurrent.juc.aqs.s08; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.AbstractQueuedSynchronizer; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; - -/** - * 正确 - * 独占锁 - * @author lastwhisper - */ -public class MLock implements Lock { - private Sync sync = new Sync(); - - private class Sync extends AbstractQueuedSynchronizer { - @Override - protected boolean tryAcquire(int arg) { - assert arg == 1; - if (compareAndSetState(0, 1)) { - setExclusiveOwnerThread(Thread.currentThread());// 设置互斥锁 - return true; - } - return false; - } - - @Override - protected boolean tryRelease(int arg) { - assert arg == 1; - if (!isHeldExclusively()) throw new IllegalMonitorStateException(); - setExclusiveOwnerThread(null); - setState(0); - return true; - } - - @Override - protected boolean isHeldExclusively() { - // 拿到当前排他线程是不是和当前线程一样,如果一样才释放 - return getExclusiveOwnerThread() == Thread.currentThread(); - - } - } - - @Override - public void lock() { - sync.acquire(1); - } - - @Override - public void lockInterruptibly() throws InterruptedException { - - } - - @Override - public boolean tryLock() { - return false; - } - - @Override - public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { - return false; - } - - @Override - public void unlock() { - sync.release(1); - } - - @Override - public Condition newCondition() { - return null; - } - -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s08/Main.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s08/Main.java deleted file mode 100644 index 7a7270ff..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/aqs/s08/Main.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.lastwhisper.concurrent.juc.aqs.s08; - -import java.util.concurrent.locks.Lock; - -/** - * @author lastwhisper - */ -public class Main { - private static int m = 0; - private static Lock lock = new MLock(); - - public static void main(String[] args) throws InterruptedException { - Thread[] threads = new Thread[100]; - for (int i = 0; i < threads.length; i++) { - threads[i] = new Thread(() -> { - try { - lock.lock(); - for (int j = 0; j < 100; j++) m++; - } finally { - lock.unlock(); - } - - }); - } - - for (Thread t : threads) t.start(); - for (Thread t : threads) t.join();//等待所有线程运行结束 - - System.out.println(m); - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/atomic/AtomicReferenceDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/atomic/AtomicReferenceDemo.java deleted file mode 100644 index be937d77..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/atomic/AtomicReferenceDemo.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.lastwhisper.concurrent.juc.atomic; - -import jdk.nashorn.internal.objects.annotations.Getter; -import jdk.nashorn.internal.objects.annotations.Setter; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.ToString; - -import java.util.concurrent.atomic.AtomicReference; -@Data -@AllArgsConstructor -@ToString -class User{ - private String name; - private int age; -} -public class AtomicReferenceDemo { - public static void main(String[] args) { - User zs = new User("zs", 22); - User ls = new User("ls", 22); - AtomicReference userAtomicReference = new AtomicReference<>(); - userAtomicReference.set(zs); - System.out.println(userAtomicReference.compareAndSet(zs, ls)+"\t"+userAtomicReference.get().toString()); - System.out.println(userAtomicReference.compareAndSet(zs, ls)+"\t"+userAtomicReference.get().toString()); - } -} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/atomic/CASDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/atomic/CASDemo.java deleted file mode 100644 index 0fbacf47..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/atomic/CASDemo.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.lastwhisper.concurrent.juc.atomic; - -import java.util.concurrent.atomic.AtomicInteger; - -public class CASDemo { - public static void main(String[] args) { - AtomicInteger atomicInteger = new AtomicInteger(5); - System.out.println(atomicInteger.compareAndSet(5, 2019) + "\t current" + atomicInteger.get()); - System.out.println(atomicInteger.compareAndSet(5, 2014) + "\t current" + atomicInteger.get()); - atomicInteger.getAndIncrement(); - } -} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/atomic/TestAtomic.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/atomic/TestAtomic.java deleted file mode 100644 index d377d57e..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/atomic/TestAtomic.java +++ /dev/null @@ -1,52 +0,0 @@ -package cn.lastwhisper.concurrent.juc.atomic; - -import java.util.concurrent.atomic.AtomicInteger; - -/** - * 一、i++的原子性问题:i++并非原子操作,取值,修改,存储 - * int temp = i;//第一步:取值 - * i = i + 1;//第二步:修改 - * i = temp;//第三步:存储 - * 内存到寄存器 - * 寄存器自增 - * 写回内存 - * 二、原子变量:jdk5后java.util.concurrent.atomic 包下提供了常用的原子变量 - * AtomicInteger - * 1.volatile 保证可见性 - * 2.CAS(Compare-And-Swap) 保证原子性 - * CAS 算法是硬件对于并发操作共享数据的支持 - * CAS 算法的过程:包含三个参数CAS(V,E,N), - * V 表示要更新的变量 - * E 表示预期值 - * N 表示新值 - * 仅当V==E时,才会将V=N,如果V!=E说明有其他线程做了更新,则当前线程什么也不做。 - * - * @author lastwhisper - */ -public class TestAtomic { - public static void main(String[] args) { - AtomicDemo ad = new AtomicDemo(); - for (int i = 0; i < 10; i++) { - new Thread(ad).start(); - } - } -} - -class AtomicDemo implements Runnable { - private int i; - //private volatile int i; - private AtomicInteger serialNum = new AtomicInteger(); - @Override - public void run() { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println(Thread.currentThread().getName() + " : " + increment()); - } - public int increment() { - //return serialNum.incrementAndGet(); - return i++; - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/atomic/TestCompareAndSwap.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/atomic/TestCompareAndSwap.java deleted file mode 100644 index 543358db..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/atomic/TestCompareAndSwap.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.lastwhisper.concurrent.juc.atomic; - -/** - * 模拟的CAS算法 - * @author lastwhisper - */ -public class TestCompareAndSwap { - public static void main(String[] args) { - final CompareAndSwap CAS = new CompareAndSwap(); - for (int i = 0; i < 10; i++) { - new Thread(new Runnable() { - @Override - public void run() { - int expectedValue = CAS.get(); - boolean flag = CAS.compareAndSet(expectedValue, (int) (Math.random() * 100)); - System.out.println(flag); - } - }).start(); - } - } -} - -class CompareAndSwap { - private int value; - - //获取当前内存的值 - public synchronized int get() { - return value; - } - - //比较当前内存的值与预期的值是否相同,相同则设置内存值为更新的值 - // 并返回当前内存值 - public synchronized int compareAndSwap(int expectedValue, int newValue) { - int oldValue = value; - if (oldValue == expectedValue) { - this.value = newValue; - } - return oldValue; - } - - //交换是否成功 - public synchronized boolean compareAndSet(int expectedValue, int newValue) { - return expectedValue == compareAndSwap(expectedValue, newValue); - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/blockingqueue/ArrayBlockingQueueDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/blockingqueue/ArrayBlockingQueueDemo.java new file mode 100644 index 00000000..ad5bfac6 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/blockingqueue/ArrayBlockingQueueDemo.java @@ -0,0 +1,81 @@ +package cn.lastwhisper.concurrent.juc.blockingqueue; + +import org.junit.Test; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.TimeUnit; + +/** + * 阻塞队列 + * + * @author lastwhisper + */ +public class ArrayBlockingQueueDemo { + ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3); + + // 超时退出 + @Test + public void test4() throws InterruptedException { + blockingQueue.offer("a"); + blockingQueue.offer("b"); + blockingQueue.offer("c"); + // 当阻塞队列满时,队列会阻塞生产者线程一定时间,超过后限时后生产者线程就会退出 + blockingQueue.offer("x", 2L, TimeUnit.SECONDS); + + System.out.println(blockingQueue.poll()); + System.out.println(blockingQueue.poll()); + System.out.println(blockingQueue.poll()); + System.out.println(blockingQueue.poll(2L, TimeUnit.SECONDS)); + } + + // 一直阻塞 + @Test + public void test3() throws InterruptedException { + blockingQueue.put("a"); + blockingQueue.put("b"); + blockingQueue.put("c"); + // 当阻塞队列满时,生产者继续往队列里面put元素,队列会一直阻塞直到put数据or响应中断退出 + blockingQueue.offer("x"); + + System.out.println(blockingQueue.take()); + System.out.println(blockingQueue.take()); + System.out.println(blockingQueue.take()); + //当阻塞队列空时,消费者试图从队列take元素,队列会一直阻塞消费者线程直到队列可用. + System.out.println(blockingQueue.take()); + } + + // 特殊值 + @Test + public void test2() { + System.out.println(blockingQueue.offer("a")); + System.out.println(blockingQueue.offer("b")); + System.out.println(blockingQueue.offer("c")); + // 插入方法,成功返回true 失败返回false + System.out.println(blockingQueue.offer("x")); + + System.out.println(blockingQueue.poll()); + System.out.println(blockingQueue.poll()); + System.out.println(blockingQueue.poll()); + //移除方法,成功返回元素,队列里面没有就返回null + System.out.println(blockingQueue.poll()); + } + + // 抛异常 + @Test + public void test1() { + System.out.println(blockingQueue.add("a")); + System.out.println(blockingQueue.add("b")); + System.out.println(blockingQueue.add("c")); + //当阻塞队列满时,再往队列里面add插入元素会抛IllegalStateException: Queue full + //System.out.println(blockingQueue.add("x")); + + System.out.println(blockingQueue.element()); + System.out.println(blockingQueue.remove()); + System.out.println(blockingQueue.remove()); + System.out.println(blockingQueue.remove()); + //当阻塞队列空时,再往队列Remove元素时候回抛出NoSuchElementException + //System.out.println(blockingQueue.remove()); + } + + +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/blockingqueue/DelayQueueDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/blockingqueue/DelayQueueDemo.java new file mode 100644 index 00000000..0c3a1b50 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/blockingqueue/DelayQueueDemo.java @@ -0,0 +1,64 @@ +package cn.lastwhisper.concurrent.juc.blockingqueue; + +import java.util.concurrent.DelayQueue; +import java.util.concurrent.Delayed; +import java.util.concurrent.TimeUnit; + +/** + * @author cunchang + * @date 2022/6/18 11:01 AM + */ +public class DelayQueueDemo { + + public static void main(String[] args) throws InterruptedException { + DelayQueue queue = new DelayQueue<>(); + queue.add(new MyDelay<>(8, "第一次添加任务")); + queue.add(new MyDelay<>(3, "第二次添加任务")); + queue.add(new MyDelay<>(5, "第三次添加任务")); + + while (!queue.isEmpty()) { + Delayed delayed = queue.take(); + System.out.println(delayed); + } + } + + static class MyDelay implements Delayed { + long delayTime; // 延迟时间 + long expire; // 过期时间 + T data; + + public MyDelay(long delayTime, T t) { + this.delayTime = delayTime; + // 过期时间 = 当前时间 + 延迟时间 + this.expire = System.currentTimeMillis() + delayTime; + data = t; + } + + /** + * 剩余时间 = 到期时间 - 当前时间 + */ + @Override + public long getDelay(TimeUnit unit) { + return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS); + } + + /** + * 优先级规则:两个任务比较,时间短的优先执行 + */ + @Override + public int compareTo(Delayed o) { + long f = this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS); + return (int) f; + } + + + @Override + public String toString() { + return "delayTime=" + delayTime + + ", expire=" + expire + + ", data=" + data; + } + } + +} + diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/blockingqueue/PriorityBlockingQueueDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/blockingqueue/PriorityBlockingQueueDemo.java new file mode 100644 index 00000000..a6b700e8 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/blockingqueue/PriorityBlockingQueueDemo.java @@ -0,0 +1,80 @@ +package cn.lastwhisper.concurrent.juc.blockingqueue; + +import java.util.concurrent.PriorityBlockingQueue; + +/** + * @author cunchang + * @date 2022/6/18 11:11 AM + */ +public class PriorityBlockingQueueDemo { + + public static void main(String[] args) throws InterruptedException { + PriorityBlockingQueue pbq = new PriorityBlockingQueue<>(); + pbq.add(new Person(3,"person3")); + System.err.println("容器为:" + pbq); + pbq.add(new Person(2,"person2")); + System.err.println("容器为:" + pbq); + pbq.add(new Person(1,"person1")); + System.err.println("容器为:" + pbq); + pbq.add(new Person(4,"person4")); + System.err.println("容器为:" + pbq); + System.err.println("分割线----------------------------------------------------------------" ); + + + System.err.println("获取元素 " + pbq.take()); + System.err.println("当前容器为:" + pbq); + System.err.println("分割线----------------------------------------------------------------" ); + + System.err.println("获取元素 " + pbq.take()); + System.err.println("当前容器为:" + pbq); + System.err.println("分割线----------------------------------------------------------------" ); + + System.err.println("获取元素 " + pbq.take()); + System.err.println("当前容器为:" + pbq); + System.err.println("分割线----------------------------------------------------------------" ); + + System.err.println("获取元素 " + pbq.take()); + System.err.println("当前容器为:" + pbq); + System.err.println("分割线----------------------------------------------------------------" ); + } + + static class Person implements Comparable { + private int id; + private String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Person(int id, String name) { + super(); + this.id = id; + this.name = name; + } + + public Person() { + } + + @Override + public String toString() { + return this.id + ":" + this.name; + } + + @Override + public int compareTo(Person person) { + return Integer.compare(this.id, person.getId()); + } + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/collections/SynchronousQueueDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/blockingqueue/SynchronousQueueDemo.java similarity index 97% rename from java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/collections/SynchronousQueueDemo.java rename to java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/blockingqueue/SynchronousQueueDemo.java index 2113eae8..248a241f 100644 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/collections/SynchronousQueueDemo.java +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/blockingqueue/SynchronousQueueDemo.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.concurrent.juc.collections; +package cn.lastwhisper.concurrent.juc.blockingqueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.SynchronousQueue; @@ -9,6 +9,7 @@ * @author lastwhisper */ public class SynchronousQueueDemo { + public static void main(String[] args) { BlockingQueue blockingQueue = new SynchronousQueue<>(); new Thread(() -> { diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/atomic/ABADemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/cas/ABADemo.java similarity index 98% rename from java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/atomic/ABADemo.java rename to java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/cas/ABADemo.java index 57220a5f..b4e1990a 100644 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/atomic/ABADemo.java +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/cas/ABADemo.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.concurrent.juc.atomic; +package cn.lastwhisper.concurrent.juc.cas; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/cas/AtomicIntegerTest.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/cas/AtomicIntegerTest.java new file mode 100644 index 00000000..d9c82c28 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/cas/AtomicIntegerTest.java @@ -0,0 +1,54 @@ +package cn.lastwhisper.concurrent.juc.cas; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * 一、i++的原子性问题:i++并非原子操作,取值,修改,存储 + * int temp = i;//第一步:取值 + * i = i + 1;//第二步:修改 + * i = temp;//第三步:存储 + * 内存到寄存器 + * 寄存器自增 + * 写回内存 + * 二、原子变量:jdk5后java.util.concurrent.atomic 包下提供了常用的原子变量 + * AtomicInteger + * 1.volatile 保证可见性 + * 2.CAS(Compare-And-Swap) 保证原子性 + * CAS 算法是硬件对于并发操作共享数据的支持 + * CAS 算法的过程:包含三个参数CAS(V,E,N), + * V 表示要更新的变量 + * E 表示预期值 + * N 表示新值 + * 仅当V==E时,才会将V=N,如果V!=E说明有其他线程做了更新,则当前线程什么也不做。 + * + * @author lastwhisper + */ +public class AtomicIntegerTest { + public static void main(String[] args) { + AtomicDemo ad = new AtomicDemo(); + for (int i = 0; i < 10; i++) { + new Thread(ad).start(); + } + } +} + +class AtomicDemo implements Runnable { + private int i; + //private volatile int i; + private AtomicInteger serialNum = new AtomicInteger(); + + @Override + public void run() { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println(Thread.currentThread().getName() + " : " + increment()); + } + + public int increment() { + //return serialNum.incrementAndGet(); + return i++; + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/cas/CASDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/cas/CASDemo.java new file mode 100644 index 00000000..8aaddd8e --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/cas/CASDemo.java @@ -0,0 +1,45 @@ +package cn.lastwhisper.concurrent.juc.cas; + +/** + * 模拟的CAS算法 + * @author lastwhisper + */ +public class CASDemo { + public static void main(String[] args) { + final CompareAndSwap CAS = new CompareAndSwap(); + for (int i = 0; i < 10; i++) { + new Thread(new Runnable() { + @Override + public void run() { + int expectedValue = CAS.get(); + boolean flag = CAS.compareAndSet(expectedValue, (int) (Math.random() * 100)); + System.out.println(flag); + } + }).start(); + } + } +} + +class CompareAndSwap { + private int value; + + //获取当前内存的值 + public synchronized int get() { + return value; + } + + //比较当前内存的值与预期的值是否相同,相同则设置内存值为更新的值 + // 并返回当前内存值 + public synchronized int compareAndSwap(int expectedValue, int newValue) { + int oldValue = value; + if (oldValue == expectedValue) { + this.value = newValue; + } + return oldValue; + } + + //交换是否成功 + public synchronized boolean compareAndSet(int expectedValue, int newValue) { + return expectedValue == compareAndSwap(expectedValue, newValue); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/collections/BlockingQueueDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/collections/BlockingQueueDemo.java deleted file mode 100644 index 7ad4bad0..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/collections/BlockingQueueDemo.java +++ /dev/null @@ -1,80 +0,0 @@ -package cn.lastwhisper.concurrent.juc.collections; - -import org.junit.Test; - -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.TimeUnit; - -/** - * 阻塞队列 - * @author lastwhisper - */ -public class BlockingQueueDemo { - ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3); - - // 超时退出 - @Test - public void test4() throws InterruptedException { - blockingQueue.offer("a"); - blockingQueue.offer("b"); - blockingQueue.offer("c"); - // 当阻塞队列满时,队列会阻塞生产者线程一定时间,超过后限时后生产者线程就会退出 - blockingQueue.offer("x",2L, TimeUnit.SECONDS); - - System.out.println(blockingQueue.poll()); - System.out.println(blockingQueue.poll()); - System.out.println(blockingQueue.poll()); - System.out.println(blockingQueue.poll(2L, TimeUnit.SECONDS)); - } - - // 一直阻塞 - @Test - public void test3() throws InterruptedException { - blockingQueue.put("a"); - blockingQueue.put("b"); - blockingQueue.put("c"); - // 当阻塞队列满时,生产者继续往队列里面put元素,队列会一直阻塞直到put数据or响应中断退出 - blockingQueue.offer("x"); - - System.out.println(blockingQueue.take()); - System.out.println(blockingQueue.take()); - System.out.println(blockingQueue.take()); - //当阻塞队列空时,消费者试图从队列take元素,队列会一直阻塞消费者线程直到队列可用. - System.out.println(blockingQueue.take()); - } - - // 特殊值 - @Test - public void test2(){ - System.out.println(blockingQueue.offer("a")); - System.out.println(blockingQueue.offer("b")); - System.out.println(blockingQueue.offer("c")); - // 插入方法,成功返回true 失败返回false - System.out.println(blockingQueue.offer("x")); - - System.out.println(blockingQueue.poll()); - System.out.println(blockingQueue.poll()); - System.out.println(blockingQueue.poll()); - //移除方法,成功返回元素,队列里面没有就返回null - System.out.println(blockingQueue.poll()); - } - - // 抛异常 - @Test - public void test1(){ - System.out.println(blockingQueue.add("a")); - System.out.println(blockingQueue.add("b")); - System.out.println(blockingQueue.add("c")); - //当阻塞队列满时,再往队列里面add插入元素会抛IllegalStateException: Queue full - //System.out.println(blockingQueue.add("x")); - - System.out.println(blockingQueue.element()); - System.out.println(blockingQueue.remove()); - System.out.println(blockingQueue.remove()); - System.out.println(blockingQueue.remove()); - //当阻塞队列空时,再往队列Remove元素时候回抛出NoSuchElementException - //System.out.println(blockingQueue.remove()); - } - - -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/collections/ContainerNotSafeDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/collections/ContainerNotSafeDemo.java deleted file mode 100644 index 3692c78f..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/collections/ContainerNotSafeDemo.java +++ /dev/null @@ -1,61 +0,0 @@ -package cn.lastwhisper.concurrent.juc.collections; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 集合类不安全的问题 - * @author lastwhisper - */ -public class ContainerNotSafeDemo { - /** - * 读写分离的思想,读和写不同的容器. - * CopyOnWriteArrayList在add时,会先上锁,然后copy一个新arr - * 将add的元素放入新arr里面,再将arr替换 - */ - public static void main(String[] args) { - //listNotSafe(); - //setNotSafe(); - mapNotSafe(); - - } - - private static void mapNotSafe() { - //Map map = new HashMap<>(); - Map map = new ConcurrentHashMap<>(); - for (int i = 1; i <= 30; i++) { - new Thread(() -> { - map.put(generatorStr(), generatorStr()); - System.out.println(map); - }, String.valueOf(i)).start(); - } - - } - - private static void setNotSafe() { - //Set set= new CopyOnWriteArraySet<>(); - Set set = new HashSet<>(); - for (int i = 1; i <= 30; i++) { - new Thread(() -> { - set.add(generatorStr()); - System.out.println(set); - }, String.valueOf(i)).start(); - } - } - - private static void listNotSafe() { - //List list= new CopyOnWriteArrayList<>(); - List list = new ArrayList<>(); - for (int i = 1; i <= 30; i++) { - new Thread(() -> { - list.add(generatorStr()); - System.out.println(list);//toString里面使用了迭代器 - }, String.valueOf(i)).start(); - } - } - - public static String generatorStr() { - return UUID.randomUUID().toString().substring(1, 8); - } - -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/collections/SkipListMapDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/collections/SkipListMapDemo.java deleted file mode 100644 index 450bd96a..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/collections/SkipListMapDemo.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.lastwhisper.concurrent.juc.collections; - -import java.util.Map; -import java.util.concurrent.ConcurrentSkipListMap; - -/** - * 跳表 - * @author lastwhisper - */ -public class SkipListMapDemo { - - public static void main(String[] args) { - ConcurrentSkipListMap skipListMap = new ConcurrentSkipListMap<>(); - for (int i = 0; i < 30; i++) { - skipListMap.put(i, i); - } - for (Map.Entry entry : skipListMap.entrySet()) { - System.out.println(entry.getKey()); - } - } - -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain1.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain1.java new file mode 100644 index 00000000..7539874b --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain1.java @@ -0,0 +1,38 @@ +package cn.lastwhisper.concurrent.juc.completefuture; + +import java.util.concurrent.CompletableFuture; + +/** + * 脱离线程池的使用,仅作为一个契约 + * + * @author Geym + * + */ +public class CFutureMain1 { + public static class AskThread implements Runnable { + CompletableFuture re = null; + + public AskThread(CompletableFuture re) { + this.re = re; + } + + @Override + public void run() { + int myRe = 0; + try { + myRe = re.get() * re.get(); + } catch (Exception e) { + } + System.out.println(myRe); + } + } + + public static void main(String[] args) throws InterruptedException { + final CompletableFuture future = new CompletableFuture<>(); + new Thread(new AskThread(future)).start(); + // 模拟长时间其他调用 + Thread.sleep(1000); + // 告知完成结果 + future.complete(60); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain2.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain2.java new file mode 100644 index 00000000..70d9c63e --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain2.java @@ -0,0 +1,32 @@ +package cn.lastwhisper.concurrent.juc.completefuture; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +/** + * 完成普通future的工作 + * + * 以下几个函数可以执行(创建)一个CompletableFuture任务 + * static CompletableFuture supplyAsync(Supplier supplier); + * static CompletableFuture supplyAsync(Supplier supplier, Executor executor); + * static CompletableFuture runAsync(Runnable runnable); + * static CompletableFuture runAsync(Runnable runnable, Executor executor); + * @author Geym + * + */ +public class CFutureMain2 { + public static Integer calc(Integer para) { + try { + // 模拟一个长时间的执行 + Thread.sleep(1000); + } catch (InterruptedException e) { + } + return para*para; + } + + public static void main(String[] args) throws InterruptedException, ExecutionException { + final CompletableFuture future = + CompletableFuture.supplyAsync(() -> calc(50)); + System.out.println(future.get()); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain3.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain3.java new file mode 100644 index 00000000..4d249326 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain3.java @@ -0,0 +1,32 @@ +package cn.lastwhisper.concurrent.juc.completefuture; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +/** + * 完成普通future的工作 + * + * 以下几个函数可以执行(创建)一个CompletableFuture任务 + * thenApply 转换 + * thenAccept 最后处理 + * @author Geym + * + */ +public class CFutureMain3 { + public static Integer calc(Integer para) { + try { + // 模拟一个长时间的执行 + Thread.sleep(1000); + } catch (InterruptedException e) { + } + return para*para; + } + + public static void main(String[] args) throws InterruptedException, ExecutionException { + CompletableFuture fu=CompletableFuture.supplyAsync(() -> calc(50)) + .thenApply((i)->Integer.toString(i)) + .thenApply((str)->"\""+str+"\"") + .thenAccept(System.out::println); + fu.get(); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain4.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain4.java new file mode 100644 index 00000000..b52726d9 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain4.java @@ -0,0 +1,33 @@ +package cn.lastwhisper.concurrent.juc.completefuture; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +/** + * 完成普通future的工作 + * + * exceptionally 异常处理 发生异常进行处理,如果没有异常,则它返回原有的结果 + * + * @author Geym + * + */ +public class CFutureMain4 { + + public static Integer calc(Integer para) { + return para / 0; + } + + public static void main(String[] args) throws InterruptedException,ExecutionException { + CompletableFuture fu = CompletableFuture + .supplyAsync(() -> calc(50)) + .exceptionally(ex -> { + System.out.println(ex.toString()); + return 0; + }) + .thenApply((i) -> Integer.toString(i)) + .thenApply((str) -> "\"" + str + "\"") + .thenAccept(System.out::println); + fu.get(); + } + +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain5.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain5.java new file mode 100644 index 00000000..d9d3c3fd --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain5.java @@ -0,0 +1,28 @@ +package cn.lastwhisper.concurrent.juc.completefuture; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +/** + * 完成普通future的工作 + * + * thenCompose + * + * @author Geym + * + */ +public class CFutureMain5 { + + public static Integer calc(Integer para) { + return para/2; + } + + public static void main(String[] args) throws InterruptedException, ExecutionException { + CompletableFuture fu = + CompletableFuture.supplyAsync(() -> calc(50)) + .thenCompose((i)->CompletableFuture.supplyAsync(() -> calc(i))) + .thenApply((str)->"\"" + str + "\"").thenAccept(System.out::println); + fu.get(); + } + +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain6.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain6.java new file mode 100644 index 00000000..3b1d1d85 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/CFutureMain6.java @@ -0,0 +1,30 @@ +package cn.lastwhisper.concurrent.juc.completefuture; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +/** + * 完成普通future的工作 + * + * thenCombine 合并结果 + * + * @author Geym + * + */ +public class CFutureMain6 { + + public static Integer calc(Integer para) { + return para / 2; + } + + public static void main(String[] args) throws InterruptedException,ExecutionException { + CompletableFuture intFuture = CompletableFuture.supplyAsync(() -> calc(50)); + CompletableFuture intFuture2 = CompletableFuture.supplyAsync(() -> calc(25)); + + CompletableFuture fu = intFuture.thenCombine(intFuture2, (i, j) -> (i + j)) + .thenApply((str) -> "\"" + str + "\"") + .thenAccept(System.out::println); + fu.get(); + } + +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/README.md b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/README.md new file mode 100644 index 00000000..78f37c12 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/completefuture/README.md @@ -0,0 +1,6 @@ + +脱离线程池使用 +CFutureMain1 手动设置future完成状态 + + + diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/ForkJoinPoolTest.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/ForkJoinPoolTest.java new file mode 100644 index 00000000..a2293006 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/ForkJoinPoolTest.java @@ -0,0 +1,69 @@ +package cn.lastwhisper.concurrent.juc.executor; + +import org.junit.Test; + +import java.time.Duration; +import java.time.Instant; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.RecursiveTask; + +/** + * fork/join任务偷窃 + * + * @author lastwhisper + */ +public class ForkJoinPoolTest { + public static void main(String[] args) { + Instant start = Instant.now(); + ForkJoinPool pool = new ForkJoinPool(); + ForkJoinTask task = new ForkJoinSumCalculate(0L, 100000000L); + Long sum = pool.invoke(task); + System.out.println("结果:" + sum); + Instant end = Instant.now(); + System.out.println("耗费时间:" + Duration.between(start, end).toMillis());//28 + } + + @Test + public void test1() { + Instant start = Instant.now(); + long sum = 0L; + for (long i = 0L; i <= 100000000L; i++) { + sum += i; + } + System.out.println(sum); + Instant end = Instant.now(); + System.out.println("耗费时间为:" + Duration.between(start, end).toMillis());//51 + } +} + +class ForkJoinSumCalculate extends RecursiveTask { + private static final long THUSHOLD = 10000000L;//临界值 + private long start; + private long end; + + public ForkJoinSumCalculate(long start, long end) { + this.start = start; + this.end = end; + } + + @Override + protected Long compute() { + long length = end - start; + if (length <= THUSHOLD) { + long sum = 0L; + for (long i = start; i <= end; i++) { + sum += i; + } + return sum; + } else { + long middle = ((end - start) >> 1) + start; + ForkJoinSumCalculate left = new ForkJoinSumCalculate(start, middle); + left.fork();//进行拆分,同时压入线程队列 + ForkJoinSumCalculate right = new ForkJoinSumCalculate(middle + 1, end); + right.fork(); + + return left.join() + right.join(); + } + } +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/MyThreadPoolDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/MyThreadPoolDemo.java deleted file mode 100644 index 4cdf9f3c..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/MyThreadPoolDemo.java +++ /dev/null @@ -1,70 +0,0 @@ -package cn.lastwhisper.concurrent.juc.executor; - -import java.util.concurrent.*; - -public class MyThreadPoolDemo { - public static void main(String[] args) { - ExecutorService threadPool = new ThreadPoolExecutor( - 2, - 5, - 1L, - TimeUnit.SECONDS, - new LinkedBlockingDeque(3), - Executors.defaultThreadFactory(), - //threadNum>maximumPoolSize+capacity+1会异常 - //new ThreadPoolExecutor.AbortPolicy() - //threadNum>maximumPoolSize+capacity+1将任务回退到调用者 - //new ThreadPoolExecutor.CallerRunsPolicy() - //抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交 - //new ThreadPoolExecutor.DiscardOldestPolicy() - //直接丢弃任务,不予任何处理也不抛出异常 - new ThreadPoolExecutor.DiscardPolicy() - ); - //模拟10个用户来办理业务 没有用户就是来自外部的请求线程. - try { - for (int i = 1; i <= 10; i++) { - threadPool.execute(() -> { - System.out.println(Thread.currentThread().getName() + "\t 办理业务"); - }); - } - } catch (Exception e) { - e.printStackTrace(); - } finally { - threadPool.shutdown(); - } - //threadPoolInit(); - } - - private static void threadPoolInit() { - /* - * 一池5个处理线程 - */ - //ExecutorService threadPool= Executors.newFixedThreadPool(5); - /* - * 一池一线程 - */ - //ExecutorService threadPool= Executors.newSingleThreadExecutor(); - /* - * 一池N线程 - */ - ExecutorService threadPool = Executors.newCachedThreadPool(); - //模拟10个用户来办理业务 没有用户就是来自外部的请求线程. - try { - for (int i = 1; i <= 20; i++) { - threadPool.execute(() -> { - System.out.println(Thread.currentThread().getName() + "\t 办理业务"); - }); - try { - TimeUnit.MICROSECONDS.sleep(200); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } catch (Exception e) { - e.printStackTrace(); - } finally { - threadPool.shutdown(); - } - } -} - diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/README.md b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/README.md new file mode 100644 index 00000000..7bbb5e10 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/README.md @@ -0,0 +1,8 @@ + +1. RejectedExecutionHandlerTest;线程池拒绝策略 +2. ScheduledExecutorTest;调度线程池 +3. ThreadPoolIdTest;验证线程池的线程复用 +4. ThreadPoolExceptionTest;线程池execute执行异常,线程会不断创建 + + + diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/RejectedExecutionHandlerTest.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/RejectedExecutionHandlerTest.java new file mode 100644 index 00000000..351c7935 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/RejectedExecutionHandlerTest.java @@ -0,0 +1,45 @@ +package cn.lastwhisper.concurrent.juc.executor; + +import java.util.concurrent.*; + +public class RejectedExecutionHandlerTest { + public static void main(String[] args) { + ExecutorService threadPool = new ThreadPoolExecutor( + 2, + 5, + 1L, + TimeUnit.SECONDS, + new LinkedBlockingDeque(3), + Executors.defaultThreadFactory(), + //1、AbortPolicy()策略,当前threadNum>maximumPoolSize+capacity+1会异常 + //new ThreadPoolExecutor.AbortPolicy() + //2、CallerRunsPolicy()策略,threadNum>maximumPoolSize+capacity+1任务将由调用者自己执行 + //new ThreadPoolExecutor.CallerRunsPolicy() + //3、DiscardOldestPolicy()策略,抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交 + //new ThreadPoolExecutor.DiscardOldestPolicy() + //4、DiscardPolicy()策略直接丢弃任务,不予任何处理也不抛出异常 +// new ThreadPoolExecutor.DiscardPolicy() + // 5、自定义策略 + new RejectedExecutionHandler() { + @Override + public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { + System.out.println(r.toString() + " is discard"); + } + } + ); + //模拟10个用户来办理业务 每个用户就是来自外部的请求线程. + try { + for (int i = 1; i <= 10; i++) { + threadPool.execute(() -> { + System.out.println(Thread.currentThread().getName() + "\t 办理业务"); + }); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + threadPool.shutdown(); + } + } + +} + diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/ScheduledExecutorTest.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/ScheduledExecutorTest.java new file mode 100644 index 00000000..01a9d587 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/ScheduledExecutorTest.java @@ -0,0 +1,153 @@ +package cn.lastwhisper.concurrent.juc.executor; + +import java.util.Random; +import java.util.concurrent.*; + +/** + * 一、线程池体系 + * java.util.concurrent.Executor接口: 负责线程的使用与调度的根接口 + * |--**.ExecutorService子接口: 线程池的主要接口 + * |--**AbstractExecutorService抽象类 + * |--**ThreadPoolExecutor线程池的实现类 + * |--**ForkJoinPool Fork/Join任务窃取实现类 + * |--**ScheduledExecutorService子接口: 负责线程的调度 + * |--**ScheduledThreadPoolExecutor 继承 ThreadPoolExecutor,实现 ScheduledExecutorService + * 二、线程池创建工具类 + * java.util.concurrent.Executors主要用于创建线程池 + * ExecutorService newFixedThreadPool() : 创建固定大小的线程池 + * ExecutorService newCachedThreadPool() : 缓存线程池,线程池的数量不固定,可以根据需求自动的更改数量。 + * ExecutorService newSingleThreadExecutor() : 创建单个线程池。线程池中只有一个线程 + * ScheduledExecutorService newScheduledThreadPool() : 创建固定大小的线程,可以延迟或定时的执行任务。 + * 三、线程池原理 + * java.util.concurrent.ThreadPoolExecutor + * 1.构造函数:ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, + * BlockingQueue workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) + * 参数: + * corePoolSize:指定线程池中的线程数量 + * maximumPoolSize:指定了线程池中的最大线程数量 + * keepAliveTime:超过corePoolSize的空闲线程,在多长时间内会被销毁 + * unit:keepAliveTime的单位 + * workQueue:任务队列,被提交但尚未执行的任务 + * SynchronousQueue:直接提交的队列 + * ArrayBlockingQueue:有界的任务队列 + * LinkedBlockingQueue:无界的任务队列 + * PriorityBlockingQueue:优先任务队列 + * threadFactory:线程工厂,用于创建线程,一般用默认即可 + * handler:拒绝策略。任务太多来不及处理,如何拒绝任务 + * AbortPolicy:直接抛出异常,阻止系统正常工作 + * CallerRunsPolicy:只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的任务 + * DiscardOldestPolicy:丢弃最老的一个请求 + * DiscardPolicy:丢弃无法处理的任务 + * @author lastwhisper + */ +public class ScheduledExecutorTest { + // 计划任务线程池 + static ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); + // 普通的线程池 + static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5); + + public static class MyTask implements Runnable { + @Override + public void run() { + System.out.println(System.currentTimeMillis() + ":Thread ID:" + Thread.currentThread().getId()); + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public static void main(String[] args) throws Exception { + ScheduledExecutorTest test = new ScheduledExecutorTest(); + //测试普通的线程池 +// test.testFixedThreadPool(); + //测试计划任务线程池 + //test.testSchedule(); + //test.testScheduleAtFixedRate(); + test.testScheduleWithFixedDelay(); + } + + private void testFixedThreadPool() throws Exception { + for (int i = 0; i < 10; i++) { + Future future = fixedThreadPool.submit(new MyTask(), new Integer(0)); + System.out.println(future.get()); + } + fixedThreadPool.shutdown(); + } + + /** + * 1.scheduleWithFixedDelay + * + * 2.构造器: + * scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit); + * command任务体; + * initialDelay初始延时时间; + * period:等待时间; + * unit:时间单位; + * 3.testScheduleWithFixedDelay不会等待执行体内的执行时间 + */ + private void testScheduleWithFixedDelay() throws Exception { + ((ScheduledThreadPoolExecutor)scheduledThreadPool).scheduleWithFixedDelay(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(8000); + System.out.println(System.currentTimeMillis() / 1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }, 0, 2, TimeUnit.SECONDS); + } + + /** + * 1.scheduleAtFixedRate + * 创建一个周期性任务,任务开始于给定的初始化延时。 + * 后续第一个任务会在initialDelay+1*period时执行,第二个任务会在initialDelay+2*period时执行,以此类推。 + * 2.构造器: + * scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit); + * command任务体; + * initialDelay初始延时时间; + * period:等待时间; + * unit:时间单位; + * 3.scheduleAtFixedRate会等待执行体内的执行时间 + */ + private void testScheduleAtFixedRate() throws Exception { + scheduledThreadPool.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(8000); + System.out.println(System.currentTimeMillis() / 1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }, 0, 2, TimeUnit.SECONDS); + } + + /** + * 1.schedule:给定时间,对任务进行一次调度 + * 2.构造器: + * schedule(Callable callable,long delay, TimeUnit unit) + * schedule(Runnable command,long delay, TimeUnit unit) + * 参数意义: + * callable、command任务体; + * delay延时时间; + * unit:时间单位 + */ + private void testSchedule() throws ExecutionException, InterruptedException { + // 给定时间,对任务进行一次调度 + Future result = scheduledThreadPool.schedule(new Callable() { + @Override + public Integer call() throws Exception { + int num = new Random().nextInt(100);//生成随机数 + System.out.println(Thread.currentThread().getName() + " : " + num); + return num; + } + }, 1, TimeUnit.SECONDS); + System.out.println("返回的计算结果:" + result.get()); + scheduledThreadPool.shutdown(); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/TestForkJoinPool.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/TestForkJoinPool.java deleted file mode 100644 index 497b04b9..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/TestForkJoinPool.java +++ /dev/null @@ -1,67 +0,0 @@ -package cn.lastwhisper.concurrent.juc.executor; - -import org.junit.Test; - -import java.time.Duration; -import java.time.Instant; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.ForkJoinTask; -import java.util.concurrent.RecursiveTask; - -/** - * fork/join任务偷窃 - * @author lastwhisper - */ -public class TestForkJoinPool { - public static void main(String[] args) { - Instant start = Instant.now(); - ForkJoinPool pool = new ForkJoinPool(); - ForkJoinTask task = new ForkJoinSumCalculate(0L, 100000000L); - Long sum = pool.invoke(task); - System.out.println("结果:" + sum); - Instant end = Instant.now(); - System.out.println("耗费时间:" + Duration.between(start, end).toMillis());//28 - } - @Test - public void test1(){ - Instant start = Instant.now(); - long sum = 0L; - for (long i = 0L; i <= 100000000L; i++) { - sum += i; - } - System.out.println(sum); - Instant end = Instant.now(); - System.out.println("耗费时间为:" + Duration.between(start, end).toMillis());//51 - } -} - -class ForkJoinSumCalculate extends RecursiveTask { - private static final long THUSHOLD = 10000000L;//临界值 - private long start; - private long end; - - public ForkJoinSumCalculate(long start, long end) { - this.start = start; - this.end = end; - } - - @Override - protected Long compute() { - long length = end - start; - if (length <= THUSHOLD) { - long sum = 0L; - for (long i = start; i <= end; i++) { - sum += i; - } - return sum; - } else { - long middle = ((end - start) >> 1) + start; - ForkJoinSumCalculate left = new ForkJoinSumCalculate(start, middle); - left.fork();//进行拆分,同时压入线程队列 - ForkJoinSumCalculate right = new ForkJoinSumCalculate(middle + 1, end); - right.fork(); - - return left.join() + right.join(); - } - } -} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/TestRejectedExecutionHandler.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/TestRejectedExecutionHandler.java deleted file mode 100644 index e5deac61..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/TestRejectedExecutionHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.lastwhisper.concurrent.juc.executor; - -import java.util.concurrent.*; - -/** - * 自定义线程池的拒绝策略 - * @author lastwhisper - */ -public class TestRejectedExecutionHandler { - public static class MyTask implements Runnable{ - @Override - public void run() { - System.out.println(System.currentTimeMillis()+":Thread ID:"+Thread.currentThread().getId()); - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - public static void main(String[] args) throws InterruptedException { - MyTask myTask = new MyTask(); - ExecutorService pool = new ThreadPoolExecutor(5, 5, 0, - TimeUnit.MILLISECONDS, new LinkedBlockingQueue(10), Executors.defaultThreadFactory(), new RejectedExecutionHandler() { - @Override - public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { - System.out.println(r.toString()+" is discard"); - } - }); - for (int i = 0; i < Integer.MAX_VALUE; i++) { - pool.submit(myTask); - Thread.sleep(10); - } - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/TestThreadPool.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/TestThreadPool.java deleted file mode 100644 index 19e14e4c..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/TestThreadPool.java +++ /dev/null @@ -1,153 +0,0 @@ -package cn.lastwhisper.concurrent.juc.executor; - -import java.util.Random; -import java.util.concurrent.*; - -/** - * 一、线程池体系 - * java.util.concurrent.Executor接口: 负责线程的使用与调度的根接口 - * |--**.ExecutorService子接口: 线程池的主要接口 - * |--**AbstractExecutorService抽象类 - * |--**ThreadPoolExecutor线程池的实现类 - * |--**ForkJoinPool Fork/Join任务窃取实现类 - * |--**ScheduledExecutorService子接口: 负责线程的调度 - * |--**ScheduledThreadPoolExecutor 继承 ThreadPoolExecutor,实现 ScheduledExecutorService - * 二、线程池创建工具类 - * java.util.concurrent.Executors主要用于创建线程池 - * ExecutorService newFixedThreadPool() : 创建固定大小的线程池 - * ExecutorService newCachedThreadPool() : 缓存线程池,线程池的数量不固定,可以根据需求自动的更改数量。 - * ExecutorService newSingleThreadExecutor() : 创建单个线程池。线程池中只有一个线程 - * ScheduledExecutorService newScheduledThreadPool() : 创建固定大小的线程,可以延迟或定时的执行任务。 - * 三、线程池原理 - * java.util.concurrent.ThreadPoolExecutor - * 1.构造函数:ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, - * BlockingQueue workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) - * 参数: - * corePoolSize:指定线程池中的线程数量 - * maximumPoolSize:指定了线程池中的最大线程数量 - * keepAliveTime:超过corePoolSize的空闲线程,在多长时间内会被销毁 - * unit:keepAliveTime的单位 - * workQueue:任务队列,被提交但尚未执行的任务 - * SynchronousQueue:直接提交的队列 - * ArrayBlockingQueue:有界的任务队列 - * LinkedBlockingQueue:无界的任务队列 - * PriorityBlockingQueue:优先任务队列 - * threadFactory:线程工厂,用于创建线程,一般用默认即可 - * handler:拒绝策略。任务太多来不及处理,如何拒绝任务 - * AbortPolicy:直接抛出异常,阻止系统正常工作 - * CallerRunsPolicy:只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的任务 - * DiscardOldestPolicy:丢弃最老的一个请求 - * DiscardPolicy:丢弃无法处理的任务 - * @author lastwhisper - */ -public class TestThreadPool { - // 计划任务线程池 - static ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); - // 普通的线程池 - static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5); - - public static class MyTask implements Runnable { - @Override - public void run() { - System.out.println(System.currentTimeMillis() + ":Thread ID:" + Thread.currentThread().getId()); - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - public static void main(String[] args) throws Exception { - TestThreadPool test = new TestThreadPool(); - //测试普通的线程池 - test.testFixedThreadPool(); - //测试计划任务线程池 - //test.testSchedule(); - //test.testScheduleAtFixedRate(); - //test.testScheduleWithFixedDelay(); - } - - private void testFixedThreadPool() throws Exception { - for (int i = 0; i < 10; i++) { - Future future = fixedThreadPool.submit(new MyTask(), new Integer(0)); - System.out.println(future.get()); - } - fixedThreadPool.shutdown(); - } - - /** - * 1.scheduleWithFixedDelay - * - * 2.构造器: - * scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit); - * command任务体; - * initialDelay初始延时时间; - * period:等待时间; - * unit:时间单位; - * 3.testScheduleWithFixedDelay不会等待执行体内的执行时间 - */ - private void testScheduleWithFixedDelay() throws Exception { - scheduledThreadPool.scheduleWithFixedDelay(new Runnable() { - @Override - public void run() { - try { - Thread.sleep(8000); - System.out.println(System.currentTimeMillis() / 1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }, 0, 2, TimeUnit.SECONDS); - } - - /** - * 1.scheduleAtFixedRate - * 创建一个周期性任务,任务开始于给定的初始化延时。 - * 后续第一个任务会在initialDelay+1*period时执行,第二个任务会在initialDelay+2*period时执行,以此类推。 - * 2.构造器: - * scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit); - * command任务体; - * initialDelay初始延时时间; - * period:等待时间; - * unit:时间单位; - * 3.scheduleAtFixedRate会等待执行体内的执行时间 - */ - private void testScheduleAtFixedRate() throws Exception { - scheduledThreadPool.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - try { - Thread.sleep(8000); - System.out.println(System.currentTimeMillis() / 1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }, 0, 2, TimeUnit.SECONDS); - } - - /** - * 1.schedule:给定时间,对任务进行一次调度 - * 2.构造器: - * schedule(Callable callable,long delay, TimeUnit unit) - * schedule(Runnable command,long delay, TimeUnit unit) - * 参数意义: - * callable、command任务体; - * delay延时时间; - * unit:时间单位 - */ - private void testSchedule() throws ExecutionException, InterruptedException { - // 给定时间,对任务进行一次调度 - Future result = scheduledThreadPool.schedule(new Callable() { - @Override - public Integer call() throws Exception { - int num = new Random().nextInt(100);//生成随机数 - System.out.println(Thread.currentThread().getName() + " : " + num); - return num; - } - }, 1, TimeUnit.SECONDS); - System.out.println("返回的计算结果:" + result.get()); - scheduledThreadPool.shutdown(); - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/ThreadPoolExceptionTest.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/ThreadPoolExceptionTest.java new file mode 100644 index 00000000..039a9310 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/ThreadPoolExceptionTest.java @@ -0,0 +1,60 @@ +package cn.lastwhisper.concurrent.juc.executor; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +/** + * 测试线程池出现异常时的线程id + * @author lastwhisper + * @date 2022/5/2 + */ +public class ThreadPoolExceptionTest { + + public static void main(String[] args) { + // 线程池会复用线程,线程id会重复出现; + // 但是线程池执行任务出现异常,会把异常线程移除,创建新的线程 + ExecutorService pool = Executors.newFixedThreadPool(1); + for (int i = 0; i < 100; i++) { + int finalI = i; + pool.execute(() -> { + if(finalI % 2==0){ + try { + int x = finalI/0; + } catch (Exception e) { + System.err.println("异常线程id:"+Thread.currentThread().getId()+" e:"+e); + throw e; + } + } + System.err.println("无异常线程id:"+Thread.currentThread().getId()); + }); + } + pool.shutdown(); + + +// ExecutorService pool = Executors.newFixedThreadPool(1); +// for (int i = 0; i < 50; i++) { +// int finalI = i; +// Future future = pool.submit(() -> { +// if (finalI % 2 == 0) { +// try { +// int x = finalI / 0; +// } catch (Exception e) { +// System.err.println("异常线程id:" + Thread.currentThread().getId() + " e:" + e); +// throw e; +// } +// } +// System.err.println("无异常线程id:" + Thread.currentThread().getId()); +// }); +// try { +// System.out.println(future.get()); +// } catch (InterruptedException | ExecutionException e) { +// e.printStackTrace(); +// } +// } +// pool.shutdown(); + + } + +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/ThreadPoolIdTest.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/ThreadPoolIdTest.java similarity index 82% rename from java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/ThreadPoolIdTest.java rename to java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/ThreadPoolIdTest.java index 47772b0b..fc11019f 100644 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/basic/ThreadPoolIdTest.java +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/ThreadPoolIdTest.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.concurrent.basic; +package cn.lastwhisper.concurrent.juc.executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -14,7 +14,8 @@ public static void main(String[] args) { // 线程池会复用线程,线程id会重复出现 ExecutorService pool = Executors.newFixedThreadPool(10); for (int i = 0; i < 100; i++) { - pool.submit(() -> { + pool.execute(() -> { +// pool.submit(() -> { System.err.println(Thread.currentThread().getId()); }); } diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/trace/CatchException.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/trace/CatchException.java new file mode 100644 index 00000000..38971f00 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/trace/CatchException.java @@ -0,0 +1,38 @@ +package cn.lastwhisper.concurrent.juc.executor.trace; + +import java.util.concurrent.*; + +/** + * submit吃掉异常 + * 1. 用Future.get()获得异常 + * 2. try-catch + * @author Geym + * + */ +public class CatchException { + public static void main(String[] args) throws InterruptedException, ExecutionException { + ThreadPoolExecutor pools=new ThreadPoolExecutor(0, Integer.MAX_VALUE, + 0L, TimeUnit.SECONDS, + new SynchronousQueue()); + + // 1、不打印异常;submit + for(int i=0;i<5;i++){ + pools.submit(new DivTask(100,i)); + } + System.out.println("======================================================"); + // 2、打印异常;execute + for (int i = 0; i < 5; i++) { + pools.execute(new DivTask(100, i)); + } + System.out.println("======================================================"); + // 3、打印异常;Future.get() + for (int i = 0; i < 5; i++) { + Future re = pools.submit(new DivTask(100, i)); + try { + re.get(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/trace/DivTask.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/trace/DivTask.java new file mode 100644 index 00000000..c9a63a76 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/trace/DivTask.java @@ -0,0 +1,14 @@ +package cn.lastwhisper.concurrent.juc.executor.trace; + +public class DivTask implements Runnable { + int a,b; + public DivTask(int a,int b){ + this.a=a; + this.b=b; + } + @Override + public void run() { + double re=a/b; + System.out.println(re); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/trace/README.md b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/trace/README.md new file mode 100644 index 00000000..42f521c9 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/trace/README.md @@ -0,0 +1,3 @@ +CatchException;线程池如何处理异常 +TraceMain;包装线程池异常 + diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/trace/TraceMain.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/trace/TraceMain.java new file mode 100644 index 00000000..36828112 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/trace/TraceMain.java @@ -0,0 +1,19 @@ +package cn.lastwhisper.concurrent.juc.executor.trace; + +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + + +public class TraceMain { + + public static void main(String[] args) { + ThreadPoolExecutor pools=new TraceThreadPoolExecutor(0, Integer.MAX_VALUE, + 0L, TimeUnit.SECONDS, + new SynchronousQueue()); + for(int i=0;i<5;i++){ + pools.execute(new DivTask(100,i)); + } + } + +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/trace/TraceThreadPoolExecutor.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/trace/TraceThreadPoolExecutor.java new file mode 100644 index 00000000..22c8e26e --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/executor/trace/TraceThreadPoolExecutor.java @@ -0,0 +1,44 @@ +package cn.lastwhisper.concurrent.juc.executor.trace; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class TraceThreadPoolExecutor extends ThreadPoolExecutor { + public TraceThreadPoolExecutor(int corePoolSize, int maximumPoolSize, + long keepAliveTime, TimeUnit unit, BlockingQueue workQueue) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); + } + + @Override + public void execute(Runnable task) { + super.execute(wrap(task, clientTrace(), Thread.currentThread() + .getName())); + } + + @Override + public Future submit(Runnable task) { + return super.submit(wrap(task, clientTrace(), Thread.currentThread() + .getName())); + } + + private Exception clientTrace() { + return new Exception("Client stack trace"); + } + + private Runnable wrap(final Runnable task, final Exception clientStack, + String clientThreadName) { + return new Runnable() { + @Override + public void run() { + try { + task.run(); + } catch (Exception e) { + clientStack.printStackTrace(); + throw e; + } + } + }; + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/future/FutureTest.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/future/FutureTest.java new file mode 100644 index 00000000..47f5438b --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/future/FutureTest.java @@ -0,0 +1,30 @@ +package cn.lastwhisper.concurrent.juc.future; + +import java.util.concurrent.*; + +/** + * @author cunchang + * @date 2022/4/22 5:18 PM + */ +public class FutureTest { + public static void main(String[] args) throws InterruptedException, ExecutionException { + FutureTask futureTask = new FutureTask<>(new Task()," circuit breaker defalut result"); + ExecutorService threadPool = Executors.newFixedThreadPool(1); + threadPool.submit(futureTask); + + System.out.println("异步提交任务"); + // 同步执行其他业务 + Thread.sleep(200); + System.out.println("同步执行其他业务,200ms"); + + // call方法未执行完,这里会阻塞 + try { + System.out.println("接口1000ms拿不到结果就熔断:"+futureTask.get(1, TimeUnit.SECONDS)); + } catch (TimeoutException e) { + threadPool.shutdown(); + System.err.println(e); + } + + threadPool.shutdown(); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/future/Task.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/future/Task.java new file mode 100644 index 00000000..29c8991d --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/future/Task.java @@ -0,0 +1,20 @@ +package cn.lastwhisper.concurrent.juc.future; + +/** + * @author cunchang + * @date 2022/4/22 5:15 PM + */ +public class Task implements Runnable { + + @Override + public void run() { + for (int i = 0; i < 12; i++) { + try { + Thread.sleep(100); + System.out.println("有12个任务,当前任务" + i + "执行中,已耗时" + i + "00ms,"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/ReentrantLockDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/ReentrantLockDemo.java new file mode 100644 index 00000000..b35a910d --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/ReentrantLockDemo.java @@ -0,0 +1,32 @@ +package cn.lastwhisper.concurrent.juc.lock; + +import java.util.concurrent.locks.ReentrantLock; + +/** + * 重入锁的公平性 + * @author lastwhisper + */ +public class ReentrantLockDemo implements Runnable { + //是否公平,公平时交替打印 + private final ReentrantLock lock = new ReentrantLock(true); + + @Override + public void run() { + for(;;){ + try { + lock.lock(); + System.out.println(Thread.currentThread().getName()); + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + }finally { + lock.unlock(); + } + } + } + public static void main(String[] args){ + ReentrantLockDemo lockDemo = new ReentrantLockDemo(); + new Thread(lockDemo,"A").start(); + new Thread(lockDemo,"B").start(); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/ReentrantLockInterruptedDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/ReentrantLockInterruptedDemo.java new file mode 100644 index 00000000..9749d5bf --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/ReentrantLockInterruptedDemo.java @@ -0,0 +1,46 @@ +package cn.lastwhisper.concurrent.juc.lock; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; + +/** + * @author lastwhisper + */ +public class ReentrantLockInterruptedDemo { + + public static void main(String[] args) throws InterruptedException { + + ReentrantLock lock = new ReentrantLock(); + Thread t1 = new Thread(() -> { + try { + lock.lock(); + System.out.println("t1 come in"); + try { + TimeUnit.MINUTES.sleep(20); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } finally { + lock.unlock(); + } + }, "A"); + t1.start(); + + Thread t2 = new Thread(() -> { + try { + lock.lockInterruptibly(); + System.out.println("t2 come in"); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + System.out.println("t2线程被人中断"); + } finally { + lock.unlock(); + } + }, "B"); + t2.start(); + + Thread.sleep(1000); + t2.interrupt(); + Thread.sleep(1000); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/SpinLockDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/SpinLockDemo.java similarity index 97% rename from java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/SpinLockDemo.java rename to java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/SpinLockDemo.java index dfc2e1fb..a269a7bf 100644 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/SpinLockDemo.java +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/SpinLockDemo.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.concurrent.juc.locks; +package cn.lastwhisper.concurrent.juc.lock; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/TestLock.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/TestLock.java similarity index 96% rename from java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/TestLock.java rename to java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/TestLock.java index c4a93845..946048a4 100644 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/TestLock.java +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/TestLock.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.concurrent.juc.locks; +package cn.lastwhisper.concurrent.juc.lock; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/TestManyReadOneWriteCollection.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/TestManyReadOneWriteCollection.java new file mode 100644 index 00000000..0c9e927c --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/TestManyReadOneWriteCollection.java @@ -0,0 +1,111 @@ +package cn.lastwhisper.concurrent.juc.lock; + +import java.util.ArrayList; +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * 多读一写集合是否线程安全 + * @author lastwhisper + */ +public class TestManyReadOneWriteCollection { + // 读写锁 + private static ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + private static Lock readLock = readWriteLock.readLock(); + private static Lock writeLock = readWriteLock.writeLock(); + // 闭锁 + private static CountDownLatch latch = new CountDownLatch(21); + + private static ExecutorService threadPool = Executors.newCachedThreadPool(); + + // 共享数据 + private ArrayList collection = new ArrayList<>(); + + { + for (int i = 0; i < 20; i++) { + collection.add(i); + } + } + + public static void main(String[] args) throws InterruptedException { + + TestManyReadOneWriteCollection rwl = new TestManyReadOneWriteCollection(); + // 读线程执行的主体 + Runnable readThread = () -> { + //System.out.println(rwl.handleReadLock(readLock));; + System.out.println(rwl.handleRead()); + latch.countDown(); + }; + // 写线程执行的主体 + Runnable writeThread = () -> { + //rwl.handleWriteLock(writeLock, new Random().nextInt(10000)); + rwl.handleWrite(new Random().nextInt(10000)); + latch.countDown(); + }; + + // 多读一写 + for (int i = 0; i < 10; i++) { + threadPool.execute(readThread); + } + for (int i = 0; i < 1; i++) { + threadPool.execute(writeThread); + } + for (int i = 0; i < 10; i++) { + threadPool.execute(readThread); + } + latch.await(); + threadPool.shutdown(); + } + + // 读取文件 + public String handleRead() { + StringBuilder result= new StringBuilder(); + //Thread.sleep(9); + for (Integer num : collection) { + result.append(num); + } + return result.toString(); + } + + // 写入文件 + public void handleWrite(int writeVal) { + //Thread.sleep(10); + for (int i = 0; i < writeVal; i++) { + collection.add(i); + } + } + + // 读取文件 + public String handleReadLock(Lock lock) { + StringBuilder result= new StringBuilder(); + lock.lock(); + try { + //Thread.sleep(9); + for (Integer num : collection) { + result.append(num); + } + } finally { + lock.unlock(); + } + return result.toString(); + } + + // 写入文件 + public void handleWriteLock(Lock lock, int writeVal) { + lock.lock(); + try { + //Thread.sleep(10); + for (int i = 0; i < writeVal; i++) { + collection.add(i); + } + } finally { + lock.unlock(); + } + } + +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/TestReadWriteLock.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/TestReadWriteLock.java similarity index 91% rename from java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/TestReadWriteLock.java rename to java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/TestReadWriteLock.java index f73202fb..e0aeefbc 100644 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/TestReadWriteLock.java +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/lock/TestReadWriteLock.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.concurrent.juc.locks; +package cn.lastwhisper.concurrent.juc.lock; import java.time.Duration; import java.time.Instant; @@ -34,8 +34,8 @@ public static void main(String[] args) throws InterruptedException { Runnable readThread = new Runnable() { @Override public void run() { - //rwl.handleRead(readLock); - rwl.handleRead(lock); + rwl.handleRead(readLock); + //rwl.handleRead(lock); latch.countDown(); } }; @@ -43,8 +43,8 @@ public void run() { Runnable writeThread = new Runnable() { @Override public void run() { - //rwl.handleWrite(writeLock, new Random().nextInt()); - rwl.handleWrite(lock, new Random().nextInt()); + rwl.handleWrite(writeLock, new Random().nextInt()); + //rwl.handleWrite(lock, new Random().nextInt()); latch.countDown(); } }; diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/ReentrantLockDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/ReentrantLockDemo.java deleted file mode 100644 index 3c7d34f1..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/ReentrantLockDemo.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.lastwhisper.concurrent.juc.locks; - -import java.util.Random; -import java.util.concurrent.locks.ReentrantLock; - -/** - * 重入锁的公平性 - * http://www.imooc.com/article/288805?block_id=tuijian_wz - * @author lastwhisper - */ -public class ReentrantLockDemo implements Runnable { - //是否公平,公平时交替打印 - private ReentrantLock lock = new ReentrantLock(true); - - @Override - public void run() { - while (true){ - try { - lock.lock(); - lock.lock(); - System.out.println(Thread.currentThread().getName()); - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - }finally { - lock.unlock(); - lock.unlock(); - } - } - } - public static void main(String[] args){ - ReentrantLockDemo lockDemo = new ReentrantLockDemo(); - new Thread(lockDemo,"A").start(); - new Thread(lockDemo,"B").start(); - } -} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/ReentrantLockToReentryDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/ReentrantLockToReentryDemo.java deleted file mode 100644 index 66565cf0..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/ReentrantLockToReentryDemo.java +++ /dev/null @@ -1,65 +0,0 @@ -package cn.lastwhisper.concurrent.juc.locks; - -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -class Phone implements Runnable { - private Lock lock = new ReentrantLock(); - - @Override - public void run() { - get(); - } - - private void get() { - lock.lock(); - try { - System.out.println(Thread.currentThread().getName() + "\tget\tlock"); - set(); - } finally { - System.out.println(Thread.currentThread().getName() + "\tget\tunlock"); - lock.unlock(); - } - } - - private void set() { - lock.lock(); - try { - System.out.println(Thread.currentThread().getName() + "\tset\tlock"); - } finally { - System.out.println(Thread.currentThread().getName() + "\tset\tunlock"); - lock.unlock(); - } - } -} - -/** - * Description: - * 可重入锁(也叫做递归锁) - * 指的是同一先生外层函数获得锁后,内层敌对函数任然能获取该锁的代码 - * 在同一线程外外层方法获取锁的时候,在进入内层方法会自动获取锁 - *

- * 也就是说,线程可以进入任何一个它已经标记的锁所同步的代码块 - * - * @author veliger@163.com - * @date 2019-04-12 23:36 - **/ -public class ReentrantLockToReentryDemo { - /** - * Thread-0 get - * Thread-0 set - * Thread-1 get - * Thread-1 set - * - * @param args - */ - public static void main(String[] args) { - Phone phone = new Phone(); - Thread t3 = new Thread(phone); - Thread t4 = new Thread(phone); - t3.start(); - t4.start(); - - } -} - diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/TestLockSupport.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/TestLockSupport.java deleted file mode 100644 index 4e948693..00000000 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locks/TestLockSupport.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.lastwhisper.concurrent.juc.locks; - -import java.util.concurrent.locks.LockSupport; - -/** - * 线程阻塞工具类 - * @author lastwhisper - */ -public class TestLockSupport { - private static ChangObjectThread t1 = new ChangObjectThread("t1"); - private static ChangObjectThread t2 = new ChangObjectThread("t2"); - - public static void main(String[] args) throws InterruptedException { - t1.start(); - Thread.sleep(1000); - t2.start(); - LockSupport.unpark(t1); - Thread.sleep(1000); - LockSupport.unpark(t2); - t1.join(); - t2.join(); - } -} - -class ChangObjectThread extends Thread { - final static Object lock = new Object(); - public ChangObjectThread(String name) { - super(name); - } - - @Override - public void run() { - synchronized (lock) { - System.out.println("in " + getName()); - // sleep - LockSupport.park(); - System.out.println("out " + getName()); - } - } - -} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locksupport/LockSupportDemo.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locksupport/LockSupportDemo.java new file mode 100644 index 00000000..cf6cbf12 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locksupport/LockSupportDemo.java @@ -0,0 +1,115 @@ +package cn.lastwhisper.concurrent.juc.locksupport; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.LockSupport; +import java.util.concurrent.locks.ReentrantLock; + +/** + * + * on 2020/11/10 23:17 + */ +public class LockSupportDemo { + + static Object objectLock = new Object(); + static Lock lock = new ReentrantLock(); + static Condition condition = lock.newCondition(); + + public static void main(String[] args) { +// synchronizedWaitNotify(); +// lockAwaitSignal(); + lockSupport(); + } + + private static void lockSupport() { + Thread a = new Thread(() -> { + try { + TimeUnit.SECONDS.sleep(3L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println(Thread.currentThread().getName() + "\t" + "come in" + System.currentTimeMillis()); + LockSupport.park(); //wait 被阻塞,等待通知等待放行,它要通过需要许可证 + System.out.println(Thread.currentThread().getName() + "\t" + "---被唤醒--" + System.currentTimeMillis()); + }, "a"); + a.start(); + + //暂停几秒钟线程 + /* try { + TimeUnit.SECONDS.sleep(3L); + } catch (InterruptedException e) { + e.printStackTrace(); + }*/ + + Thread b = new Thread(() -> { + LockSupport.unpark(a); + System.out.println(Thread.currentThread().getName() + "\t" + "---被唤醒--"); + + }, "b"); + b.start(); + } + + private static void lockAwaitSignal() { + new Thread(() -> { + lock.lock(); + try { + System.out.println(Thread.currentThread().getName() + "\t" + "----come in"); + try { + condition.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println(Thread.currentThread().getName() + "\t" + "----被唤醒"); + } finally { + lock.unlock(); + } + }, "A").start(); + + new Thread(() -> { + lock.lock(); + try { + condition.signal(); + System.out.println(Thread.currentThread().getName() + "\t" + "----通知---"); + } finally { + lock.unlock(); + } + }, "B").start(); + } + + /** + * synchronized/wait/notifyAll + */ + private static void synchronizedWaitNotify() { + new Thread(() -> { + //暂停几秒钟线程 +// try { +// TimeUnit.SECONDS.sleep(3); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } + synchronized (objectLock) { + System.out.println(Thread.currentThread().getName() + "\t" + "---come in--"); + try { + objectLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println(Thread.currentThread().getName() + "\t" + "-----被唤醒-----"); + } + + }, "A").start(); + + new Thread(() -> { + try { + TimeUnit.SECONDS.sleep(3); + } catch (InterruptedException e) { + e.printStackTrace(); + } + synchronized (objectLock) { + objectLock.notify(); + System.out.println(Thread.currentThread().getName() + "\t" + "---通知---"); + } + }, "B").start(); + } +} \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locksupport/README.md b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locksupport/README.md new file mode 100644 index 00000000..35bc7546 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/locksupport/README.md @@ -0,0 +1,11 @@ +## 一、线程阻塞唤醒 +方式1: 使用Object中的wait()方法让线程等待, 使用Object中的notify()方法唤醒线程 +方式2: 使用JUC包中Condition的await()方法让线程等待,使用signal()方法唤醒线程 +方式3: LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程 + +## 二、优缺点 +传统的synchronized和Lock实现等待唤醒通知的约束 +1. 线程先要获得并持有锁,必须在锁块(synchronized或lock)中 +2. 必须要先等待后唤醒,线程才能够被唤醒 + + diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/tools/README.md b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/tools/README.md new file mode 100644 index 00000000..e69de29b diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/tools/TestCountDownLatch.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/tools/TestCountDownLatch.java index 5061a2f2..ac5b7e72 100644 --- a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/tools/TestCountDownLatch.java +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/tools/TestCountDownLatch.java @@ -1,52 +1,70 @@ package cn.lastwhisper.concurrent.juc.tools; -import java.util.concurrent.CountDownLatch; +import java.time.LocalDate; +import java.time.Period; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.*; /** * 闭锁是一种同步方法,可以延迟线程的进度直到其到达终止状态。 * 闭锁可以用来确保某些活动直到其他活动都完成才继续执行: + * * @author lastwhisper */ public class TestCountDownLatch { - public static void main(String[] args) { + // 线程池并行执行任务 + private static ExecutorService threadPool = Executors.newFixedThreadPool(10); + + public static void main(String[] args) throws InterruptedException, ExecutionException { + CountDownLatch latch = new CountDownLatch(5); - CountDownLatchDemo cdl = new CountDownLatchDemo(latch); - long start = System.currentTimeMillis(); - for (int i = 0; i < 5; i++) { - new Thread(cdl).start(); + + List months = Arrays.asList("1月份", "2月份", "3月份", "4月份", "5月份"); + List> futureList = new ArrayList<>(); + // 并发执行每个月的报表 + for (String month : months) { + Future future = threadPool.submit(new Report(latch, month)); + futureList.add(future); } - try { - //等待所有线程执行完毕 - latch.await(); - } catch (InterruptedException e) { - e.printStackTrace(); + System.out.println("等待所有线程执行完毕"); + latch.await(); + // 对每个线程执行结果进行汇总 + List allReportData = new ArrayList<>(); + for (Future future : futureList) { + allReportData.add(future.get()); } - long end = System.currentTimeMillis(); - System.out.println("耗时:" + (end - start)); + + System.out.println(allReportData); + + // 关闭线程池 + threadPool.shutdown(); } } -class CountDownLatchDemo implements Runnable { +class Report implements Callable { private CountDownLatch latch; + private String month; - public CountDownLatchDemo(CountDownLatch latch) { + public Report(CountDownLatch latch, String month) { this.latch = latch; + this.month = month; } @Override - public void run() { - synchronized (this) { - try { - for (int i = 0; i < 1000; i++) { - if (i % 2 == 0) { - System.out.println(i); - } - } - } finally { - //线程完成后,进行减一 - latch.countDown(); - } - + public String call() { + try { + Thread.sleep(200); + System.out.println(month + "报表统计完毕"); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //线程完成后,进行减一 + latch.countDown(); } + return month + "报表数据"; } + + } \ No newline at end of file diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/tools/TestCountDownLatch2.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/tools/TestCountDownLatch2.java new file mode 100644 index 00000000..2a268b85 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/juc/tools/TestCountDownLatch2.java @@ -0,0 +1,54 @@ +package cn.lastwhisper.concurrent.juc.tools; + +import java.time.LocalDate; +import java.time.Period; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * 范围日期,按天提交到线程池,最后等待汇总 + * @author lastwhisper + */ +public class TestCountDownLatch2 { + + private static ExecutorService threadPool = Executors.newFixedThreadPool(10); + + public static void main(String[] args) throws InterruptedException, ExecutionException { + LocalDate startDate = LocalDate.now().plusDays(-30), endDate = LocalDate.now(); + + // 这种才能计算出日期之差 + int dayGap = (int) (endDate.toEpochDay() - startDate.toEpochDay())+1; + // 这种要同月才行 +// int dayGap = Period.between(endDate,startDate).getDays()+1; + System.out.println("startDate:" + startDate + " endDate:" + endDate + " 日期之差:" + dayGap); + + CountDownLatch countDownLatch = new CountDownLatch(dayGap); + + while (!startDate.isAfter(endDate)) { + LocalDate finalStartDate = startDate; + threadPool.submit(() -> { + try { + Thread.sleep(100); + System.out.println("startDate:" + finalStartDate); + } catch (InterruptedException e) { + System.out.println("startDate:" + finalStartDate+"InterruptedException:"+e); + Thread.interrupted(); + } finally { + countDownLatch.countDown(); + } + }); + startDate = startDate.plusDays(1L); + } + + try { + countDownLatch.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + // 关闭线程池,立即 + threadPool.shutdownNow(); + } +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/README.md b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/README.md new file mode 100644 index 00000000..b15edf16 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/README.md @@ -0,0 +1,7 @@ + + + + +为什么JUC中大量使用了sun.misc.Unsafe 这个类,但官方却不建议开发者使用? - 落白的回答 - 知乎 +https://www.zhihu.com/question/29266773/answer/2461567743 + diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/UnSafeCreateTest.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/UnSafeCreateTest.java new file mode 100644 index 00000000..8d0603fb --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/UnSafeCreateTest.java @@ -0,0 +1,29 @@ +package cn.lastwhisper.concurrent.unsafe; + +import sun.misc.Unsafe; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; + +/** + * @author cunchang + * @date 2022/4/29 12:24 AM + */ +public class UnSafeCreateTest { + + public static void main(String[] args) throws Exception{ + // method 1 + Class unsafeClass = Unsafe.class; + Constructor constructor = unsafeClass.getDeclaredConstructor(); + constructor.setAccessible(true); + Unsafe unsafe1 = constructor.newInstance(); + System.out.println(unsafe1); + + // method2 + Field theUnsafe = unsafeClass.getDeclaredField("theUnsafe"); + theUnsafe.setAccessible(true); + Unsafe unsafe2 = (Unsafe) theUnsafe.get(null); + System.out.println(unsafe2); + } + +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/UnSafeMemoryTest.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/UnSafeMemoryTest.java new file mode 100644 index 00000000..08a96f20 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/UnSafeMemoryTest.java @@ -0,0 +1,36 @@ +package cn.lastwhisper.concurrent.unsafe; + +import sun.misc.Unsafe; + +import java.lang.reflect.Field; + +/** + * @author cunchang + * @date 2022/4/29 12:24 AM + */ +public class UnSafeMemoryTest { + /** + * 堆外内存不受jvm内存模型掌控,在nio(netty,mina)中大量使用对外内存进行管道传输,copy等, + * 使用它们的好处如下: + * 对垃圾回收停顿的改善。由于堆外内存是直接受操作系统管理而不是JVM,所以当我们使用堆外内存时,即可保持较小的堆内内存规模。从而在GC时减少回收停顿对于应用的影响。 + * 提升程序I/O操作的性能。通常在I/O通信过程中,会存在堆内内存到堆外内存的数据拷贝操作,对于需要频繁进行内存间数据拷贝且生命周期较短的暂存数据,都建议存储到堆外内存。而在jdk中,堆外内存对应的类为DirectByteBuffer,它内部也是通过unsafe分配的内存: + * + * @param args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafe.setAccessible(true); + Unsafe unsafe = (Unsafe) theUnsafe.get(null); + + // 分配 10M的堆外内存 + long _10M_Address = unsafe.allocateMemory(1 * 1024 * 1024 * 10); + // 将10M内存的 前面1M内存值设置为10 + unsafe.setMemory(_10M_Address, 1 * 1024 * 1024 * 1, (byte) 10); + // 获取第1M内存的值: 10 + System.out.println(unsafe.getByte(_10M_Address + 1000)); + // 获取第1M内存后的值: 0(没有设置) + System.out.println(unsafe.getByte(_10M_Address + 1 * 1024 * 1024 * 5)); + } + +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/UnSafeOpArrayTest.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/UnSafeOpArrayTest.java new file mode 100644 index 00000000..7b0b5866 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/UnSafeOpArrayTest.java @@ -0,0 +1,36 @@ +package cn.lastwhisper.concurrent.unsafe; + +import sun.misc.Unsafe; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.util.Arrays; + +/** + * @author cunchang + * @date 2022/4/29 12:24 AM + */ +public class UnSafeOpArrayTest { + + public static void main(String[] args) throws Exception{ + Class unsafeClass = Unsafe.class; + Constructor constructor = unsafeClass.getDeclaredConstructor(); + constructor.setAccessible(true); + Unsafe unsafe = constructor.newInstance(); + + Integer[] integers = new Integer[10]; + // 打印数组的原始值 + System.out.println(Arrays.toString(integers)); + // 获取Integer数组在内存中的固定的偏移量 + long arrayBaseOffset = unsafe.arrayBaseOffset(Integer[].class); + System.out.println(unsafe.arrayIndexScale(Integer[].class)); + System.out.println(unsafe.arrayIndexScale(double[].class)); + // 将数组中第一个元素的更新为100 + unsafe.putObject(integers, arrayBaseOffset, 100); + // 将数组中第五个元素更新为50 注意 引用类型占用4个字节,所以内存地址 需要 4 * 4 = 16 + unsafe.putObject(integers, arrayBaseOffset + 16, 50); + // 打印更新后的值 + System.out.println(Arrays.toString(integers)); + } + +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/UnSafeParkTest.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/UnSafeParkTest.java new file mode 100644 index 00000000..d3f2240c --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/UnSafeParkTest.java @@ -0,0 +1,43 @@ +package cn.lastwhisper.concurrent.unsafe; + +import sun.misc.Unsafe; + +import java.lang.reflect.Field; + +/** + * @author cunchang + * @date 2022/4/29 12:24 AM + */ +public class UnSafeParkTest { + + public static void main(String[] args) throws Exception { + Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafe.setAccessible(true); + Unsafe unsafe = (Unsafe) theUnsafe.get(null); + + Thread t1 = new Thread(() -> { + for (int i = 0; i < 10; i++) { + if (i == 5) { + // i == 5时,将当前线程挂起 + unsafe.park(false, 0L); + } + System.out.println(Thread.currentThread().getName() + " printing i : " + i); + } + }, " Thread__Unsafe__1"); + + t1.start(); + + // 主线程休息三秒 + Thread.sleep(3000L); + for (int i = 0; i < 10; i++) { + System.out.println(Thread.currentThread().getName() + " printing i : " + i); + if (i == 9) { + // 将线程 t1 唤醒 + unsafe.unpark(t1); + } + } + + System.in.read(); + } + +} diff --git a/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/UnsafeCasTest.java b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/UnsafeCasTest.java new file mode 100644 index 00000000..29250729 --- /dev/null +++ b/java-basic/concurrent/src/main/java/cn/lastwhisper/concurrent/unsafe/UnsafeCasTest.java @@ -0,0 +1,32 @@ +package cn.lastwhisper.concurrent.unsafe; + +import sun.misc.Unsafe; + +import java.lang.reflect.Field; + +public class UnsafeCasTest { + public static void main(String[] args) throws Exception { + Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafe.setAccessible(true); + Unsafe unsafe = (Unsafe) theUnsafe.get(null); + + User user = new User("jsbintask"); + long nameOffset = unsafe.objectFieldOffset(User.class.getDeclaredField("name")); + unsafe.compareAndSwapObject(user, nameOffset, "jsbintask1", "jsbintask2"); + System.out.println("第一次更新后的值:" + user.getName()); + unsafe.compareAndSwapObject(user, nameOffset, "jsbintask", "jsbintask2"); + System.out.println("第二次更新后的值:" + user.getName()); + } +} + +class User { + private String name; + + public User(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} \ No newline at end of file diff --git a/java-basic/design-pattern/README.md b/java-basic/design-pattern/README.md index fba38945..4f68ee58 100644 --- a/java-basic/design-pattern/README.md +++ b/java-basic/design-pattern/README.md @@ -80,3 +80,8 @@ 中间也参考了无数的博客,这里只贴几个参考比较多的。 [chenssy设计模式](https://www.cnblogs.com/chenssy/category/482229.html) + + +# 4. 进阶 + + diff --git a/java-basic/design-pattern/pom.xml b/java-basic/design-pattern/pom.xml index 33caf942..5523f3eb 100644 --- a/java-basic/design-pattern/pom.xml +++ b/java-basic/design-pattern/pom.xml @@ -2,15 +2,12 @@ - - java-basic - cn.lastwhisper - 1.0-SNAPSHOT - + 4.0.0 cn.lastwhisper design-pattern + 1.0-SNAPSHOT UTF-8 @@ -282,6 +279,11 @@ 2.9.0 + + junit + junit + 4.13 + diff --git a/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/Boxer.java b/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/Boxer.java new file mode 100644 index 00000000..3d64d384 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/Boxer.java @@ -0,0 +1,13 @@ +package com.desgin.advance.decorator_vs_proxy; + +/** + * 拳击手 + * @author lastwhisper + * @date 2020/4/12 + */ +public interface Boxer { + + // 打拳 + void fight(); + +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/BoxerImpl.java b/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/BoxerImpl.java new file mode 100644 index 00000000..22eb67ea --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/BoxerImpl.java @@ -0,0 +1,30 @@ +package com.desgin.advance.decorator_vs_proxy; + +/** + * 泰森 + * @author lastwhisper + * @date 2020/4/12 + */ +public class BoxerImpl implements Boxer { + + private String name; + + @Override + public void fight() { + hook(); + duck(); + straight(); + } + + private void duck() { + System.out.println("拳手:闪避"); + } + + private void hook() { + System.out.println("拳手:勾拳"); + } + + private void straight() { + System.out.println("拳手:直拳"); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/Client.java b/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/Client.java new file mode 100644 index 00000000..f2162f89 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/Client.java @@ -0,0 +1,35 @@ +package com.desgin.advance.decorator_vs_proxy; + +import com.desgin.advance.decorator_vs_proxy.decorator.FastShoesDecorator; +import com.desgin.advance.decorator_vs_proxy.proxy.AgentProxy; +import org.junit.Test; + +/** + * @author lastwhisper + * @date 2020/4/12 + */ +public class Client { + + // 代理模式 + @Test + public void test1() { + Boxer boxer = new BoxerImpl(); + Boxer agent = new AgentProxy(boxer); + System.out.println("准备比赛!"); + agent.fight(); + System.out.println("比赛结束!"); + } + + // 装饰者模式 + @Test + public void test2() { + Boxer boxer = new BoxerImpl(); + FastShoesDecorator fastShoesDecorator = new FastShoesDecorator(boxer); + Boxer agent = new AgentProxy(fastShoesDecorator); + System.out.println("准备比赛!"); + fastShoesDecorator.moveFast(); + agent.fight(); + System.out.println("比赛结束!"); + } + +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/README.md b/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/README.md new file mode 100644 index 00000000..f568c025 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/README.md @@ -0,0 +1,17 @@ +decorator_proxy为装饰者模式与代理模式的对比 +https://www.zhihu.com/question/41988550/answer/462204684 +拳击手、经纪人、移速鞋 + + + +看过钢铁侠没? +史塔克穿反浩克战甲(装饰模式) +但是史塔克没能力自己穿,只能让贾维斯帮自己从太空上叫下来(代理模式) +贾维斯只有一个(代理模式不会无限代理) +mark装甲有无数个(装饰模式可以无限增强) + + + + + + diff --git a/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/decorator/FastShoesDecorator.java b/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/decorator/FastShoesDecorator.java new file mode 100644 index 00000000..a4c72ceb --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/decorator/FastShoesDecorator.java @@ -0,0 +1,26 @@ +package com.desgin.advance.decorator_vs_proxy.decorator; + +import com.desgin.advance.decorator_vs_proxy.Boxer; + +/** + * 移速鞋 + * @author lastwhisper + * @date 2020/4/12 + */ +public class FastShoesDecorator implements Boxer { + private Boxer boxer; + + public FastShoesDecorator(Boxer boxer) { + this.boxer = boxer; + } + + public void moveFast() { + System.out.println("穿上非常快的鞋:移速+5"); + } + + @Override + public void fight() { + boxer.fight(); + } + +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/proxy/AgentProxy.java b/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/proxy/AgentProxy.java new file mode 100644 index 00000000..7bdab293 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/advance/decorator_vs_proxy/proxy/AgentProxy.java @@ -0,0 +1,37 @@ +package com.desgin.advance.decorator_vs_proxy.proxy; + +import com.desgin.advance.decorator_vs_proxy.Boxer; + +/** + * 经纪人 + * @author lastwhisper + * @date 2020/4/12 + */ +public class AgentProxy implements Boxer { + private Boxer boxer; + + public AgentProxy(Boxer boxer) { + this.boxer = boxer; + } + + @Override + public void fight() { + findOpponent(); + findSponsor(); + negotiate(); + System.out.println("让拳手去比赛"); + boxer.fight(); + } + + private void findOpponent() { + System.out.println("经纪人:寻找适用于当前拳手的对手"); + } + + private void findSponsor() { + System.out.println("经纪人:寻找赞助商"); + } + + private void negotiate() { + System.out.println("经纪人:洽谈"); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/README.md b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/README.md new file mode 100644 index 00000000..b79df7d6 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/README.md @@ -0,0 +1,10 @@ + +责任链实现 +v1:多个过滤器逻辑写在一起 +问题:如何支持可配置化拦截器? +v2:各个过滤器责任单一 +问题:如何支持可配置化拦截器? +v3:通过一个上下文类,支持配置化 +v4: +v4、v5:本质上差不多,但是v5通过模板方法,固定调用了流程,降低了使用门槛 + diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v1/Client.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v1/Client.java new file mode 100644 index 00000000..24500b5a --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v1/Client.java @@ -0,0 +1,39 @@ +package com.desgin.mashibing.chainofresponsibility.abstractImpl.v1; + +/** + * @author lastwhisper + */ +public class Client { + static class HandlerA extends Handler{ + @Override + protected void handleProcess() { + System.out.println("handle by a"); + } + } + + static class HandlerB extends Handler{ + @Override + protected void handleProcess() { + System.out.println("handle by b"); + } + } + + static class HandlerC extends Handler{ + @Override + protected void handleProcess() { + System.out.println("handle by c"); + } + } + + public static void main(String[] args){ + Handler handlerA = new HandlerA(); + Handler handlerB = new HandlerB(); + Handler handlerC = new HandlerC(); + + handlerA.setSucessor(handlerB); + handlerB.setSucessor(handlerC); + + handlerA.execute(); + } + +} diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v1/Handler.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v1/Handler.java similarity index 86% rename from springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v1/Handler.java rename to java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v1/Handler.java index b50fc633..03d964a1 100644 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v1/Handler.java +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v1/Handler.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.chain.v1; +package com.desgin.mashibing.chainofresponsibility.abstractImpl.v1; /** * @author lastwhisper diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v2/Chain.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v2/Chain.java new file mode 100644 index 00000000..a8f118fd --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v2/Chain.java @@ -0,0 +1,24 @@ +package com.desgin.mashibing.chainofresponsibility.abstractImpl.v2; + +import java.util.List; + +/** + * 使用chain进行包装 + * @author lastwhisper + */ +public class Chain { + private List handlers; + private int index = 0; + + public Chain(List handlers) { + this.handlers = handlers; + } + + //将顺序关系封装 + public void proceed() { + if (index >= handlers.size()) { + return; + } + handlers.get(index++).execute(this); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v2/ChainClient.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v2/ChainClient.java new file mode 100644 index 00000000..e0742ff3 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v2/ChainClient.java @@ -0,0 +1,38 @@ +package com.desgin.mashibing.chainofresponsibility.abstractImpl.v2; + +import java.util.Arrays; +import java.util.List; + +/** + * Created by cat on 2017-02-28. + */ +public class ChainClient { + static class ChainHandlerA extends ChainHandler{ + @Override + protected void handleProcess() { + System.out.println("handle by chain a"); + } + } + static class ChainHandlerB extends ChainHandler{ + @Override + protected void handleProcess() { + System.out.println("handle by chain b"); + } + } + static class ChainHandlerC extends ChainHandler{ + @Override + protected void handleProcess() { + System.out.println("handle by chain c"); + } + } + + public static void main(String[] args){ + List handlers = Arrays.asList( + new ChainHandlerA(), + new ChainHandlerB(), + new ChainHandlerC() + ); + Chain chain = new Chain(handlers); + chain.proceed(); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v2/ChainHandler.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v2/ChainHandler.java new file mode 100644 index 00000000..4a8b4014 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v2/ChainHandler.java @@ -0,0 +1,15 @@ +package com.desgin.mashibing.chainofresponsibility.abstractImpl.v2; + +/** + * Created by cat on 2017-02-28. + */ +public abstract class ChainHandler { + + public void execute(Chain chain){ + handleProcess(); + chain.proceed(); + + } + + protected abstract void handleProcess(); +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v3/Chain.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v3/Chain.java new file mode 100644 index 00000000..75f30e77 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v3/Chain.java @@ -0,0 +1,24 @@ +package com.desgin.mashibing.chainofresponsibility.abstractImpl.v3; + +import java.util.List; + +/** + * 使用chain进行包装 + * @author lastwhisper + */ +public class Chain { + private List handlers; + private int index = 0; + + public Chain(List handlers) { + this.handlers = handlers; + } + + //将顺序关系封装 + public void proceed() { + if (index >= handlers.size()) { + return; + } + handlers.get(index++).execute(this); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v3/ChainClient.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v3/ChainClient.java new file mode 100644 index 00000000..72c7e54f --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v3/ChainClient.java @@ -0,0 +1,57 @@ +package com.desgin.mashibing.chainofresponsibility.abstractImpl.v3; + +import java.util.Arrays; +import java.util.List; + +/** + * Created by cat on 2017-02-28. + */ +public class ChainClient { + static class ChainHandlerA extends ChainHandler { + @Override + protected void handlePreProcess() { + System.out.println("ChainHandlerA handlePreProcess"); + } + + @Override + protected void handlePostProcess() { + System.out.println("ChainHandlerA handlePostProcess"); + } + } + + static class ChainHandlerB extends ChainHandler { + @Override + protected void handlePreProcess() { + System.out.println("ChainHandlerB handlePreProcess"); + } + + @Override + protected void handlePostProcess() { + System.out.println("ChainHandlerB handlePostProcess"); + } + } + + static class ChainHandlerC extends ChainHandler { + @Override + protected void handlePreProcess() { + System.out.println("ChainHandlerC handlePreProcess"); + } + + @Override + protected void handlePostProcess() { + System.out.println("ChainHandlerC handlePostProcess"); + } + } + + public static void main(String[] args) { + List handlers = Arrays.asList( + new ChainHandlerA(), + new ChainHandlerB(), + new ChainHandlerC() + ); + Chain chain = new Chain(handlers); + chain.proceed(); + + + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v3/ChainHandler.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v3/ChainHandler.java new file mode 100644 index 00000000..3e175f5c --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/abstractImpl/v3/ChainHandler.java @@ -0,0 +1,17 @@ +package com.desgin.mashibing.chainofresponsibility.abstractImpl.v3; + +/** + * Created by cat on 2017-02-28. + */ +public abstract class ChainHandler { + + // 模板方法 + public void execute(Chain chain){ + handlePreProcess(); + chain.proceed(); + handlePostProcess(); + } + + protected abstract void handlePreProcess(); + protected abstract void handlePostProcess(); +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v1/Main.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v1/Main.java new file mode 100644 index 00000000..1d29a78d --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v1/Main.java @@ -0,0 +1,15 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v1; + +/** + * @author lastwhisper + */ +public class Main { + + public static void main(String[] args) { + String msg = "大家好,QAQ, ,郭嘉,漂亮国!"; + MsgProcessor mp = new MsgProcessor(); + mp.setMsg(msg); + msg = mp.process(); + System.out.println(msg); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v1/MsgProcessor.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v1/MsgProcessor.java new file mode 100644 index 00000000..644f849f --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v1/MsgProcessor.java @@ -0,0 +1,27 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v1; + +/** + * @author lastwhisper + */ +public class MsgProcessor { + String msg; + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public String process() { + // process the html tag <> + String r = msg.replaceAll("<", "<") + .replaceAll(">", ">"); + // process the sensitive words + r= r.replaceAll("郭嘉", "**") + .replaceAll("漂亮国", "***"); + + return r; + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/FaceFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/FaceFilter.java new file mode 100644 index 00000000..bceb5784 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/FaceFilter.java @@ -0,0 +1,13 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v2; + +/** + * @author lastwhisper + */ +public class FaceFilter implements Filter { + // process the face tag <> + @Override + public String doFilter(String str) { + return str.replaceAll("QAQ", "^V^"); + } + +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/Filter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/Filter.java new file mode 100644 index 00000000..d10b777f --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/Filter.java @@ -0,0 +1,5 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v2; + +public interface Filter { + String doFilter(String str); +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/HTMLFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/HTMLFilter.java new file mode 100644 index 00000000..7af98970 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/HTMLFilter.java @@ -0,0 +1,13 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v2; + +/** + * @author lastwhisper + */ +public class HTMLFilter implements Filter { + // process the html tag <> + @Override + public String doFilter(String str) { + return str.replaceAll("<", "<") + .replaceAll(">", ">"); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/Main.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/Main.java new file mode 100644 index 00000000..32f028cb --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/Main.java @@ -0,0 +1,15 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v2; + +/** + * @author lastwhisper + */ +public class Main { + + public static void main(String[] args) { + String msg = "大家好,QAQ, ,郭嘉,漂亮国!"; + MsgProcessor mp = new MsgProcessor(); + mp.setMsg(msg); + msg = mp.process(); + System.out.println(msg); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/MsgProcessor.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/MsgProcessor.java new file mode 100644 index 00000000..bf65a9fd --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/MsgProcessor.java @@ -0,0 +1,26 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v2; + +/** + * @author lastwhisper + */ +public class MsgProcessor { + String msg; + + Filter[] filters = {new HTMLFilter(), new SesitiveFilter(), new FaceFilter()}; + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public String process() { + String r = msg; + for (Filter filter : filters) { + r = filter.doFilter(r); + } + return r; + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/SesitiveFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/SesitiveFilter.java new file mode 100644 index 00000000..a1160abd --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v2/SesitiveFilter.java @@ -0,0 +1,14 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v2; + +/** + * @author lastwhisper + */ +public class SesitiveFilter implements Filter { + // process the sensitive words + @Override + public String doFilter(String str) { + String r = str.replaceAll("郭嘉", "**") + .replaceAll("漂亮国", "***"); + return r; + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/FaceFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/FaceFilter.java new file mode 100644 index 00000000..0d9daf22 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/FaceFilter.java @@ -0,0 +1,14 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v3; + +/** + * @author lastwhisper + */ +public class FaceFilter implements Filter { + // process the face tag <> + @Override + public String doFilter(String str) { + String r = str.replaceAll("QAQ", "^V^"); + return r; + } + +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/Filter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/Filter.java new file mode 100644 index 00000000..a37e8c1f --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/Filter.java @@ -0,0 +1,5 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v3; + +public interface Filter { + String doFilter(String str); +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/FilterChain.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/FilterChain.java new file mode 100644 index 00000000..eefc65ab --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/FilterChain.java @@ -0,0 +1,25 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v3; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author lastwhisper + */ +public class FilterChain implements Filter{ + + List filters = new ArrayList(); + + public FilterChain addFilter(Filter f) { + filters.add(f); + return this; + } + + public String doFilter(String str) { + String r = str; + for (Filter filter : filters) { + r = filter.doFilter(r); + } + return r; + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/HTMLFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/HTMLFilter.java new file mode 100644 index 00000000..801678de --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/HTMLFilter.java @@ -0,0 +1,14 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v3; + +/** + * @author lastwhisper + */ +public class HTMLFilter implements Filter { + // process the html tag <> + @Override + public String doFilter(String str) { + String r = str.replaceAll("<", "<") + .replaceAll(">", ">"); + return r; + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/Main.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/Main.java new file mode 100644 index 00000000..d7d597dd --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/Main.java @@ -0,0 +1,23 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v3; + + +/** + * @author lastwhisper + */ +public class Main { + + public static void main(String[] args) { + String msg = "大家好,QAQ, ,郭嘉,漂亮国!"; + FilterChain filterChain = new FilterChain(); + filterChain.addFilter(new HTMLFilter()) + .addFilter(new SesitiveFilter()); + + FilterChain filterChain2 = new FilterChain(); + filterChain2.addFilter(new FaceFilter()); + + filterChain.addFilter(filterChain2); + + msg = filterChain.doFilter(msg); + System.out.println(msg); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/SesitiveFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/SesitiveFilter.java new file mode 100644 index 00000000..b6017510 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v3/SesitiveFilter.java @@ -0,0 +1,14 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v3; + +/** + * @author lastwhisper + */ +public class SesitiveFilter implements Filter { + // process the sensitive words + @Override + public String doFilter(String str) { + String r = str.replaceAll("郭嘉", "**") + .replaceAll("漂亮国", "***"); + return r; + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/FaceFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/FaceFilter.java new file mode 100644 index 00000000..a97587c3 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/FaceFilter.java @@ -0,0 +1,22 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v4; + +/** + * @author lastwhisper + */ +public class FaceFilter implements Filter { + + @Override + public void doFilter(Request request, Response response, FilterChain chain) { + // 处理request请求 + request.requestStr = request.requestStr.replaceAll("QAQ", "^V^") + + "---FaceFilter.request()"; + System.out.println("FaceFilter.request()"); + + chain.doFilter(request, response, chain); + + // 处理response响应 + response.responseStr = response.responseStr.replaceAll("QAQ", "^V^") + + "---FaceFilter.response()"; + System.out.println("FaceFilter.response()"); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/Filter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/Filter.java new file mode 100644 index 00000000..4c53bfe6 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/Filter.java @@ -0,0 +1,5 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v4; + +public interface Filter { + void doFilter(Request request, Response response, FilterChain chain); +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/FilterChain.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/FilterChain.java new file mode 100644 index 00000000..70dc568d --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/FilterChain.java @@ -0,0 +1,25 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v4; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author lastwhisper + */ +public class FilterChain implements Filter { + + private List filters = new ArrayList(); + + private int index = 0; + + public FilterChain addFilter(Filter f) { + filters.add(f); + return this; + } + + @Override + public void doFilter(Request request, Response response, FilterChain chain) { + if (index == filters.size()) return; + filters.get(index++).doFilter(request, response, chain); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/HTMLFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/HTMLFilter.java new file mode 100644 index 00000000..a1e1cc43 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/HTMLFilter.java @@ -0,0 +1,22 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v4; + +/** + * @author lastwhisper + */ +public class HTMLFilter implements Filter { + + @Override + public void doFilter(Request request, Response response, FilterChain chain) { + // 处理request请求 + request.requestStr = request.requestStr.replaceAll("<", "<") + .replaceAll(">", ">") + "---HTMLFilter.request()"; + System.out.println("HTMLFilter.request()"); + + chain.doFilter(request, response, chain); + + // 处理response响应 + response.responseStr = response.responseStr.replaceAll("<", "<") + .replaceAll(">", ">") + "---HTMLFilter.response()"; + System.out.println("HTMLFilter.response()"); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/Main.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/Main.java new file mode 100644 index 00000000..ae9bb311 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/Main.java @@ -0,0 +1,31 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v4; + + +/** + * @author lastwhisper + */ +public class Main { + + public static void main(String[] args) { + // 初始化数据 + String msg = "大家好,QAQ, ,郭嘉,漂亮国!"; + Request request = new Request(); + request.setRequestStr(msg); + Response response = new Response(); + response.setResponseStr(msg); + // 过滤链1 + FilterChain filterChain = new FilterChain(); + filterChain.addFilter(new HTMLFilter()) + .addFilter(new SesitiveFilter()); + //// 过滤链2 + FilterChain filterChain2 = new FilterChain(); + filterChain2.addFilter(new FaceFilter()); + //// 过滤链1+过滤链2 + filterChain.addFilter(filterChain2); + // 处理 + filterChain.doFilter(request, response, filterChain); + + System.out.println(request.getRequestStr()); + System.out.println(response.getResponseStr()); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/Request.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/Request.java new file mode 100644 index 00000000..b6ddb6f3 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/Request.java @@ -0,0 +1,16 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v4; + +/** + * @author lastwhisper + */ +public class Request { + String requestStr; + + public String getRequestStr() { + return requestStr; + } + + public void setRequestStr(String requestStr) { + this.requestStr = requestStr; + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/Response.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/Response.java new file mode 100644 index 00000000..8c597c72 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/Response.java @@ -0,0 +1,16 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v4; + +/** + * @author lastwhisper + */ +public class Response { + String responseStr; + + public String getResponseStr() { + return responseStr; + } + + public void setResponseStr(String responseStr) { + this.responseStr = responseStr; + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/SesitiveFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/SesitiveFilter.java new file mode 100644 index 00000000..2846cac6 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v4/SesitiveFilter.java @@ -0,0 +1,22 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v4; + +/** + * @author lastwhisper + */ +public class SesitiveFilter implements Filter { + + @Override + public void doFilter(Request request, Response response, FilterChain chain) { + // 处理request请求 + request.requestStr = request.requestStr.replaceAll("郭嘉", "**") + .replaceAll("漂亮国", "***") + "---SesitiveFilter.request()"; + System.out.println("SesitiveFilter.request()"); + + chain.doFilter(request, response, chain); + + // 处理response响应 + response.responseStr = response.responseStr.replaceAll("郭嘉", "**") + .replaceAll("漂亮国", "***") + "---SesitiveFilter.response()"; + System.out.println("SesitiveFilter.response()"); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/AbstractFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/AbstractFilter.java new file mode 100644 index 00000000..bc0bcb28 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/AbstractFilter.java @@ -0,0 +1,30 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v5; + + +/** + * @author cunchang + * @date 2021/5/11 12:58 下午 + */ +public abstract class AbstractFilter implements Filter { + + @Override + public void doFilter(Request request, Response response, FilterChain chain) { + handlePreProcess(request,response); + chain.doFilter(request,response,chain); + handlePostProcess(request,response); + } + + /** + * 责任链前置处理 + * @param request + * @param response + */ + protected abstract void handlePreProcess(Request request, Response response); + + /** + * 责任链后置处理 + * @param request + * @param response + */ + protected abstract void handlePostProcess(Request request, Response response); +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/FaceFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/FaceFilter.java new file mode 100644 index 00000000..862495f8 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/FaceFilter.java @@ -0,0 +1,23 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v5; + +/** + * @author lastwhisper + */ +public class FaceFilter extends AbstractFilter { + + @Override + protected void handlePreProcess(Request request, Response response) { + // 处理request请求 + request.requestStr = request.requestStr.replaceAll("QAQ", "^V^") + + "---FaceFilter.request()"; + System.out.println("FaceFilter.request()"); + } + + @Override + protected void handlePostProcess(Request request, Response response) { + // 处理response响应 + response.responseStr = response.responseStr.replaceAll("QAQ", "^V^") + + "---FaceFilter.response()"; + System.out.println("FaceFilter.response()"); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/Filter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/Filter.java new file mode 100644 index 00000000..6b1848de --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/Filter.java @@ -0,0 +1,11 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v5; + +public interface Filter { + /** + * 责任链 + * @param request + * @param response + * @param chain + */ + void doFilter(Request request, Response response, FilterChain chain); +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/FilterChain.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/FilterChain.java new file mode 100644 index 00000000..63736574 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/FilterChain.java @@ -0,0 +1,25 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v5; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author lastwhisper + */ +public class FilterChain implements Filter { + + private List filters = new ArrayList(); + + private int index = 0; + + public FilterChain addFilter(Filter f) { + filters.add(f); + return this; + } + + @Override + public void doFilter(Request request, Response response, FilterChain chain) { + if (index == filters.size()) return; + filters.get(index++).doFilter(request, response, chain); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/HTMLFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/HTMLFilter.java new file mode 100644 index 00000000..02780de8 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/HTMLFilter.java @@ -0,0 +1,23 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v5; + +/** + * @author lastwhisper + */ +public class HTMLFilter extends AbstractFilter { + + @Override + protected void handlePreProcess(Request request, Response response) { + // 处理request请求 + request.requestStr = request.requestStr.replaceAll("<", "<") + .replaceAll(">", ">") + "---HTMLFilter.request()"; + System.out.println("HTMLFilter.request()"); + } + + @Override + protected void handlePostProcess(Request request, Response response) { + // 处理response响应 + response.responseStr = response.responseStr.replaceAll("<", "<") + .replaceAll(">", ">") + "---HTMLFilter.response()"; + System.out.println("HTMLFilter.response()"); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/Main.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/Main.java new file mode 100644 index 00000000..5ff0623b --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/Main.java @@ -0,0 +1,36 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v5; + + +/** + * @author lastwhisper + */ +public class Main { + + public static void main(String[] args) { + // 初始化数据 + String msg = "大家好,QAQ, ,郭嘉,漂亮国!"; + Request request = new Request(); + request.setRequestStr(msg); + Response response = new Response(); + response.setResponseStr(msg); + // 过滤链1 + FilterChain filterChain = new FilterChain(); + filterChain.addFilter(new HTMLFilter()) + .addFilter(new SesitiveFilter()); + // 过滤链2 + FilterChain filterChain2 = new FilterChain(); + filterChain2.addFilter(new FaceFilter()); + // 过滤链1+过滤链2 + filterChain.addFilter(filterChain2); + + // 处理前 + System.out.println(request.getRequestStr()); + System.out.println(response.getResponseStr()); + + filterChain.doFilter(request, response, filterChain); + + // 处理后 + System.out.println(request.getRequestStr()); + System.out.println(response.getResponseStr()); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/Request.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/Request.java new file mode 100644 index 00000000..62c544b6 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/Request.java @@ -0,0 +1,16 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v5; + +/** + * @author lastwhisper + */ +public class Request { + String requestStr; + + public String getRequestStr() { + return requestStr; + } + + public void setRequestStr(String requestStr) { + this.requestStr = requestStr; + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/Response.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/Response.java new file mode 100644 index 00000000..b314ac2a --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/Response.java @@ -0,0 +1,16 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v5; + +/** + * @author lastwhisper + */ +public class Response { + String responseStr; + + public String getResponseStr() { + return responseStr; + } + + public void setResponseStr(String responseStr) { + this.responseStr = responseStr; + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/SesitiveFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/SesitiveFilter.java new file mode 100644 index 00000000..faaea7f6 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/chainofresponsibility/interfaceImpl/v5/SesitiveFilter.java @@ -0,0 +1,22 @@ +package com.desgin.mashibing.chainofresponsibility.interfaceImpl.v5; + +/** + * @author lastwhisper + */ +public class SesitiveFilter implements Filter { + + @Override + public void doFilter(Request request, Response response, FilterChain chain) { + // 处理request请求 + request.requestStr = request.requestStr.replaceAll("郭嘉", "**") + .replaceAll("漂亮国", "***") + "---SesitiveFilter.request()"; + System.out.println("SesitiveFilter.request()"); + + chain.doFilter(request, response, chain); + + // 处理response响应 + response.responseStr = response.responseStr.replaceAll("郭嘉", "**") + .replaceAll("漂亮国", "***") + "---SesitiveFilter.response()"; + System.out.println("SesitiveFilter.response()"); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/command/Boy.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/command/Boy.java new file mode 100644 index 00000000..d0b9856c --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/command/Boy.java @@ -0,0 +1,39 @@ +package com.desgin.mashibing.command; + +import java.util.ArrayList; +import java.util.List; + +public class Boy { + private String name; + private List commands = new ArrayList(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void pursue(MM mm) { + } + + public void doSomeThing() { + + } + + public void addCommand(Command c1) { + this.commands.add(c1); + } + + public void executeCommands() { + for(Command c : commands) { + c.execute(); + } + } + + public void undoCommands() { + // + } + +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/command/Command.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/command/Command.java new file mode 100644 index 00000000..a1020c51 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/command/Command.java @@ -0,0 +1,6 @@ +package com.desgin.mashibing.command; + +public abstract class Command { + public abstract void execute(); + public abstract void unDo(); +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/command/HugCommand.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/command/HugCommand.java new file mode 100644 index 00000000..7eb289c8 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/command/HugCommand.java @@ -0,0 +1,15 @@ +package com.desgin.mashibing.command; + +public class HugCommand extends Command { + + @Override + public void execute() { + System.out.println("hug"); + } + + @Override + public void unDo() { + System.out.println("open your arms"); + } + +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/command/MM.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/command/MM.java new file mode 100644 index 00000000..afda0b9f --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/command/MM.java @@ -0,0 +1,21 @@ +package com.desgin.mashibing.command; + +public class MM { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void order(Boy b) { + Command c1 = new ShoppingCommand(); + b.addCommand(c1); + Command c2 = new HugCommand(); + b.addCommand(c2); + b.executeCommands(); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/command/ShoppingCommand.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/command/ShoppingCommand.java new file mode 100644 index 00000000..e98bf5f7 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/command/ShoppingCommand.java @@ -0,0 +1,15 @@ +package com.desgin.mashibing.command; + +public class ShoppingCommand extends Command { + + @Override + public void execute() { + System.out.println("zoo"); + } + + @Override + public void unDo() { + System.out.println("undo zoo"); + } + +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/ArrayList.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/ArrayList.java new file mode 100644 index 00000000..2c38ed51 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/ArrayList.java @@ -0,0 +1,44 @@ +package com.desgin.mashibing.iterator; + +import com.desgin.mashibing.iterator.Collection; + +public class ArrayList implements Collection { + Object[] objects = new Object[10]; + int index = 0; + public void add(Object o) { + if(index == objects.length) { + Object[] newObjects = new Object[objects.length * 2]; + System.arraycopy(objects, 0, newObjects, 0, objects.length); + objects = newObjects; + } + objects[index] = o; + index ++; + } + + public int size() { + return index; + } + + public Iterator iterator() { + + return new ArrayListIterator(); + } + + private class ArrayListIterator implements Iterator { + private int currentIndex = 0; + + @Override + public boolean hasNext() { + if(currentIndex >= index) return false; + else return true; + } + + @Override + public Object next() { + Object o = objects[currentIndex]; + currentIndex ++; + return o; + } + + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/Cat.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/Cat.java new file mode 100644 index 00000000..75ef13c6 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/Cat.java @@ -0,0 +1,15 @@ +package com.desgin.mashibing.iterator; + +public class Cat { + public Cat(int id) { + super(); + this.id = id; + } + + private int id; + + @Override + public String toString() { + return "cat:" + id; + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/Collection.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/Collection.java new file mode 100644 index 00000000..1554ee63 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/Collection.java @@ -0,0 +1,7 @@ +package com.desgin.mashibing.iterator; + +public interface Collection { + void add(Object o); + int size(); + Iterator iterator(); +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/Iterator.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/Iterator.java new file mode 100644 index 00000000..4ea28f81 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/Iterator.java @@ -0,0 +1,6 @@ +package com.desgin.mashibing.iterator; + +public interface Iterator { + Object next(); + boolean hasNext(); +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/LinkedList.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/LinkedList.java new file mode 100644 index 00000000..afb898a2 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/LinkedList.java @@ -0,0 +1,28 @@ +package com.desgin.mashibing.iterator; + +import com.desgin.mashibing.iterator.Collection; + +public class LinkedList implements Collection { + Node head = null; + Node tail = null; + int size = 0; + public void add(Object o) { + Node n = new Node(o, null); + if(head == null) { + head = n; + tail = n; + } + tail.setNext(n); + tail = n; + size ++; + } + + public int size() { + return size; + } + + @Override + public Iterator iterator() { + return null; + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/Node.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/Node.java new file mode 100644 index 00000000..324fc007 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/Node.java @@ -0,0 +1,24 @@ +package com.desgin.mashibing.iterator; + +public class Node { + public Node(Object data, Node next) { + super(); + this.data = data; + this.next = next; + } + + public Object getData() { + return data; + } + public void setData(Object data) { + this.data = data; + } + public Node getNext() { + return next; + } + public void setNext(Node next) { + this.next = next; + } + private Object data; + private Node next; +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/Test.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/Test.java new file mode 100644 index 00000000..ba6587f2 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/Test.java @@ -0,0 +1,24 @@ +package com.desgin.mashibing.iterator; + +import com.desgin.mashibing.iterator.ArrayList; +import com.desgin.mashibing.iterator.LinkedList; + +public class Test { + public static void main(String[] args) { + //ArrayList al = new ArrayList(); + //LinkedList al = new LinkedList(); + Collection c = new ArrayList(); + for(int i=0; i<15; i++) { + c.add(new Cat(i)); + } + System.out.println(c.size()); + + Iterator it = c.iterator(); + while(it.hasNext()) { + Object o = it.next(); + System.out.print(o + " "); + } + } +} + + diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/generic/GenericArrayList.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/generic/GenericArrayList.java new file mode 100644 index 00000000..c4de9e33 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/iterator/generic/GenericArrayList.java @@ -0,0 +1,24 @@ +package com.desgin.mashibing.iterator.generic; + +public class GenericArrayList { + Object[] objects = new Object[10]; + int index = 0; + public void add(E o) { + if(index == objects.length) { + Object[] newObjects = new Object[objects.length * 2]; + System.arraycopy(objects, 0, newObjects, 0, objects.length); + objects = newObjects; + } + objects[index] = o; + index ++; + } + + public int size() { + return index; + } + + public static void main(String args[]) { + GenericArrayList a = new GenericArrayList(); + a.add("hello"); + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/Cat.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/Cat.java new file mode 100644 index 00000000..617c067d --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/Cat.java @@ -0,0 +1,45 @@ +package com.desgin.mashibing.strategy; + + +public class Cat implements Comparable { + private int height; + //private Comparator comparator = new CatHeightComparator(); + private java.util.Comparator comparator = new CatHeightComparator(); + public java.util.Comparator getComparator() { + return comparator; + } + public void setComparator(java.util.Comparator comparator) { + this.comparator = comparator; + } + public int getHeight() { + return height; + } + public void setHeight(int height) { + this.height = height; + } + + + public Cat(int height, int weight) { + super(); + this.height = height; + this.weight = weight; + } + public int getWeight() { + return weight; + } + public void setWeight(int weight) { + this.weight = weight; + } + private int weight; + + @Override + public String toString() { + return height + "|" + weight; + } + + @Override + public int compareTo(Cat o) { + return comparator.compare(this, o); + } + +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/CatHeightComparator.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/CatHeightComparator.java new file mode 100644 index 00000000..ddf061d8 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/CatHeightComparator.java @@ -0,0 +1,15 @@ +package com.desgin.mashibing.strategy; + +public class CatHeightComparator implements java.util.Comparator { + + @Override + public int compare(Cat o1, Cat o2) { + Cat c1 = (Cat)o1; + Cat c2 = (Cat)o2; + if(c1.getHeight() > c2.getHeight()) return 1; + else if(c1.getHeight() < c2.getHeight()) return -1; + return 0; + + } + +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/CatWeightComparator.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/CatWeightComparator.java new file mode 100644 index 00000000..616ce4c1 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/CatWeightComparator.java @@ -0,0 +1,14 @@ +package com.desgin.mashibing.strategy; + +public class CatWeightComparator implements Comparator { + + @Override + public int compare(Object o1, Object o2) { + Cat c1 = (Cat)o1; + Cat c2 = (Cat)o2; + if(c1.getWeight() > c2.getWeight()) return -1; + else if(c1.getHeight() < c2.getHeight()) return 1; + return 0; + } + +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/Comparable.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/Comparable.java new file mode 100644 index 00000000..6c392185 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/Comparable.java @@ -0,0 +1,8 @@ +package com.desgin.mashibing.strategy; + +//使一个类本身具备比较性 +//优点:实现此接口的类可以自己重写自己规定比较的内容 +//缺点:因为只有一个方法,一个类只能有一种方式进行比较 +public interface Comparable { + public int compareTo(T o); +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/Comparator.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/Comparator.java new file mode 100644 index 00000000..6608b934 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/Comparator.java @@ -0,0 +1,5 @@ +package com.desgin.mashibing.strategy; + +public interface Comparator { + int compare(Object o1, Object o2); +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/DataSorter.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/DataSorter.java new file mode 100644 index 00000000..2221e156 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/DataSorter.java @@ -0,0 +1,55 @@ +package com.desgin.mashibing.strategy; + +import java.lang.Comparable; + +public class DataSorter { + + public static void sort(Object[] a) { + for(int i=a.length; i>0; i--) { + for(int j=0; j0; i--) { + for(int j=0; j a[j+1]) { + swap(a, j , j+1); + } + } + } + } + + private static void swap(int[] a, int x, int y) { + int temp = a[x]; + a[x] = a[y]; + a[y] = temp; + } + + public static void p(int[] a) { + for(int i=0; i d.getFood()) return 1; + else if(this.food < d.getFood()) return -1; + else return 0; + } + + @Override + public String toString() { + return this.food + ""; + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/Test.java b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/Test.java new file mode 100644 index 00000000..56f96af7 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/mashibing/strategy/Test.java @@ -0,0 +1,13 @@ +package com.desgin.mashibing.strategy; + +public class Test { + public static void main(String[] args) { + //int[] a = {9, 5, 3, 7, 1}; + Cat[] a = {new Cat(5, 5), new Cat(3, 3), new Cat(1, 1)}; + //Dog[] a = {new Dog(5), new Dog(3), new Dog(1)}; + DataSorter.sort(a); + java.util.Arrays.sort(a); + DataSorter.p(a); + + } +} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/Approver.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/Approver.java deleted file mode 100644 index 7a17b5bf..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/Approver.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility; - -/** - * 批准者 - */ -public abstract class Approver { - /** 责任链的核心就是在类里面包含了一个自己同样类型的一个对象 */ - protected Approver approver; - - public void setNextApprover(Approver approver) { - this.approver = approver; - } - - public abstract void deploy(Course course) ; -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/ArticleApprover.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/ArticleApprover.java deleted file mode 100644 index 2a8d4359..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/ArticleApprover.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility; - -import org.apache.commons.lang3.StringUtils; - -public class ArticleApprover extends Approver { - - @Override - public void deploy(Course course) { - if (StringUtils.isNoneEmpty(course.getArticle())) { - System.out.println(course.getName() + "含有手记,批准"); - //交给下一个责任链对象处理 - if (approver != null) { - approver.deploy(course); - } - } else { - System.out.println(course.getName() + "不含有手记,不批准,流程结束"); - return; - } - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/Course.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/Course.java deleted file mode 100644 index 702b314a..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/Course.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility; - -public class Course { - private String name; - private String article; - private String video; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getArticle() { - return article; - } - - public void setArticle(String article) { - this.article = article; - } - - public String getVideo() { - return video; - } - - public void setVideo(String video) { - this.video = video; - } - - @Override - public String toString() { - return "Course{" + - "name='" + name + '\'' + - ", article='" + article + '\'' + - ", video='" + video + '\'' + - '}'; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/README.md b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/README.md new file mode 100644 index 00000000..fbef29f9 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/README.md @@ -0,0 +1 @@ +请查看 design-pattern 项目 com/desgin/mashibing/chainofresponsibility 包 \ No newline at end of file diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/Test.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/Test.java deleted file mode 100644 index c232eec2..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/Test.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility; - -public class Test { - public static void main(String[] args) { - Approver articleApprover = new ArticleApprover(); - Approver videoApprover = new VideoApprover(); - - Course course = new Course(); - course.setName("Java设计模式精讲"); - course.setArticle("Java设计模式精讲的手记"); - course.setVideo("Java设计模式精讲的视频"); - /** 先通过手记的审核才交给视频的审核,视频的审核过了才能进行发布上线 */ - articleApprover.setNextApprover(videoApprover); - articleApprover.deploy(course); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/VideoApprover.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/VideoApprover.java deleted file mode 100644 index 1cb9c4f6..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/VideoApprover.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility; - -import org.apache.commons.lang3.StringUtils; - -public class VideoApprover extends Approver { - @Override - public void deploy(Course course) { - if (StringUtils.isNoneEmpty(course.getVideo())) { - System.out.println(course.getName() + "含有视频,批准"); - //交给下一个责任链对象处理 - if (approver != null) { - approver.deploy(course); - } - } else { - System.out.println(course.getName() + "不含有视频,不批准,流程结束"); - return; - } - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version1/Main.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version1/Main.java deleted file mode 100644 index caec89e0..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version1/Main.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version1; - -/** - * @author lastwhisper - */ -public class Main { - - public static void main(String[] args) { - String msg = "大家好,QAQ, ,敏感字眼,不学习!"; - MsgProcessor mp = new MsgProcessor(); - mp.setMsg(msg); - msg = mp.process(); - System.out.println(msg); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version1/MsgProcessor.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version1/MsgProcessor.java deleted file mode 100644 index e4d39d0b..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version1/MsgProcessor.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version1; - -/** - * @author lastwhisper - */ -public class MsgProcessor { - String msg; - - public String getMsg() { - return msg; - } - - public void setMsg(String msg) { - this.msg = msg; - } - - public String process() { - // process the html tag <> - String r = msg.replaceAll("<", "[") - .replaceAll(">", "]"); - // process the sensitive words - r= r.replaceAll("不学习", "好好学习") - .replaceAll("敏感字眼", ""); - - return r; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/FaceFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/FaceFilter.java deleted file mode 100644 index e063179e..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/FaceFilter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version2; - -/** - * @author lastwhisper - */ -public class FaceFilter implements Filter { - // process the face tag <> - @Override - public String doFilter(String str) { - return str.replaceAll("QAQ", "^V^"); - } - -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/Filter.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/Filter.java deleted file mode 100644 index 2cae1c0e..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/Filter.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version2; - -public interface Filter { - String doFilter(String str); -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/HTMLFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/HTMLFilter.java deleted file mode 100644 index e777772d..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/HTMLFilter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version2; - -/** - * @author lastwhisper - */ -public class HTMLFilter implements Filter { - // process the html tag <> - @Override - public String doFilter(String str) { - return str.replaceAll("<", "[") - .replaceAll(">", "]"); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/Main.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/Main.java deleted file mode 100644 index 1898a170..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/Main.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version2; - -/** - * @author lastwhisper - */ -public class Main { - - public static void main(String[] args) { - String msg = "大家好,QAQ, ,敏感字眼,不学习!"; - MsgProcessor mp = new MsgProcessor(); - mp.setMsg(msg); - msg = mp.process(); - System.out.println(msg); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/MsgProcessor.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/MsgProcessor.java deleted file mode 100644 index ffce5536..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/MsgProcessor.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version2; - -/** - * @author lastwhisper - */ -public class MsgProcessor { - String msg; - - Filter[] filters = {new HTMLFilter(), new SesitiveFilter(), new FaceFilter()}; - - public String getMsg() { - return msg; - } - - public void setMsg(String msg) { - this.msg = msg; - } - - public String process() { - String r = msg; - for (Filter filter : filters) { - r = filter.doFilter(r); - } - return r; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/SesitiveFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/SesitiveFilter.java deleted file mode 100644 index ed062f8a..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version2/SesitiveFilter.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version2; - -/** - * @author lastwhisper - */ -public class SesitiveFilter implements Filter { - // process the sensitive words - @Override - public String doFilter(String str) { - String r = str.replaceAll("不学习", "好好学习") - .replaceAll("敏感字眼", ""); - return r; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/FaceFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/FaceFilter.java deleted file mode 100644 index e9bff6b8..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/FaceFilter.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version3; - -/** - * @author lastwhisper - */ -public class FaceFilter implements Filter { - // process the face tag <> - @Override - public String doFilter(String str) { - String r = str.replaceAll("QAQ", "^V^"); - return r; - } - -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/Filter.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/Filter.java deleted file mode 100644 index f0d49a82..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/Filter.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version3; - -public interface Filter { - String doFilter(String str); -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/FilterChain.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/FilterChain.java deleted file mode 100644 index 55cac184..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/FilterChain.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version3; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author lastwhisper - */ -public class FilterChain implements Filter{ - - List filters = new ArrayList(); - - public FilterChain addFilter(Filter f) { - filters.add(f); - return this; - } - - public String doFilter(String str) { - String r = str; - for (Filter filter : filters) { - r = filter.doFilter(r); - } - return r; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/HTMLFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/HTMLFilter.java deleted file mode 100644 index 9cde94ff..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/HTMLFilter.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version3; - -/** - * @author lastwhisper - */ -public class HTMLFilter implements Filter { - // process the html tag <> - @Override - public String doFilter(String str) { - String r = str.replaceAll("<", "[") - .replaceAll(">", "]"); - return r; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/Main.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/Main.java deleted file mode 100644 index 7384099b..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/Main.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version3; - - -/** - * @author lastwhisper - */ -public class Main { - - public static void main(String[] args) { - String msg = "大家好,QAQ, ,敏感字眼,不学习!"; - FilterChain filterChain = new FilterChain(); - filterChain.addFilter(new HTMLFilter()) - .addFilter(new SesitiveFilter()); - - FilterChain filterChain2 = new FilterChain(); - filterChain2.addFilter(new FaceFilter()); - - filterChain.addFilter(filterChain2); - - msg = filterChain.doFilter(msg); - System.out.println(msg); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/SesitiveFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/SesitiveFilter.java deleted file mode 100644 index bbd9a142..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version3/SesitiveFilter.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version3; - -/** - * @author lastwhisper - */ -public class SesitiveFilter implements Filter { - // process the sensitive words - @Override - public String doFilter(String str) { - String r = str.replaceAll("不学习", "好好学习") - .replaceAll("敏感字眼", ""); - return r; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/FaceFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/FaceFilter.java deleted file mode 100644 index bc679660..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/FaceFilter.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version4; - -/** - * @author lastwhisper - */ -public class FaceFilter implements Filter { - - @Override - public void doFilter(Request request, Response response, FilterChain chain) { - // 处理request请求 - request.requestStr = request.requestStr.replaceAll("QAQ", "^V^") - + "---FaceFilter.request()"; - - // 处理response响应 - response.responseStr = response.responseStr.replaceAll("QAQ", "^V^") - + "---FaceFilter.response()"; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/Filter.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/Filter.java deleted file mode 100644 index 1e33bb35..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/Filter.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version4; - -public interface Filter { - void doFilter(Request request, Response response, FilterChain chain); -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/FilterChain.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/FilterChain.java deleted file mode 100644 index 425d493d..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/FilterChain.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version4; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author lastwhisper - */ -public class FilterChain implements Filter { - - private List filters = new ArrayList(); - - private int index = 0; - - public FilterChain addFilter(Filter f) { - filters.add(f); - return this; - } - - @Override - public void doFilter(Request request, Response response, FilterChain chain) { - if (index == filters.size()) return; - //Filter filter = filters.get(index); - //index++; - //filter.doFilter(request, response, chain); - filters.get(index++).doFilter(request, response, chain); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/HTMLFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/HTMLFilter.java deleted file mode 100644 index 5467b9e0..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/HTMLFilter.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version4; - -/** - * @author lastwhisper - */ -public class HTMLFilter implements Filter { - - @Override - public void doFilter(Request request, Response response, FilterChain chain) { - // 处理request请求 - request.requestStr = request.requestStr.replaceAll("<", "<") - .replaceAll(">", ">") + "---HTMLFilter.request()"; - - chain.doFilter(request, response, chain); - - // 处理response响应 - response.responseStr = response.responseStr.replaceAll("<", "<") - .replaceAll(">", ">") + "---HTMLFilter.response()"; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/Main.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/Main.java deleted file mode 100644 index 187d32f5..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/Main.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version4; - - -/** - * @author lastwhisper - */ -public class Main { - - public static void main(String[] args) { - // 初始化数据 - String msg = "大家好,QAQ, ,敏感字眼,不学习!"; - Request request = new Request(); - request.setRequestStr(msg); - Response response = new Response(); - response.setResponseStr(msg); - // 过滤链1 - FilterChain filterChain = new FilterChain(); - filterChain.addFilter(new HTMLFilter()) - .addFilter(new SesitiveFilter()); - //// 过滤链2 - //FilterChain filterChain2 = new FilterChain(); - //filterChain2.addFilter(new FaceFilter()); - //// 过滤链1+过滤链2 - //filterChain.addFilter(filterChain2); - // 处理 - filterChain.doFilter(request, response, filterChain); - - System.out.println(request.getRequestStr()); - System.out.println(response.getResponseStr()); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/Request.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/Request.java deleted file mode 100644 index 9dc62243..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/Request.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version4; - -/** - * @author lastwhisper - */ -public class Request { - String requestStr; - - public String getRequestStr() { - return requestStr; - } - - public void setRequestStr(String requestStr) { - this.requestStr = requestStr; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/Response.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/Response.java deleted file mode 100644 index b145d239..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/Response.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version4; - -/** - * @author lastwhisper - */ -public class Response { - String responseStr; - - public String getResponseStr() { - return responseStr; - } - - public void setResponseStr(String responseStr) { - this.responseStr = responseStr; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/SesitiveFilter.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/SesitiveFilter.java deleted file mode 100644 index 1d2bcd0a..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/chainofresponsibility/mashibing/version4/SesitiveFilter.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.desgin.pattern.behavioral.chainofresponsibility.mashibing.version4; - -/** - * @author lastwhisper - */ -public class SesitiveFilter implements Filter { - - @Override - public void doFilter(Request request, Response response, FilterChain chain) { - // 处理request请求 - request.requestStr = request.requestStr.replaceAll("不学习", "好好学习") - .replaceAll("敏感字眼", "") + "---SesitiveFilter.request()"; - // 处理response响应 - response.responseStr = response.responseStr.replaceAll("不学习", "好好学习") - .replaceAll("敏感字眼", "") + "---SesitiveFilter.response()"; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/state/Test.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/state/Test.java index 80c37684..e748f33c 100644 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/state/Test.java +++ b/java-basic/design-pattern/src/main/java/com/desgin/pattern/behavioral/state/Test.java @@ -6,6 +6,7 @@ public class Test { public static void main(String[] args){ CourseVideoContext courseVideoContext = new CourseVideoContext(); + // 改变一个对象,所属的类 courseVideoContext.setCourseVideoState(new PlayState()); System.out.println("当前状态"+ courseVideoContext.getCourseVideoState().getClass().getSimpleName()); diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/prototype/Mail.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/prototype/Mail.java deleted file mode 100644 index 1fa56565..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/prototype/Mail.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.desgin.pattern.creational.prototype; - -/** - * Create by lastwhisper on 2019/1/27 - */ -public class Mail implements Cloneable{ - private String name; - private String emailAddress; - private String content; - - public Mail() { - System.out.println("Mail Class Constructor"); - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getEmailAddress() { - return emailAddress; - } - - public void setEmailAddress(String emailAddress) { - this.emailAddress = emailAddress; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - @Override - public String toString() { - return "Mail{" + - "name='" + name + '\'' + - ", emailAddress='" + emailAddress + '\'' + - ", content='" + content + '\'' + - '}'+super.toString(); - } - - @Override - protected Object clone() throws CloneNotSupportedException { - System.out.println("clone mail object"); - return super.clone(); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/prototype/MailUtils.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/prototype/MailUtils.java deleted file mode 100644 index 753e47e3..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/prototype/MailUtils.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.desgin.pattern.creational.prototype; - -import java.text.MessageFormat; - -/** - * Create by lastwhisper on 2019/1/27 - */ -public class MailUtils { - public static void sendMail(Mail mail){ - String outputContent = "向{0}同学,邮件地址:{1},邮件内容:{2}发送邮件成功"; - System.out.println(MessageFormat.format(outputContent, - mail.getName(),mail.getEmailAddress(),mail.getContent())); - } - public static void saveOriginMailRecord(Mail mail){ - System.out.println("存储originMail记录,originMail:"+mail.getContent()); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/prototype/Test.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/prototype/Test.java deleted file mode 100644 index 586573a2..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/prototype/Test.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.desgin.pattern.creational.prototype; - -/** - * Create by lastwhisper on 2019/1/27 - */ -public class Test { - public static void main(String[] args) throws CloneNotSupportedException { - Mail mail = new Mail(); - mail.setContent("初始化模板"); - System.out.println("初始化mail:"+mail); - for (int i = 0; i < 10; i++) { - Mail mailTemp = (Mail) mail.clone(); -// mail.setName("姓名" + i); -// mail.setEmailAddress("姓名" + i + "@qq.com"); -// mail.setContent("恭喜您,QQ号中大奖了"); - mailTemp.setName("姓名" + i); - mailTemp.setEmailAddress("姓名" + i + "@qq.com"); - mailTemp.setContent("恭喜您,QQ号中大奖了"); - MailUtils.sendMail(mailTemp); - System.out.println("克隆的mailTemp:"+mailTemp); - } - MailUtils.saveOriginMailRecord(mail); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/prototype/clone/Pig.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/prototype/clone/Pig.java deleted file mode 100644 index d45402fb..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/prototype/clone/Pig.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.desgin.pattern.creational.prototype.clone; - -import java.util.Date; - -/** - * Create by lastwhisper on 2019/1/27 - */ -public class Pig implements Cloneable { - private String name; - private Date birthday; - - public Pig() { - } - - public Pig(String name, Date birthday) { - this.name = name; - this.birthday = birthday; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Date getBirthday() { - return birthday; - } - - public void setBirthday(Date birthday) { - this.birthday = birthday; - } - - @Override - public String toString() { - return "Pig{" + - "name='" + name + '\'' + - ", birthday=" + birthday + - '}' + super.toString(); - } - - @Override - protected Object clone() throws CloneNotSupportedException { - Pig pig = (Pig) super.clone(); - //深克隆 - pig.birthday = (Date) pig.birthday.clone(); - return pig; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/prototype/clone/Test.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/prototype/clone/Test.java deleted file mode 100644 index 515e4df5..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/prototype/clone/Test.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.desgin.pattern.creational.prototype.clone; - -import com.desgin.pattern.creational.singleton.HungrySingleton; - -/** - * Create by lastwhisper on 2019/1/27 - */ -public class Test { - public static void main(String[] args) throws CloneNotSupportedException { -// Date birthday = new Date(0L); -// Pig pig1 = new Pig("佩奇", birthday); -// Pig pig2 = (Pig) pig1.clone(); -// System.out.println(pig1); -// System.out.println(pig2); -// pig1.getBirthday().setTime(666666666666L); -// System.out.println(pig1); -// System.out.println(pig2); - HungrySingleton instance = HungrySingleton.getInstance(); - - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/singleton/LazyDoubleCheckSingleton.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/singleton/LazyDoubleCheckSingleton.java index 753adee3..eb3bd774 100644 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/singleton/LazyDoubleCheckSingleton.java +++ b/java-basic/design-pattern/src/main/java/com/desgin/pattern/creational/singleton/LazyDoubleCheckSingleton.java @@ -5,13 +5,15 @@ */ public class LazyDoubleCheckSingleton { private static volatile LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null; - private LazyDoubleCheckSingleton(){ + + private LazyDoubleCheckSingleton() { } - public static LazyDoubleCheckSingleton getInstance(){ - if(lazyDoubleCheckSingleton == null){ - synchronized (LazyDoubleCheckSingleton.class){ - if(lazyDoubleCheckSingleton == null){ + + public static LazyDoubleCheckSingleton getInstance() { + if (lazyDoubleCheckSingleton == null) { + synchronized (LazyDoubleCheckSingleton.class) { + if (lazyDoubleCheckSingleton == null) { lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton(); //第一步 分配内存给这个对象 //第二步 初始化这个对象 diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/IOrderDao.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/IOrderDao.java deleted file mode 100644 index 84fec5c3..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/IOrderDao.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.desgin.pattern.structural.proxy; - -public interface IOrderDao { - int insert(Order order); -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/IOrderService.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/IOrderService.java deleted file mode 100644 index 6ad40c8c..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/IOrderService.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.desgin.pattern.structural.proxy; - -public interface IOrderService { - /** 保存订单,参数为订单对象,返回值为生效行数 */ - int saveOrder(Order order); -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/Order.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/Order.java deleted file mode 100644 index 9f5e3cb7..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/Order.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.desgin.pattern.structural.proxy; - -public class Order { - private Object orderInfo; - private Integer userId; - - public Object getOrderInfo() { - return orderInfo; - } - - public void setOrderInfo(Object orderInfo) { - this.orderInfo = orderInfo; - } - - public Integer getUserId() { - return userId; - } - - public void setUserId(Integer userId) { - this.userId = userId; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/OrderDaoImpl.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/OrderDaoImpl.java deleted file mode 100644 index bdad76e3..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/OrderDaoImpl.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.desgin.pattern.structural.proxy; - -public class OrderDaoImpl implements IOrderDao { - @Override - public int insert(Order order) { - System.out.println("Dao层添加order成功"); - return 1; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/OrderServiceImpl.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/OrderServiceImpl.java deleted file mode 100644 index 4cca5932..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/OrderServiceImpl.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.desgin.pattern.structural.proxy; - -public class OrderServiceImpl implements IOrderService { - - private IOrderDao iOrderDao; - - @Override - public int saveOrder(Order order) { - /** Spring会自己注入,我们这里就直接new出来了 */ - iOrderDao = new OrderDaoImpl(); - System.out.println("Service调用Dao层添加Order层"); - return iOrderDao.insert(order); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/README.md b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/README.md new file mode 100644 index 00000000..7cff2471 --- /dev/null +++ b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/README.md @@ -0,0 +1 @@ +移至 java-advance/proxy 目录 \ No newline at end of file diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/db/DataSourceContextHolder.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/db/DataSourceContextHolder.java deleted file mode 100644 index 01f4b4f6..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/db/DataSourceContextHolder.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.desgin.pattern.structural.proxy.db; - -public class DataSourceContextHolder { - private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal<>(); - - public static void setDBType(String dbType) { - CONTEXT_HOLDER.set(dbType); - } - - public static String getDBType() { - return CONTEXT_HOLDER.get(); - } - - public static void clearDBType() { - CONTEXT_HOLDER.remove(); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/db/DynamicDataSource.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/db/DynamicDataSource.java deleted file mode 100644 index 05b6c1cd..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/db/DynamicDataSource.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.desgin.pattern.structural.proxy.db; - -import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; - -public class DynamicDataSource extends AbstractRoutingDataSource { - @Override - protected Object determineCurrentLookupKey() { - return DataSourceContextHolder.getDBType(); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/dynamicproxy/OrderServiceDynamicProxy.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/dynamicproxy/OrderServiceDynamicProxy.java deleted file mode 100644 index 5e52c678..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/dynamicproxy/OrderServiceDynamicProxy.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.desgin.pattern.structural.proxy.dynamicproxy; - -import com.desgin.pattern.structural.proxy.Order; -import com.desgin.pattern.structural.proxy.db.DataSourceContextHolder; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - -/** - * Create by lastwhisper on 2019/2/10 - */ -public class OrderServiceDynamicProxy implements InvocationHandler { - - /** 这是目标类 */ - private Object target; - - /** 通过构造器把目标类注入进来 */ - public OrderServiceDynamicProxy(Object target) { - this.target = target; - } - - /** 获取目标对象 */ - public Object getProxy() { - Class clazz = target.getClass(); - return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this); - } - - /** - * proxy:代理类代理的真实代理对象com.sun.proxy.$Proxy0 - * method:我们所要调用某个对象真实的方法的Method对象 - * args:指代代理对象方法传递的参数 - */ - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - Object argObject = args[0]; - beforeMethod(argObject); - Object object = method.invoke(target, args); - afterMethod(); - return object; - } - - public void beforeMethod(Object obj) { - int userId = 0; - System.out.println("动态代理before code"); - if (obj instanceof Order) { - Order order = (Order) obj; - userId = order.getUserId(); - } - /** 这里就是实现一个分库的功能,对userId取模2,这里就只会得到0或者是1 */ - int dbRouter = userId % 2; - System.out.println("动态代理分配到【db"+dbRouter+"】处理数据"); - //todo 设置dataSource; - DataSourceContextHolder.setDBType(String.valueOf(dbRouter)); - } - public void afterMethod() { - System.out.println("动态代理after code"); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/dynamicproxy/Test.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/dynamicproxy/Test.java deleted file mode 100644 index db551300..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/dynamicproxy/Test.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.desgin.pattern.structural.proxy.dynamicproxy; - -import com.desgin.pattern.structural.proxy.IOrderService; -import com.desgin.pattern.structural.proxy.Order; -import com.desgin.pattern.structural.proxy.OrderServiceImpl; - -public class Test { - public static void main(String[]args){ - Order order = new Order(); - order.setUserId(2); - /** 这里没有采用spring自动注入的方式,而是采用了直接new的方式 */ - IOrderService orderServiceProxy = (IOrderService) new OrderServiceDynamicProxy(new OrderServiceImpl()).getProxy(); - orderServiceProxy.saveOrder(order); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/dynamicproxy/Calculator.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/dynamicproxy/Calculator.java deleted file mode 100644 index 54b26b10..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/dynamicproxy/Calculator.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.desgin.pattern.structural.proxy.my.dynamicproxy; - -/** - * @author lastwhisper - */ -public interface Calculator { - int add(int a, int b); - int subtract(int a, int b); -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/dynamicproxy/CalculatorDynamicProxy.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/dynamicproxy/CalculatorDynamicProxy.java deleted file mode 100644 index f4b61081..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/dynamicproxy/CalculatorDynamicProxy.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.desgin.pattern.structural.proxy.my.dynamicproxy; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - -/** - * 动态代理 - * @author lastwhisper - */ -public class CalculatorDynamicProxy implements InvocationHandler { - // 目标类 - private Object target; - - // 代理类通过构造器接收目标对象(被代理类) - public CalculatorDynamicProxy(Object target) { - this.target = target; - } - - /** 获取目标对象 */ - public Object getProxy() { - Class clazz = target.getClass(); - return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this); - } - - /** - * proxy:代理类代理的真实代理对象com.sun.proxy.$Proxy0 - * method:我们所要调用某个对象真实的方法的Method对象 - * args:指代代理对象方法传递的参数 - */ - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - Object argObject = args[0]; - beforeMethod(); - Object object = method.invoke(target, args); - afterMethod(); - return object; - } - - public void beforeMethod() { - System.out.println("proxy代理,日志开始记录"); - } - - public void afterMethod() { - System.out.println("proxy代理,日志结束,已记录到数据库中"); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/dynamicproxy/CalculatorImpl.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/dynamicproxy/CalculatorImpl.java deleted file mode 100644 index 64a66ab8..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/dynamicproxy/CalculatorImpl.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.desgin.pattern.structural.proxy.my.dynamicproxy; - -/** - * @author lastwhisper - */ -public class CalculatorImpl implements Calculator { - - @Override - public int add(int a, int b) { - int result = a + b; - return result; - } - - @Override - public int subtract(int a, int b) { - int result = a - b; - return result; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/dynamicproxy/Client.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/dynamicproxy/Client.java deleted file mode 100644 index 7a445068..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/dynamicproxy/Client.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.desgin.pattern.structural.proxy.my.dynamicproxy; - -/** - * @author lastwhisper - */ -public class Client { - public static void main(String[] args) { - Calculator calculator = (Calculator) new CalculatorDynamicProxy(new CalculatorImpl()).getProxy(); - System.out.println(calculator.add(1, 2)); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/hardcode/Calculator.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/hardcode/Calculator.java deleted file mode 100644 index 8278ef64..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/hardcode/Calculator.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.desgin.pattern.structural.proxy.my.hardcode; -// 硬编码 -public class Calculator { - - //加 - public int add(int a, int b) { - System.out.println("add日志开始记录"); - int result = a + b; - System.out.println("add日志结束,已记录到数据库中"); - return result; - } - - //减 - public int subtract(int a, int b) { - System.out.println("subtract日志开始记录"); - int result = a - b; - System.out.println("subtract日志结束,已记录到数据库中"); - return result; - } - - //乘法、除法... -} \ No newline at end of file diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/staticproxy/Calculator.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/staticproxy/Calculator.java deleted file mode 100644 index 562d1ba7..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/staticproxy/Calculator.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.desgin.pattern.structural.proxy.my.staticproxy; - -/** - * @author lastwhisper - */ -public interface Calculator { - int add(int a, int b); - int subtract(int a, int b); -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/staticproxy/CalculatorImpl.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/staticproxy/CalculatorImpl.java deleted file mode 100644 index e1cb4ac0..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/staticproxy/CalculatorImpl.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.desgin.pattern.structural.proxy.my.staticproxy; - -/** - * @author lastwhisper - */ -public class CalculatorImpl implements Calculator { - - @Override - public int add(int a, int b) { - int result = a + b; - return result; - } - - @Override - public int subtract(int a, int b) { - int result = a - b; - return result; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/staticproxy/CalculatorStaticProxy.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/staticproxy/CalculatorStaticProxy.java deleted file mode 100644 index b31c4dea..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/staticproxy/CalculatorStaticProxy.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.desgin.pattern.structural.proxy.my.staticproxy; - -/** - * 静态代理 - * @author lastwhisper - */ -public class CalculatorStaticProxy { - // 被代理类 - private Calculator calculator; - // 代理类通过构造器接收被代理类 - public CalculatorStaticProxy(Calculator calculator) { - this.calculator = calculator; - } - - public int proxyAdd(int a, int b) { - System.out.println("proxy代理,add日志开始记录"); - int result = calculator.add(a, b); - System.out.println("proxy代理,add日志结束,已记录到数据库中"); - return result; - } - - public int proxySubtract(int a, int b) { - System.out.println("proxy代理,subtract日志开始记录"); - int result = calculator.subtract(a, b); - System.out.println("proxy代理,subtract日志结束,已记录到数据库中"); - return result; - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/staticproxy/Client.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/staticproxy/Client.java deleted file mode 100644 index 91faae34..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/my/staticproxy/Client.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.desgin.pattern.structural.proxy.my.staticproxy; - -/** - * @author lastwhisper - */ -public class Client { - public static void main(String[] args) { - CalculatorStaticProxy calculatorProxy = new CalculatorStaticProxy(new CalculatorImpl()); - int result = calculatorProxy.proxyAdd(5, 3); - - result = calculatorProxy.proxySubtract(5, 3); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/staticproxy/OrderServiceStaticProxy.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/staticproxy/OrderServiceStaticProxy.java deleted file mode 100644 index 14233795..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/staticproxy/OrderServiceStaticProxy.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.desgin.pattern.structural.proxy.staticproxy; - -import com.desgin.pattern.structural.proxy.IOrderService; -import com.desgin.pattern.structural.proxy.Order; -import com.desgin.pattern.structural.proxy.OrderServiceImpl; -import com.desgin.pattern.structural.proxy.db.DataSourceContextHolder; - -public class OrderServiceStaticProxy { - /** 在代理类里面注入目标对象 */ - private IOrderService iOrderService; - - /** 我们要在这静态代理类里面增强这个方法 */ - public int saveOrder(Order order){ - beforeMethod(order); - /** 如果这里有spring容器的话,就不用显示的new了 */ - iOrderService = new OrderServiceImpl(); - int result = iOrderService.saveOrder(order); - afterMethod(); - return result; - } - - /** 我们要增强,我们就来写上一个before和after */ - private void beforeMethod(Order order){ - int userId = order.getUserId(); - /** 这里就是实现一个分库的功能,对userId取模2,这里就只会得到0或者是1 */ - int dbRouter = userId % 2; - System.out.println("静态代理分配到【db"+dbRouter+"】处理数据"); - - //todo 设置dataSource; - DataSourceContextHolder.setDBType("db"+dbRouter); - System.out.println("静态代理 before code"); - } - - private void afterMethod(){ - System.out.println("静态代理 after code"); - } -} diff --git a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/staticproxy/Test.java b/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/staticproxy/Test.java deleted file mode 100644 index 6abc0f70..00000000 --- a/java-basic/design-pattern/src/main/java/com/desgin/pattern/structural/proxy/staticproxy/Test.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.desgin.pattern.structural.proxy.staticproxy; - -import com.desgin.pattern.structural.proxy.Order; - -public class Test { - public static void main(String[]args){ - Order order = new Order(); - order.setUserId(0); - /** 这里没有采用spring自动注入的方式,而是采用了直接new的方式 */ - OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy(); - orderServiceStaticProxy.saveOrder(order); - } -} diff --git a/java-basic/feature-jdk5/README.md b/java-basic/feature-jdk5/README.md new file mode 100644 index 00000000..7a237054 --- /dev/null +++ b/java-basic/feature-jdk5/README.md @@ -0,0 +1,18 @@ +参考“传智 张孝详 Java高新技术” + +# Jdk5的一些新特性学习 +- 自动拆装箱 AutoBox +- 静态导入 StaticImport +- 可变参数 VariableParameter +- 枚举 enumtest +- 注解 annotation +- 反省与JavaBean introspection +- beanutils beanutils +- 反射 reflect +- 泛型 generic +- 类加载器;已从当前项目移除,查看该项目 github/code/java-basic/jvm/ +- 动态代理;已从当前项目移除,查看该项目 github/code/java-advance/proxy +- throwable + + + diff --git a/java-basic/feature-jdk5/pom.xml b/java-basic/feature-jdk5/pom.xml new file mode 100644 index 00000000..c9fa7dfe --- /dev/null +++ b/java-basic/feature-jdk5/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + feature-jdk5 + cn.cunchang + 1.0-SNAPSHOT + + + UTF-8 + + + + + + junit + junit + 4.13 + + + + + + feature-jdk5 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + + + src/main/java + + **/*.xml + + true + + + + + \ No newline at end of file diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/AutoBox.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/AutoBox.java similarity index 90% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/AutoBox.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/AutoBox.java index 75f3ac7e..f7375452 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/AutoBox.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/AutoBox.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature; +package cn.lastwhisper; /** * jdk5新特性:自动拆箱与装箱 diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/StaticImport.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/StaticImport.java similarity index 92% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/StaticImport.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/StaticImport.java index 8a71fef9..b5cb690a 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/StaticImport.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/StaticImport.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature; +package cn.lastwhisper; import static java.lang.Math.abs; import static java.lang.Math.*; diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/VariableParameter.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/VariableParameter.java similarity index 96% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/VariableParameter.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/VariableParameter.java index 13dfc994..bcc1ffff 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/VariableParameter.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/VariableParameter.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature; +package cn.lastwhisper; /** * jdk5新特性:可变参数+增强for循环 diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/annotation/AnnotationTest.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/annotation/AnnotationTest.java new file mode 100644 index 00000000..13d7ef08 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/annotation/AnnotationTest.java @@ -0,0 +1,64 @@ +package cn.lastwhisper.annotation; + +import org.junit.Test; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; +import java.util.Arrays; +import java.util.Map; + +/** + * jdk5新特性:注解 + * + * @author lastwhisper + */ +public class AnnotationTest { + + @Test + public void test一个什么都有的注解() { + if (UseAnnotation.class.isAnnotationPresent(MyAnnotation.class)) { + MyAnnotation annotation = UseAnnotation.class.getAnnotation(MyAnnotation.class); + System.out.println(annotation.color()); + System.out.println(annotation.value()); + System.out.println(Arrays.toString(annotation.arrayAttr())); + System.out.println(annotation.annotation().value()); + System.out.println(annotation.clazz()); + System.out.println(annotation.enumLevel()); + } + } + + /** + * Changing Annotation Parameters At Runtime + *

+ * https://segmentfault.com/a/1190000011213222 + * + * @throws Exception + */ + @Test + public void test运行期动态修改注解value() throws Exception { + Class clazz = Class.forName("cn.lastwhisper.annotation.StudentRsp"); + //获取 StudentRsp 的 name 字段 + Field field = clazz.getDeclaredField("name"); + //获取 name 字段上的 JsonProperty 注解实例 + JsonProperty jsonProperty = field.getAnnotation(JsonProperty.class); + + System.out.println("当前 jsonProperty value:" + jsonProperty.value()); + + //获取 JsonProperty 这个代理实例所持有的 InvocationHandler + InvocationHandler invocationHandler = Proxy.getInvocationHandler(jsonProperty); + // 获取 AnnotationInvocationHandler 的 memberValues 字段 + Field hField = invocationHandler.getClass().getDeclaredField("memberValues"); + // 设置访问权限 + hField.setAccessible(true); + // 获取 memberValues + Map memberValues = (Map) hField.get(invocationHandler); + // 修改 value 属性值 + memberValues.put("value", "beisen_pro_name"); + + // 获取 JsonProperty 的 value 属性值 + System.out.println("当前 jsonProperty value:" + jsonProperty.value()); + + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/annotation/JsonProperty.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/annotation/JsonProperty.java new file mode 100644 index 00000000..d5f5c89c --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/annotation/JsonProperty.java @@ -0,0 +1,15 @@ +package cn.lastwhisper.annotation; + + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD}) +public @interface JsonProperty { + + String value(); + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/annotation/MyAnnotation.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/annotation/MyAnnotation.java new file mode 100644 index 00000000..80651e83 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/annotation/MyAnnotation.java @@ -0,0 +1,39 @@ +package cn.lastwhisper.annotation; + +// 自定义注解 + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +@Retention(RetentionPolicy.RUNTIME)//保留策略 +@Target({ElementType.METHOD, ElementType.TYPE})//作用目标 // 为什么是TYPE,因为Class的父类是Type +public @interface MyAnnotation { + // 八大基本数据类型、String、Class、Enum、注解类型对应的数组类型 + + String color() default "green"; + + String value();//value比较特殊 + + int[] arrayAttr() default {1, 2, 3}; + + Class clazz() default Formatter.class; + + Level enumLevel() default Level.GOOD; + + MetaAnnotation annotation() default @MetaAnnotation("xxx"); + +} + + +interface Formatter { +} + +@interface MetaAnnotation { + String value(); +} + +enum Level {BAD, INDIFFERENT, GOOD} + diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/annotation/StudentRsp.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/annotation/StudentRsp.java new file mode 100644 index 00000000..5cb199d4 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/annotation/StudentRsp.java @@ -0,0 +1,17 @@ +package cn.lastwhisper.annotation; + +/** + * @author cunchang + * @date 2021/4/19 8:02 下午 + */ +public class StudentRsp { + + /** + * stable beisen_test_name + * real beisen_pro_name + */ + @JsonProperty("beisen_test_name") + public String name; + + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/annotation/UseAnnotation.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/annotation/UseAnnotation.java new file mode 100644 index 00000000..804054d9 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/annotation/UseAnnotation.java @@ -0,0 +1,22 @@ +package cn.lastwhisper.annotation; + +/** + * @author lastwhisper + */ +@MyAnnotation(color = "red", value = "/user/login", + arrayAttr = {4, 5, 6}, enumLevel = Level.INDIFFERENT, + annotation = @MetaAnnotation("yyy"), clazz = Formatter.class) +public class UseAnnotation { + + @MyAnnotation("yyy") + @SuppressWarnings("deprecation") + public static void deprecatedFun() { + sayHello(); + } + + @Deprecated + public static void sayHello() { + System.out.println("被弃用的函数"); + } + +} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/enums/EnumTest.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/enums/EnumTest.java similarity index 92% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/enums/EnumTest.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/enums/EnumTest.java index 80af3a5b..db9424b8 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/enums/EnumTest.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/enums/EnumTest.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.enums; +package cn.lastwhisper.enums; import java.util.Arrays; @@ -72,7 +72,8 @@ public static void main(String[] args) { System.out.println(monday); System.out.println(monday.name()); System.out.println(monday.ordinal());// 下标 - System.out.println(WeekDay2.valueOf("Thursday"));// 静态方法 + // java.lang.Enum.valueOf 从map去拿性能不差的 + System.out.println(WeekDay2.valueOf("Thursday1"));// 静态方法 System.out.println(Arrays.toString(WeekDay2.values()));// 静态方法 } diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/enums/WeekDay.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/enums/WeekDay.java similarity index 97% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/enums/WeekDay.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/enums/WeekDay.java index 88bc0eab..00802dde 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/enums/WeekDay.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/enums/WeekDay.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.enums; +package cn.lastwhisper.enums; /** * 实现枚举功能 diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/enums/WeekDay1.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/enums/WeekDay1.java similarity index 97% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/enums/WeekDay1.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/enums/WeekDay1.java index 4da5e0a5..9a5b67c0 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/enums/WeekDay1.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/enums/WeekDay1.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.enums; +package cn.lastwhisper.enums; /** * 实现枚举功能 diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/equals/EqualsWithExtends.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/equals/EqualsWithExtends.java new file mode 100644 index 00000000..94816423 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/equals/EqualsWithExtends.java @@ -0,0 +1,55 @@ +package cn.lastwhisper.equals; + +class BaseClass { + private int x; + + public BaseClass(int i) { + x = i; + } + + // equals()的对等性被打破 + // public boolean equals(Object rhs) { +// if (!(rhs instanceof BaseClass)) +// return false; +// +// return x == ((BaseClass) rhs).x; +// } + + public boolean equals(Object rhs) { + // Class保证equlas的对等性 + if (rhs == null || getClass() != rhs.getClass()) + return false; + + return x == ((BaseClass) rhs).x; + } +} + +class DerivedClass extends BaseClass { + private int y; + + public DerivedClass(int i, int j) { + super(i); + y = j; + } + + public boolean equals(Object rhs) { + if (!(rhs instanceof DerivedClass)) + return false; + + return super.equals(rhs) && + y == ((DerivedClass) rhs).y; + } +} + +public class EqualsWithExtends { + public static void main(String[] args) { + BaseClass a = new BaseClass(5); + DerivedClass b = new DerivedClass(5, 8); + DerivedClass c = new DerivedClass(5, 8); + + System.out.println("b.equals(c): " + b.equals(c)); + // equals()的对等性被打破 + System.out.println("a.equals(b): " + a.equals(b)); + System.out.println("b.equals(a): " + b.equals(a)); + } +} \ No newline at end of file diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/HashCode.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/equals/HashCode.java similarity index 94% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/HashCode.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/equals/HashCode.java index e298511f..48031345 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/HashCode.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/equals/HashCode.java @@ -1,6 +1,6 @@ -package cn.lastwhisper.jdk5.feature; +package cn.lastwhisper.equals; -import cn.lastwhisper.jdk5.feature.reflect.ReflectPoint; +import cn.lastwhisper.reflect.ReflectPoint; import org.junit.Test; import java.util.*; @@ -51,7 +51,7 @@ public void testOverrideEquals() { Person p2 = new Person(1, "张三"); System.out.println(p1.equals(p2));//true - Map map = new HashMap<>(); + Map map = new HashMap(); map.put(p1, "张三"); System.out.println(map.get(p2)); diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/exception/ErrorAndException.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/exception/ErrorAndException.java new file mode 100644 index 00000000..01834525 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/exception/ErrorAndException.java @@ -0,0 +1,53 @@ +package cn.lastwhisper.exception; + +import java.io.FileNotFoundException; + +/** + * 异常 + * Error + * Exception + * RuntimeException + * + * @author lastwhisper + */ +public class ErrorAndException { + // Error + private void throwError(){ + throw new StackOverflowError(); + } + + /** + * uncheck exception + * (1)RuntimeException 的子类 + * (2)在方法签名上可以不显示声明 throws *Exception + * (3)调用方可以不 try/catch ,或者 throws *Exception + * 比如:NullPointerException + * + */ + private void throwRuntimeException(){ + throw new NullPointerException(); + } + + /** + * check exception + * (1)非 RuntimeException 的子类 + * (2)在方法签名上必须显示声明 throws *Exception + * (3)调用方必须 try/catch ,或者 throws *Exception + * 比如:FileNotFoundException + */ + private void throwCheckedException() throws FileNotFoundException { + throw new FileNotFoundException(); + } + + public static void main(String[] args) { + ErrorAndException errorAndException = new ErrorAndException(); + errorAndException.throwError(); + errorAndException.throwRuntimeException(); + // 受检查异常,声明throws FileNotFoundException或者try/catch + try { + errorAndException.throwCheckedException(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } +} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic1.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic1.java similarity index 97% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic1.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic1.java index 4ad7fe9e..4bfc3489 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic1.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic1.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.generic; +package cn.lastwhisper.generic; import java.util.ArrayList; import java.util.Collection; diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic2.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic2.java similarity index 97% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic2.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic2.java index ab5310ed..6602709b 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic2.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic2.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.generic; +package cn.lastwhisper.generic; import java.util.Arrays; diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic3.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic3.java similarity index 96% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic3.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic3.java index f9a9b0ec..573691e6 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic3.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic3.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.generic; +package cn.lastwhisper.generic; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/BaseDao.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/BaseDao.java similarity index 86% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/BaseDao.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/BaseDao.java index 989a8127..37002119 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/BaseDao.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/BaseDao.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.generic.Generic4; +package cn.lastwhisper.generic.Generic4; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/BaseDaoImpl.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/BaseDaoImpl.java similarity index 96% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/BaseDaoImpl.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/BaseDaoImpl.java index 11470148..261eae36 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/BaseDaoImpl.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/BaseDaoImpl.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.generic.Generic4; +package cn.lastwhisper.generic.Generic4; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/Client.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/Client.java new file mode 100644 index 00000000..b762bdbf --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/Client.java @@ -0,0 +1,18 @@ +package cn.lastwhisper.generic.Generic4; + +/** + * 该层模拟service + * @author lastwhisper + */ +public class Client { + public static void main(String[] args) { + Person person = new Person(); + person.setId(1L); + person.setName("张三"); + // 交给Spring的IOC容器管理 + PersonDao personDao = new PersonDaoImpl(); + // 持久化到数据库 + personDao.save(person); + + } +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/Person.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/Person.java new file mode 100644 index 00000000..cf42d9d8 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/Person.java @@ -0,0 +1,40 @@ +package cn.lastwhisper.generic.Generic4; + +public class Person { + + // 编号 + private Long id; + + // 姓名 + private String name; + + public Person() { + } + + public Person(Long id, String name) { + this.id = id; + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "Person [id=" + id + ", name=" + name + "]"; + } + +} \ No newline at end of file diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/PersonDao.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/PersonDao.java new file mode 100644 index 00000000..9ecb5017 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/PersonDao.java @@ -0,0 +1,8 @@ +package cn.lastwhisper.generic.Generic4; + +/** + * extends BaseDao是为了可以使用通用的方法 + * @author lastwhisper + */ +public interface PersonDao extends BaseDao { +} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/PersonDaoImpl.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/PersonDaoImpl.java similarity index 85% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/PersonDaoImpl.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/PersonDaoImpl.java index ff1c064f..9ca57f70 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/PersonDaoImpl.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/generic/Generic4/PersonDaoImpl.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.generic.Generic4; +package cn.lastwhisper.generic.Generic4; /** * extends BaseDaoImpl让通用模板知道你的泛型参数是啥,并且可以使用通用的方法 diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/introspection/IntrospectorTest.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/introspection/IntrospectorTest.java similarity index 98% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/introspection/IntrospectorTest.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/introspection/IntrospectorTest.java index af5a65f9..7c51edea 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/introspection/IntrospectorTest.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/introspection/IntrospectorTest.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.introspection; +package cn.lastwhisper.introspection; import java.beans.BeanInfo; import java.beans.Introspector; diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/introspection/Point.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/introspection/Point.java similarity index 93% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/introspection/Point.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/introspection/Point.java index c76654ce..2ab6ebb0 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/introspection/Point.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/introspection/Point.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.introspection; +package cn.lastwhisper.introspection; /** * JavaBean diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/PropertiesDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/PropertiesDemo.java new file mode 100644 index 00000000..138dba32 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/PropertiesDemo.java @@ -0,0 +1,148 @@ +package cn.lastwhisper.io.io; + +import org.junit.Test; + +import java.io.*; +import java.util.Properties; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +public class PropertiesDemo { + + private static final String DEFAULT_ENCODING = "UTF-8"; + + /** + * 使用java.util.Properties类的load()方法加载properties文件 + */ + @Test + public void testLoad1() { + try { + // 获取文件流(方法1或2均可) + InputStream inputStream = new BufferedInputStream(new FileInputStream(new File("src/main/resources/config.properties"))); //方法1 +// InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("config.properties"); //方法2 + + Properties prop = new Properties(); + prop.load(new InputStreamReader(inputStream, DEFAULT_ENCODING)); //加载格式化后的流 + + String targetDirs = prop.getProperty("targetDirs"); + String deleteDirs = prop.getProperty("deleteDirs"); + String deleteFiles = prop.getProperty("deleteFiles"); + System.out.println("targetDirs: " + targetDirs); + System.out.println("deleteDirs: " + deleteDirs); + System.out.println("deleteFiles: " + deleteFiles); + + } catch (FileNotFoundException e) { + System.out.println("properties文件路径有误!"); + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 使用class变量的getResourceAsStream()方法 + * 注意:getResourceAsStream()方法的参数路径/包路径+properties文件名+.后缀 + */ + @Test + public void testLoad2() { + try { + InputStream inputStream = PropertiesDemo.class.getResourceAsStream("/config.properties"); + + Properties prop = new Properties(); + prop.load(inputStream); + + String targetDirs = prop.getProperty("targetDirs"); + String deleteDirs = prop.getProperty("deleteDirs"); + String deleteFiles = prop.getProperty("deleteFiles"); + System.out.println("targetDirs: " + targetDirs); + System.out.println("deleteDirs: " + deleteDirs); + System.out.println("deleteFiles: " + deleteFiles); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 使用class.getClassLoader()所得到的java.lang.ClassLoader的getResourceAsStream()方法 + * 注意:getResourceAsStream(name)方法的参数必须是包路径+文件名+.后缀 + */ + @Test + public void testLoad3() { + try { + InputStream inputStream = PropertiesDemo.class.getClassLoader().getResourceAsStream("config.properties"); + + Properties prop = new Properties(); + prop.load(inputStream); + + String targetDirs = prop.getProperty("targetDirs"); + String deleteDirs = prop.getProperty("deleteDirs"); + String deleteFiles = prop.getProperty("deleteFiles"); + System.out.println("targetDirs: " + targetDirs); + System.out.println("deleteDirs: " + deleteDirs); + System.out.println("deleteFiles: " + deleteFiles); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 使用java.lang.ClassLoader类的getSystemResourceAsStream()静态方法 + * getSystemResourceAsStream()方法的参数必须是包路径+文件名+.后缀 + */ + @Test + public void testLoad4() { + try { + InputStream inputStream = ClassLoader.getSystemResourceAsStream("config.properties"); + + Properties prop = new Properties(); + prop.load(inputStream); + + String targetDirs = prop.getProperty("targetDirs"); + String deleteDirs = prop.getProperty("deleteDirs"); + String deleteFiles = prop.getProperty("deleteFiles"); + System.out.println("targetDirs: " + targetDirs); + System.out.println("deleteDirs: " + deleteDirs); + System.out.println("deleteFiles: " + deleteFiles); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 使用java.util.ResourceBundle类的getBundle()方法 + * 注意:注意:这个getBundle()方法的参数相对同目录路径,并去掉.properties后缀,否则将抛异常 + */ + @Test + public void testLoad5() { + ResourceBundle resource = ResourceBundle.getBundle("config"); + + String targetDirs = resource.getString("targetDirs"); + String deleteDirs = resource.getString("deleteDirs"); + String deleteFiles = resource.getString("deleteFiles"); + System.out.println("targetDirs: " + targetDirs); + System.out.println("deleteDirs: " + deleteDirs); + System.out.println("deleteFiles: " + deleteFiles); + } + + /** + * 使用java.util.PropertyResourceBundle类的构造函数 + */ + public static void Method6() { + ResourceBundle resource; + try { + InputStream inputStream = new BufferedInputStream(new FileInputStream(new File("src/main/resources/demo/config.properties"))); + resource = new PropertyResourceBundle(inputStream); + + String driverClassName = resource.getString("driverClassName"); + System.out.println("Method6: " + driverClassName); + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/StringCodingDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/StringCodingDemo.java new file mode 100644 index 00000000..1e29817c --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/StringCodingDemo.java @@ -0,0 +1,57 @@ +package cn.lastwhisper.io.io; + +import org.junit.Test; + +import java.util.Arrays; + + +public class StringCodingDemo { + + /* + * 计算机是如何识别什么时候该把两个字节转换为一个中文呢? + * 在计算机中中文的存储分两个字节: + * 第一个字节肯定是负数。 + * 第二个字节常见的是负数,可能有正数。但是没影响。 + */ + @Test + public void testDoubleByte() { + String s1 = "abcde"; + // [97, 98, 99, 100, 101] + + String s2 = "我爱你中国"; + // [-26, -120, -111, -25, -120, -79, -28, -67, -96, -28, -72, -83, -27, -101, -67] + + System.out.println(Arrays.toString(s1.getBytes())); + System.out.println(Arrays.toString(s2.getBytes())); + } + + /** + * 字符编码解码 + * + * String(byte[] bytes, String charsetName):通过指定的字符集解码字节数组 + * byte[] getBytes(String charsetName):使用指定的字符集合把字符串编码为字节数组 + * + * 编码:把看得懂的变成看不懂的 + * String -- byte[] + * + * 解码:把看不懂的变成看得懂的 + * byte[] -- String + */ + @Test + public void testCode() { + String s = "你好"; + + // String -- byte[] + byte[] bys = s.getBytes(); //默认GBK [-60, -29, -70, -61] + // byte[] bys = s.getBytes("GBK");// [-60, -29, -70, -61] + // byte[] bys = s.getBytes("UTF-8");// [-28, -67, -96, -27, -91, -67] + System.out.println(Arrays.toString(bys)); + + // byte[] -- String + String ss = new String(bys); // 你好 + // String ss = new String(bys, "GBK"); // 你好 + // String ss = new String(bys, "UTF-8"); // ??? + System.out.println(ss); + } + +} \ No newline at end of file diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/bytestream/BufferedInputStreamDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/bytestream/BufferedInputStreamDemo.java new file mode 100644 index 00000000..7e44964d --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/bytestream/BufferedInputStreamDemo.java @@ -0,0 +1,33 @@ +package cn.lastwhisper.io.io.bytestream; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; + +/** + * + * @author lastwhisper + * @date 2020/6/13 + */ +public class BufferedInputStreamDemo { + + public static void main(String[] args) throws IOException { + BufferedInputStream bis = new BufferedInputStream( + new FileInputStream("D:\\a.txt")); + + // 中文乱码 + //int by; + //while ((by = bis.read()) != -1) { + //System.out.print((char) by); + //} + + byte[] buffer = new byte[1024]; + int len; + while ((len = bis.read(buffer)) != -1) { + System.out.print(new String(buffer, 0, len)); + } + // 释放资源 + bis.close(); + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/bytestream/BufferedOutputStreamDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/bytestream/BufferedOutputStreamDemo.java new file mode 100644 index 00000000..2e6216a9 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/bytestream/BufferedOutputStreamDemo.java @@ -0,0 +1,38 @@ +package cn.lastwhisper.io.io.bytestream; + +import java.io.BufferedOutputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * + * @author lastwhisper + * @date 2020/6/13 + */ +public class BufferedOutputStreamDemo { + + /* + * 通过定义数组的方式确实比以前一次读取一个字节的方式快很多,所以,看来有一个缓冲区还是非常好的。 + * 既然是这样的话,那么,java开始在设计的时候,它也考虑到了这个问题,就专门提供了带缓冲区的字节类。 + * 这种类被称为:缓冲区类(高效类) + * 写数据:BufferedOutputStream + * 读数据:BufferedInputStream + * + * 构造方法可以指定缓冲区的大小,但是我们一般用不上,因为默认缓冲区大小就足够了。 + * + * 为什么不传递一个具体的文件或者文件路径,而是传递一个OutputStream对象呢? + * 原因很简单,字节缓冲区流仅仅提供缓冲区,为高效而设计的。但是呢,真正的读写操作还得靠基本的流对象实现。 + */ + + public static void main(String[] args) throws IOException { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream("bos.txt")); + + // 写数据 + bos.write("hello".getBytes()); + + // 释放资源 + bos.close(); + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/bytestream/FileInputStreamDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/bytestream/FileInputStreamDemo.java new file mode 100644 index 00000000..50df8abf --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/bytestream/FileInputStreamDemo.java @@ -0,0 +1,56 @@ +package cn.lastwhisper.io.io.bytestream; + +import org.junit.Test; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * + * @author lastwhisper + * @date 2020/6/13 + */ +public class FileInputStreamDemo { + + /* + * 字节输入流操作步骤: + * A:创建字节输入流对象 + * B:调用read()方法读取数据,并把数据显示在控制台 + * C:释放资源 + * + * 读取数据的方式: + * A:int read():一次读取一个字节 + * B:int read(byte[] b):一次读取一个字节数组 + */ + @Test + public void testByteRead() throws IOException { + // 1、创建字节输入流对象 + InputStream is = new FileInputStream("fos.txt"); + // 2、调用read()方法读取数据 + // 一个字节一个字节的读,中文表示需要两个字节,会乱码 + int by; + while ((by = is.read()) != -1) { + System.out.print((char)by); + } + // 3、释放资源 + is.close(); + } + + @Test + public void testBufferRead() throws IOException { + // 1、创建字节输入流对象 + InputStream is = new FileInputStream("fos.txt"); + // 2、调用read()方法读取数据 + // 通过字节数组缓冲区,优化性能 + int len; + byte[] buffer = new byte[1024]; + while ((len = is.read(buffer)) != -1) { + System.out.println(new String(buffer, 0, len)); + } + // 3、释放资源 + is.close(); + } + + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/bytestream/FileOutputStreamDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/bytestream/FileOutputStreamDemo.java new file mode 100644 index 00000000..a0873540 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/bytestream/FileOutputStreamDemo.java @@ -0,0 +1,75 @@ +package cn.lastwhisper.io.io.bytestream; + +import org.junit.Test; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * @author lastwhisper + * @date 2020/6/13 + */ +public class FileOutputStreamDemo { + + /* + * IO流的分类: + * 流向: + * 输入流 读取数据 + * 输出流 写出数据 + * 数据类型: + * 字节流 + * 字节输入流 读取数据 InputStream + * 字节输出流 写出数据 OutputStream + * 字符流 + * 字符输入流 读取数据 Reader + * 字符输出流 写出数据 Writer + * + * 字节输出流操作步骤: + * A:创建字节输出流对象 + * B:写数据 + * C:释放资源 + */ + + @Test + public void testWrite() throws IOException { + // 1、创建字节输出流 + /* + * 创建字节输出流对象了做了几件事情: + * A:调用系统功能去创建文件 + * B:创建FileOutputStream对象 + * C:把FileOutputStream对象指向这个文件 + */ + File file = new File("fos.txt"); + OutputStream os = new FileOutputStream(file); + //OutputStream os = new FileOutputStream("fos.txt"); + // 2、向字节输出流写入字节流 + os.write("hello java IO\n".getBytes()); + os.write("hello python IO".getBytes()); + // 3、释放资源 + /* + * 为什么一定要close()呢? + * A:让流对象变成垃圾,这样就可以被垃圾回收器回收了 + * B:通知系统去释放跟该文件相关的资源 + */ + os.close(); + //java.io.IOException: Stream Closed + //os.write("java".getBytes()); + } + + @Test + public void testWriteAppend() throws IOException { + //1、创建字节输出流,追加写入数据 + OutputStream os = new FileOutputStream("fos.txt",true); + // 2、向字节输出流写入字节流 + os.write(97); + byte[] bytes={97,98,99,100,101}; + os.write(bytes); + os.write(bytes,1,3); + // 3、释放资源 + os.close(); + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/bytestream/IOByteStreamCopyFile.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/bytestream/IOByteStreamCopyFile.java new file mode 100644 index 00000000..850622b9 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/bytestream/IOByteStreamCopyFile.java @@ -0,0 +1,55 @@ +package cn.lastwhisper.io.io.bytestream; + +import org.junit.Test; + +import java.io.*; + +/** + * + * 字节流四种方式复制文件: + * 基本字节流一次读写一个字节: 共耗时:117235毫秒 + * 基本字节流一次读写一个字节数组: 共耗时:156毫秒 + * 高效字节流一次读写一个字节: 共耗时:1141毫秒 + * 高效字节流一次读写一个字节数组: 共耗时:47毫秒 + * + * @author lastwhisper + * @date 2020/6/13 + */ +public class IOByteStreamCopyFile { + + @Test + public void testByteCopy() throws IOException { + // 封装数据源 + InputStream fis = new FileInputStream("D:\\a.txt"); + // 封装目的地 + OutputStream fos = new FileOutputStream("D:\\b.txt"); + + // 一个字节一个字节的复制 + int by; + while ((by = fis.read()) != -1) { + fos.write(by); + } + // 释放资源(先关谁都行) + fos.close(); + fis.close(); + } + + @Test + public void testByteBufferCopy() throws IOException { + // 封装数据源 + InputStream fis = new FileInputStream("D:\\a.txt"); + // 封装目的地 + OutputStream fos = new FileOutputStream("D:\\b.txt"); + + // 复制数据 + byte[] buffer = new byte[1024]; + int len; + while ((len = fis.read(buffer)) != -1) { + fos.write(buffer, 0, len); + } + // 释放资源(先关谁都行) + fos.close(); + fis.close(); + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/BufferedReaderDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/BufferedReaderDemo.java new file mode 100644 index 00000000..a35164b9 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/BufferedReaderDemo.java @@ -0,0 +1,54 @@ +package cn.lastwhisper.io.io.charstream; + +import org.junit.Test; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; + +/** + * + * @author lastwhisper + * @date 2020/6/14 + */ +public class BufferedReaderDemo { + + @Test + public void testCharRead() throws IOException { + // 1、创建字符缓冲输入流对象 + BufferedReader br = new BufferedReader(new FileReader("bw.txt")); + + // 2、读输入流 + // 方式1 + // int ch = 0; + // while ((ch = br.read()) != -1) { + // System.out.print((char) ch); + // } + + // 方式2 + char[] chars = new char[1024]; + int len; + while ((len = br.read(chars)) != -1) { + System.out.print(new String(chars, 0, len)); + } + + // 3、释放资源 + br.close(); + } + + + @Test + public void testCharRead2() throws IOException { + BufferedReader br = new BufferedReader(new FileReader("bw2.txt")); + + // 最终版代码 + String line; + while ((line = br.readLine()) != null) { + System.out.println(line); + } + + //释放资源 + br.close(); + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/BufferedWriterDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/BufferedWriterDemo.java new file mode 100644 index 00000000..45db1ddd --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/BufferedWriterDemo.java @@ -0,0 +1,55 @@ +package cn.lastwhisper.io.io.charstream; + +import org.junit.Test; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; + +/** + * + * @author lastwhisper + * @date 2020/6/14 + */ +public class BufferedWriterDemo { + + /* + * 字符流为了高效读写,也提供了对应的字符缓冲流。 + * BufferedWriter:字符缓冲输出流 + * BufferedReader:字符缓冲输入流 + * + * BufferedWriter:字符缓冲输出流 + * 将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。 + * 可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。 + */ + @Test + public void testCharBufferWrite() throws IOException { + // 1、创建字符缓冲输出流 + // BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( + // new FileOutputStream("bw.txt"))); + BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt")); + + // 2、写入缓冲区 + bw.write("hello"); + bw.write("world"); + bw.write("java\n"); + bw.write("java 牛逼"); + bw.flush(); + + // 3、关闭流 + bw.close(); + } + + @Test + public void testCharBufferWrite2() throws IOException { + BufferedWriter bw = new BufferedWriter(new FileWriter("bw2.txt")); + for (int x = 0; x < 10; x++) { + bw.write("hello" + x); + // bw.write("\r\n"); + bw.newLine(); + bw.flush(); + } + bw.close(); + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/IOCharBufferStreamCopyFile.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/IOCharBufferStreamCopyFile.java new file mode 100644 index 00000000..c2dff14c --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/IOCharBufferStreamCopyFile.java @@ -0,0 +1,55 @@ +package cn.lastwhisper.io.io.charstream; + +import org.junit.Test; + +import java.io.*; + +/** + * + * @author lastwhisper + * @date 2020/6/14 + */ +public class IOCharBufferStreamCopyFile { + + @Test + public void testCharBufferCopy() throws IOException { + // 封装数据源 + BufferedReader br = new BufferedReader(new FileReader("a.txt")); + // 封装目的地 + BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt")); + + // 两种方式其中的一种一次读写一个字符数组 + char[] chars = new char[1024]; + int len ; + while ((len = br.read(chars)) != -1) { + bw.write(chars, 0, len); + bw.flush(); + } + + // 释放资源 + bw.close(); + br.close(); + } + + @Test + public void testCharBufferCopy2() throws IOException { + // 封装数据源 + BufferedReader br = new BufferedReader(new FileReader("a.txt")); + // 封装目的地 + BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt")); + + // 读写数据 + String line; + while ((line = br.readLine()) != null) { + bw.write(line); + bw.newLine(); + bw.flush(); + } + + // 释放资源 + bw.close(); + br.close(); + } + + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/IOCharStreamCopyFile.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/IOCharStreamCopyFile.java new file mode 100644 index 00000000..f0c17ae1 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/IOCharStreamCopyFile.java @@ -0,0 +1,74 @@ +package cn.lastwhisper.io.io.charstream; + +import org.junit.Test; + +import java.io.*; + +/** + * + * @author lastwhisper + * @date 2020/6/14 + */ +public class IOCharStreamCopyFile { + + @Test + public void testCharCopy() throws IOException { + // 1、创建字符输入输出流 + InputStreamReader isr = new InputStreamReader(new FileInputStream("d:\\a.txt")); + OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:\\b.txt")); + + // 2、将字符输入流的数据读出来,写到字符输出流中 + // 一个字符一个字符的读写 + //int ch; + //while ((ch = isr.read()) != -1) { + // osw.write(ch); + //} + + int len; + char[] cbuf = new char[1024]; + while ((len = isr.read(cbuf)) != -1) { + osw.write(cbuf, 0, len); + } + + // 3、关闭流 + osw.close(); + isr.close(); + } + + /* + * 由于我们常见的操作都是使用本地默认编码,所以,不用指定编码。 + * 而转换流的名称有点长,所以,Java就提供了其子类供我们使用。 + * OutputStreamWriter = FileOutputStream + 编码表(GBK) + * FileWriter = FileOutputStream + 编码表(GBK) + * + * InputStreamReader = FileInputStream + 编码表(GBK) + * FileReader = FileInputStream + 编码表(GBK) + * + */ + @Test + public void testFileRWCopy() throws IOException { + // 1、创建字符输入输出流 + FileReader fr = new FileReader("d:\\a.txt"); + FileWriter fw = new FileWriter("d:\\b.txt"); + + // 一次一个字符 + // int ch = 0; + // while ((ch = fr.read()) != -1) { + // fw.write(ch); + // } + + // 一次一个字符数组 + char[] chs = new char[1024]; + int len = 0; + while ((len = fr.read(chs)) != -1) { + fw.write(chs, 0, len); + fw.flush(); + } + + // 释放资源 + fw.close(); + fr.close(); + } + + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/InputStreamReaderDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/InputStreamReaderDemo.java new file mode 100644 index 00000000..a2502d4b --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/InputStreamReaderDemo.java @@ -0,0 +1,63 @@ +package cn.lastwhisper.io.io.charstream; + +import org.junit.Test; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * + * @author lastwhisper + * @date 2020/6/14 + */ +public class InputStreamReaderDemo { + + + /* + * InputStreamReader的方法: + * int read():一次读取一个字符 + * int read(char[] chs):一次读取一个字符数组 + */ + @Test + public void testCharRead() throws IOException { + // 1、创建字符输入流 + // InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt")); + + // InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"), "GBK"); + InputStreamReader isr = new InputStreamReader( + new FileInputStream("osw.txt"), "UTF-8"); + + // 2、写入数据 + // 一次读取一个字符 + int ch; + while ((ch = isr.read()) != -1) { + System.out.print((char) ch); + } + + // 3、释放资源 + isr.close(); + } + + @Test + public void testCharBufferRead() throws IOException { + // 1、创建字符输入流 + // InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt")); + + // InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"), "GBK"); + InputStreamReader isr = new InputStreamReader( + new FileInputStream("osw.txt"), "UTF-8"); + + // 2、写入数据 + // 一次读取一个字符数组 + char[] chars = new char[1024]; + int len; + while ((len = isr.read(chars)) != -1) { + System.out.print(new String(chars, 0, len)); + } + + // 3、释放资源 + isr.close(); + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/OutputStreamWriterDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/OutputStreamWriterDemo.java new file mode 100644 index 00000000..ecaf2556 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/OutputStreamWriterDemo.java @@ -0,0 +1,86 @@ +package cn.lastwhisper.io.io.charstream; + +import org.junit.Test; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; + +/** + * + * @author lastwhisper + * @date 2020/6/14 + */ +public class OutputStreamWriterDemo { + + /* + * OutputStreamWriter(OutputStream out):根据默认编码把字节流的数据转换为字符流 + * OutputStreamWriter(OutputStream out,String charsetName):根据指定编码把字节流数据转换为字符流 + * 把字节流转换为字符流。 + * 字符流 = 字节流 +编码表。 + */ + @Test + public void testWriteCoding() throws IOException { + // 1、创建字符输出流 + // OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream( + // "osw.txt")); // 默认GBK + // OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream( + // "osw.txt"), "GBK"); // 指定GBK + OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream( + "osw.txt"), "UTF-8"); // 指定UTF-8 + // 2、写数据 + osw.write("中国"); + // 3、 释放资源 + osw.close(); + } + + /* + * OutputStreamWriter的方法: + * public void write(int c):写一个字符 + * public void write(char[] cbuf):写一个字符数组 + * public void write(char[] cbuf,int off,int len):写一个字符数组的一部分 + * public void write(String str):写一个字符串 + * public void write(String str,int off,int len):写一个字符串的一部分 + * + * 面试题:close()和flush()的区别? + * A:close()关闭流对象,但是先刷新一次缓冲区。关闭之后,流对象不可以继续再使用了。 + * B:flush()仅仅刷新缓冲区,刷新之后,流对象还可以继续使用。 + */ + @Test + public void testWriteChar() throws IOException { + // 1、创建字符输出流 + OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw2.txt")); + + // 2、写数据 + // public void write(int c):写一个字符 + // osw.write('a'); + // osw.write(97); + // 为什么数据没有进去呢? + // 原因是:字符 = 2字节 + // 文件中数据存储的基本单位是字节。 + // void flush() + + // public void write(char[] cbuf):写一个字符数组 + // char[] chs = {'a','b','c','d','e'}; + // osw.write(chs); + + // public void write(char[] cbuf,int off,int len):写一个字符数组的一部分 + // osw.write(chs,1,3); + + // public void write(String str):写一个字符串 + // osw.write("我爱林青霞"); + + // public void write(String str,int off,int len):写一个字符串的一部分 + osw.write("我爱林青霞", 2, 3); + + // 刷新缓冲区 + osw.flush(); + // osw.write("我爱林青霞", 2, 3); + + // 3、释放资源 + osw.close(); + // java.io.IOException: Stream closed + // osw.write("我爱林青霞", 2, 3); + } + +} \ No newline at end of file diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/other/LineNumberReaderDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/other/LineNumberReaderDemo.java new file mode 100644 index 00000000..9462d557 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/charstream/other/LineNumberReaderDemo.java @@ -0,0 +1,34 @@ +package cn.lastwhisper.io.io.charstream.other; + +import java.io.FileReader; +import java.io.IOException; +import java.io.LineNumberReader; + +/** + * + * @author lastwhisper + * @date 2020/6/14 + */ +public class LineNumberReaderDemo { + + /* + * BufferedReader + * |--LineNumberReader + * public int getLineNumber()获得当前行号。 + * public void setLineNumber(int lineNumber) + */ + public static void main(String[] args) throws IOException { + LineNumberReader lnr = new LineNumberReader(new FileReader("d:\\a.txt")); + + // 行号从10开始 + lnr.setLineNumber(10); + + String line; + while ((line = lnr.readLine()) != null) { + System.out.println(lnr.getLineNumber() + " : " + line); + } + + lnr.close(); + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/file/FileDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/file/FileDemo.java new file mode 100644 index 00000000..14e11a7a --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/file/FileDemo.java @@ -0,0 +1,142 @@ +package cn.lastwhisper.io.io.file; + +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * File API + * @author lastwhisper + * @date 2020/6/13 + */ +public class FileDemo { + + /* + * 我们要想实现IO的操作,就必须知道硬盘上文件的表现形式。 + * 而Java就提供了一个类File供我们使用。 + * + * File:文件和目录(文件夹)路径名的抽象表示形式 + */ + @Test + public void testConstructor() { + // Creates a new File instance by converting the given pathname string into an abstract pathname. + File file1 = new File("D:\\demo\\a.txt"); + // Creates a new File instance from a parent pathname string and a child pathname string. + File file2 = new File("D:\\demo\\", "a.txt"); + // Creates a new File instance from a parent abstract pathname and a child pathname string. + File file3 = new File("D:\\demo\\"); + File file4 = new File(file3, "a.txt"); + } + + /** + * 文件以及文件夹创建 + */ + @Test + public void testCreate() throws IOException { + File file1 = new File("D:\\demo"); + System.out.println("mkdir:" + file1.mkdir()); + + File file2 = new File(file1, "a.txt"); + System.out.println("ctfile:" + file2.createNewFile()); + + // java.io.IOException: 系统找不到指定的路径。 + // file 的创建,建立在dir的基础下 + //File file3 = new File("D:\\test\\b.txt"); + //System.out.println("ctfile:" + file3.createNewFile()); + + // dir 的创建,建立在dir的基础下 + File file4 = new File("D:\\dir1\\dir2"); + System.out.println("mkdir:" + file4.mkdirs()); + } + + /** + * 文件以及文件夹删除 + * 1、要删除一个文件夹,请注意该文件夹内不能包含文件或者文件夹 + * 2、Java中的删除不走回收站 + */ + @Test + public void testDelete() throws IOException { + File file1 = new File("D:\\a.txt"); + System.out.println("ctfile:" + file1.createNewFile()); + System.out.println("delete:" + file1.delete()); + } + + /* + * 重命名功能:public boolean renameTo(File dest) + * 如果路径名相同,就是改名。 + * 如果路径名不同,就是改名并剪切。 + * + * 路径以盘符开始:绝对路径 c:\\a.txt + * 路径不以盘符开始:相对路径 a.txt + */ + @Test + public void testRename() throws IOException { + // 需求:我要修改这个文件的名称为"b.txt" + // File file = new File("D:\\a.txt"); + // File newFile = new File("D:\\b.txt"); + // System.out.println("renameTo:" + file.renameTo(newFile)); + + File file2 = new File("D:\\a.txt"); + File newFile2 = new File("D:\\b.txt"); + System.out.println("renameTo:" + file2.renameTo(newFile2)); + } + + /* + * 文件权限 + */ + @Test + public void testSecurity() throws IOException { + File file = new File("D:\\a.txt"); + if(!file.exists()){ + file.createNewFile(); + } + System.out.println("判断是否是目录:" + file.isDirectory());// false + System.out.println("判断是否是文件:" + file.isFile());// true + System.out.println("判断是否存在:" + file.exists());// true + System.out.println("判断是否可读:" + file.canRead());// true + System.out.println("判断是否可写:" + file.canWrite());// true + System.out.println("判断是否隐藏:" + file.isHidden());// false + } + + /* + * 文件详情 + */ + @Test + public void testFindDetail() throws IOException { + File file = new File("D:\\a.txt"); + System.out.println("获取绝对路径:" + file.getAbsolutePath()); + System.out.println("获取相对路径:" + file.getPath()); + System.out.println("获取名称:" + file.getName()); + System.out.println("获取字节数:" + file.length()); + System.out.println("获取最后一次的修改时间:" + file.lastModified()); + + // 1592035972157 + Date d = new Date(1592035972157L); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String s = sdf.format(d); + System.out.println(s); + } + + /** + * 文件相关信息 + */ + @Test + public void testList(){ + File file = new File("d:\\"); + // public String[] list():获取指定目录下的所有文件或者文件夹的名称数组 + String[] strArray = file.list(); + for (String s : strArray) { + System.out.println(s); + } + System.out.println("------------"); + // public File[] listFiles():获取指定目录下的所有文件或者文件夹的File数组 + File[] fileArray = file.listFiles(); + for (File f : fileArray) { + System.out.println(f.getName()); + } + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/ByteArrayStreamDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/ByteArrayStreamDemo.java new file mode 100644 index 00000000..16267a48 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/ByteArrayStreamDemo.java @@ -0,0 +1,52 @@ +package cn.lastwhisper.io.io.otherstream; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * + * @author lastwhisper + * @date 2020/6/14 + */ +public class ByteArrayStreamDemo { + + /* + * 内存操作流:用于处理临时存储信息的,程序结束,数据就从内存中消失。 + * 字节数组: + * ByteArrayInputStream + * ByteArrayOutputStream + * 字符数组: + * CharArrayReader + * CharArrayWriter + * 字符串: + * StringReader + * StringWriter + */ + public static void main(String[] args) throws IOException { + // 写数据 + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + // 写数据 + for (int x = 0; x < 10; x++) { + baos.write(("hello" + x).getBytes()); + } + + // 释放资源,内存操作流不需要释放资源 + baos.close(); + + byte[] bys = baos.toByteArray(); + + // 读数据 + ByteArrayInputStream bais = new ByteArrayInputStream(bys); + + int by; + while ((by = bais.read()) != -1) { + System.out.print((char) by); + } + + bais.close(); + + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/DataStreamDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/DataStreamDemo.java new file mode 100644 index 00000000..d9f57fdc --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/DataStreamDemo.java @@ -0,0 +1,67 @@ +package cn.lastwhisper.io.io.otherstream; + +import org.junit.Test; + +import java.io.*; + +/** + * @author lastwhisper + * @date 2020/6/14 + */ +public class DataStreamDemo { + + /** + * 可以读写基本数据类型的数据 + * 数据输入流:DataInputStream + * DataInputStream(InputStream in) + * 数据输出流:DataOutputStream + * DataOutputStream(OutputStream out) + */ + @Test + public void testWrite() throws IOException { + // 创建数据输出流对象 + DataOutputStream dos = new DataOutputStream(new FileOutputStream("dos.txt")); + + // 写数据了 + dos.writeByte(10); + dos.writeShort(100); + dos.writeInt(1000); + dos.writeLong(10000); + dos.writeFloat(12.34F); + dos.writeDouble(12.56); + dos.writeChar('a'); + dos.writeBoolean(true); + + // 释放资源 + dos.close(); + } + + @Test + public void testRead() throws IOException { + // 创建数据输入流对象 + DataInputStream dis = new DataInputStream(new FileInputStream("dos.txt")); + + // 读数据 + byte b = dis.readByte(); + short s = dis.readShort(); + int i = dis.readInt(); + long l = dis.readLong(); + float f = dis.readFloat(); + double d = dis.readDouble(); + char c = dis.readChar(); + boolean bb = dis.readBoolean(); + + // 释放资源 + dis.close(); + + System.out.println(b); + System.out.println(s); + System.out.println(i); + System.out.println(l); + System.out.println(f); + System.out.println(d); + System.out.println(c); + System.out.println(bb); + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/ObjectStreamDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/ObjectStreamDemo.java new file mode 100644 index 00000000..77b8be02 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/ObjectStreamDemo.java @@ -0,0 +1,49 @@ +package cn.lastwhisper.io.io.otherstream; + +import org.junit.Test; + +import java.io.*; + +/** + * + * @author lastwhisper + * @date 2020/6/14 + */ +public class ObjectStreamDemo { + + /* + * 序列化流:把对象按照流一样的方式存入文本文件或者在网络中传输。对象 -- 流数据(ObjectOutputStream) + * 反序列化流:把文本文件中的流对象数据或者网络中的流对象数据还原成对象。流数据 -- 对象(ObjectInputStream) + */ + @Test + public void testObjectWrite() throws IOException { + // 创建序列化流对象 + ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream( + "oos.txt")); + + // 创建对象 + Person p = new Person("林青霞", 27); + + oos.writeObject(p); + + // 释放资源 + oos.close(); + } + + @Test + public void testObjectRead() throws IOException, ClassNotFoundException { + // 创建反序列化对象 + ObjectInputStream ois = new ObjectInputStream(new FileInputStream( + "oos.txt")); + + // 还原对象 + Object obj = ois.readObject(); + + // 释放资源 + ois.close(); + + // 输出对象 + System.out.println(obj); + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/Person.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/Person.java new file mode 100644 index 00000000..8017d0dd --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/Person.java @@ -0,0 +1,74 @@ +package cn.lastwhisper.io.io.otherstream; + +import java.io.Serializable; + +/* + * NotSerializableException:未序列化异常 + * + * 类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。 + * 该接口居然没有任何方法,类似于这种没有方法的接口被称为标记接口。 + * + * java.io.InvalidClassException: + * cn.itcast_07.Person; local class incompatible: + * stream classdesc serialVersionUID = -2071565876962058344, + * local class serialVersionUID = -8345153069362641443 + * + * 为什么会有问题呢? + * Person类实现了序列化接口,那么它本身也应该有一个标记值。 + * 这个标记值假设是100。 + * 开始的时候: + * Person.class -- id=100 + * wirte数据: oos.txt -- id=100 + * read数据: oos.txt -- id=100 + * + * 现在: + * Person.class -- id=200 + * wirte数据: oos.txt -- id=100 + * read数据: oos.txt -- id=100 + * + * 注意: + * 我一个类中可能有很多的成员变量,有些我不想进行序列化。请问该怎么办呢? + * 使用transient关键字声明不需要序列化的成员变量 + */ +public class Person implements Serializable { + private static final long serialVersionUID = -2071565876962058344L; + + private String name; + + // private int age; + + private transient int age; + + // int age; + + public Person() { + super(); + } + + public Person(String name, int age) { + super(); + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + @Override + public String toString() { + return "Person [name=" + name + ", age=" + age + "]"; + } +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/PrintWriterDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/PrintWriterDemo.java new file mode 100644 index 00000000..0e4bd479 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/PrintWriterDemo.java @@ -0,0 +1,93 @@ +package cn.lastwhisper.io.io.otherstream; + +import org.junit.Test; + +import java.io.*; + +/** + * + * @author lastwhisper + * @date 2020/6/14 + */ +public class PrintWriterDemo { + + /* + * 打印流 + * 字节流打印流 PrintStream + * 字符打印流 PrintWriter + * + * 打印流的特点: + * A:只有写数据的,没有读取数据。只能操作目的地,不能操作数据源。 + * B:可以操作任意类型的数据。 + * C:如果启动了自动刷新,能够自动刷新。 + * D:该流是可以直接操作文本文件的。 + * 哪些流对象是可以直接操作文本文件的呢? + * FileInputStream + * FileOutputStream + * FileReader + * FileWriter + * PrintStream + * PrintWriter + * 看API,查流对象的构造方法,如果同时有File类型和String类型的参数,一般来说就是可以直接操作文件的。 + * + * 流: + * 基本流:就是能够直接读写文件的 + * 高级流:在基本流基础上提供了一些其他的功能 + */ + @Test + public void testPrintWriter() throws FileNotFoundException { + // 作为Writer的子类使用 + PrintWriter pw = new PrintWriter("pw.txt"); + + pw.write("hello"); + pw.write("world"); + pw.write("java"); + pw.close(); + } + + /* + * 1:可以操作任意类型的数据。 + * print() + * println() + * 2:启动自动刷新 + * PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"), true); + * 还是应该调用println()的方法才可以 + * 这个时候不仅仅自动刷新了,还实现了数据的换行。 + * + * println() + * 其实等价于于: + * bw.write(); + * bw.newLine(); + * bw.flush(); + */ + @Test + public void testPrintWriter2() throws IOException { + // 创建打印流对象 + // PrintWriter pw = new PrintWriter("pw2.txt"); + PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"), true); + + // write()只能写字节和字符 + // println()可以写任意类型数据 + pw.println("hello"); + pw.println(true); + pw.println(100); + pw.close(); + } + + + @Test + public void testCopy() throws IOException { + BufferedReader br = new BufferedReader(new FileReader( + "DataStreamDemo.java")); + // 封装目的地 + PrintWriter pw = new PrintWriter(new FileWriter("Copy.java"), true); + + String line; + while ((line = br.readLine()) != null) { + pw.println(line); + } + + pw.close(); + br.close(); + } +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/RandomAccessFileDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/RandomAccessFileDemo.java new file mode 100644 index 00000000..36a57da0 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/RandomAccessFileDemo.java @@ -0,0 +1,67 @@ +package cn.lastwhisper.io.io.otherstream; + +import org.junit.Test; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * + * @author lastwhisper + * @date 2020/6/14 + */ +public class RandomAccessFileDemo { + + /* + * 随机访问流: + * RandomAccessFile类不属于流,是Object类的子类。 + * 但它融合了InputStream和OutputStream的功能。 + * 支持对文件的随机访问读取和写入。 + * + * public RandomAccessFile(String name,String mode):第一个参数是文件路径,第二个参数是操作文件的模式。 + * 模式有四种,我们最常用的一种叫"rw",这种方式表示我既可以写数据,也可以读取数据 + * + * 访问模式 + * "r" 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。 + * "rw" 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。 + * "rws" 打开以便读取和写入,对于 "rw",还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。 + * "rwd" 打开以便读取和写入,对于 "rw",还要求对文件内容的每个更新都同步写入到底层存储设备。 + * + */ + @Test + public void testWrite() throws IOException { + // 1、创建随机访问流对象 + RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw"); + // 2、写入数据 + raf.writeInt(100); + raf.writeChar('a'); + raf.writeUTF("中国"); + // 3、关闭资源 + raf.close(); + } + + + @Test + public void testRead() throws IOException { + // 1、创建随机访问流对象 + RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw"); + int i = raf.readInt(); + System.out.println(i); + // 该文件指针可以通过 getFilePointer方法读取,并通过 seek 方法设置。 + System.out.println("当前文件的指针位置是:" + raf.getFilePointer()); + + char ch = raf.readChar(); + System.out.println(ch); + System.out.println("当前文件的指针位置是:" + raf.getFilePointer()); + + String s = raf.readUTF(); + System.out.println(s); + System.out.println("当前文件的指针位置是:" + raf.getFilePointer()); + + // 我不想重头开始了,我就要读取a,怎么办呢? + raf.seek(4); + ch = raf.readChar(); + System.out.println(ch); + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/SequenceInputStreamDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/SequenceInputStreamDemo.java new file mode 100644 index 00000000..3be09076 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/SequenceInputStreamDemo.java @@ -0,0 +1,44 @@ +package cn.lastwhisper.io.io.otherstream; + +import java.io.*; +import java.util.Enumeration; +import java.util.Vector; + +/** + * + * @author lastwhisper + * @date 2020/6/14 + */ +public class SequenceInputStreamDemo { + + public static void main(String[] args) throws IOException { + // 需求:把下面的三个文件的内容复制到Copy.java中 + // ByteArrayStreamDemo.java,CopyFileDemo.java,DataStreamDemo.java + + // SequenceInputStream(Enumeration e) + // 通过简单的回顾我们知道了Enumeration是Vector中的一个方法的返回值类型。 + // Enumeration elements() + Vector v = new Vector(); + InputStream s1 = new FileInputStream("a.txt"); + InputStream s2 = new FileInputStream("b.txt"); + InputStream s3 = new FileInputStream("c.txt"); + v.add(s1); + v.add(s2); + v.add(s3); + Enumeration en = v.elements(); + SequenceInputStream sis = new SequenceInputStream(en); + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream("d.txt")); + + // 如何写读写呢,其实很简单,你就按照以前怎么读写,现在还是怎么读写 + byte[] bytes = new byte[1024]; + int len; + while ((len = sis.read(bytes)) != -1) { + bos.write(bytes, 0, len); + } + + bos.close(); + sis.close(); + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/SystemInDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/SystemInDemo.java new file mode 100644 index 00000000..e4a1fc36 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/SystemInDemo.java @@ -0,0 +1,44 @@ +package cn.lastwhisper.io.io.otherstream; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * System.in 标准输入流。是从键盘获取数据的 + * + * 键盘录入数据: + * A:main方法的args接收参数。 + * java HelloWorld hello world java + * B:Scanner(JDK5以后的) + * Scanner sc = new Scanner(System.in); + * String s = sc.nextLine(); + * int x = sc.nextInt() + * C:通过字符缓冲流包装标准输入流实现 + * BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + * @author lastwhisper + * @date 2020/6/14 + */ +public class SystemInDemo { + + /** + * 如何从控制台键盘中获取数据? + * System.in是字节输入流,需要使用字符输入流包装 + * 再使用 BufferedReader 读取一行数据 + */ + public static void main(String[] args) throws IOException { + + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + System.out.println("请输入一个字符串:"); + String line = br.readLine(); + System.out.println("你输入的字符串是:" + line); + + System.out.println("请输入一个整数:"); + // int i = Integer.parseInt(br.readLine()); + line = br.readLine(); + int i = Integer.parseInt(line); + System.out.println("你输入的整数是:" + i); + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/SystemOutDemo.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/SystemOutDemo.java new file mode 100644 index 00000000..b8fe8024 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/io/otherstream/SystemOutDemo.java @@ -0,0 +1,36 @@ +package cn.lastwhisper.io.io.otherstream; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.OutputStreamWriter; + +/** + * + * @author lastwhisper + * @date 2020/6/14 + */ +public class SystemOutDemo { + + + /** + * 如何将数据输出到控制台? + * System.out是字节输出流,需要使用字符输出流包装 + * 再使用 BufferedWriter 打印一行数据 + */ + public static void main(String[] args) throws IOException { + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + + bw.write("hello"); + bw.newLine(); + // bw.flush(); + bw.write("world"); + bw.newLine(); + // bw.flush(); + bw.write("java"); + bw.newLine(); + bw.flush();//打断点,只有调用 flush 方法才会输出到控制台 + + bw.close(); + } + +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/README.md b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/README.md new file mode 100644 index 00000000..31bc4305 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/README.md @@ -0,0 +1,14 @@ +参考 https://blog.csdn.net/zxm1306192988/article/details/60581173 + +1. 缓冲区(Buffer);TestBuffer +2. 通道(Channel);TestChannel +3. 选择器(Selector) + TestBlockingNIO;不使用Selector + TestNIO;使用Selector + TestNIO_UDP +4. 管道 (Pipe) + TestPipe +5. Path 、Paths 、Files + TestNIOPathFiles + + diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestBlockingNIO.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestBlockingNIO.java similarity index 76% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestBlockingNIO.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestBlockingNIO.java index b81c8f02..7a885014 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestBlockingNIO.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestBlockingNIO.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.io.nio; +package cn.lastwhisper.io.nio; import org.junit.Test; @@ -39,7 +39,7 @@ public void client() throws IOException{ //1. 获取通道 SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898)); - FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ); + FileChannel inChannel = FileChannel.open(Paths.get("/Users/kaisui/Downloads/1.csv"), StandardOpenOption.READ); //2. 分配指定大小的缓冲区 ByteBuffer buf = ByteBuffer.allocate(1024); @@ -51,6 +51,15 @@ public void client() throws IOException{ buf.clear(); } + //接收服务端的反馈 + int len = 0; + while((len = sChannel.read(buf)) != -1){ + buf.flip(); + System.out.println(new String(buf.array(), 0, len)); + buf.clear(); + } + + //4. 关闭通道 inChannel.close(); sChannel.close(); @@ -62,7 +71,7 @@ public void server() throws IOException{ //1. 获取通道 ServerSocketChannel ssChannel = ServerSocketChannel.open(); - FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE); + FileChannel outChannel = FileChannel.open(Paths.get("/Users/kaisui/Downloads/2.csv"), StandardOpenOption.WRITE, StandardOpenOption.CREATE); //2. 绑定连接 ssChannel.bind(new InetSocketAddress(9898)); @@ -80,6 +89,11 @@ public void server() throws IOException{ buf.clear(); } + //发送反馈给客户端 + buf.put("服务端接收数据成功".getBytes()); + buf.flip(); + sChannel.write(buf); + //6. 关闭通道 sChannel.close(); outChannel.close(); diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestBuffer.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestBuffer.java similarity index 99% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestBuffer.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestBuffer.java index 2bb9b902..3ad6f7df 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestBuffer.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestBuffer.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.io.nio; +package cn.lastwhisper.io.nio; import org.junit.Test; diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestChannel.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestChannel.java similarity index 99% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestChannel.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestChannel.java index f60dc495..12acf27a 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestChannel.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestChannel.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.io.nio; +package cn.lastwhisper.io.nio; import org.junit.Test; diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestNIO.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestNIO.java new file mode 100644 index 00000000..c8ef08d7 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestNIO.java @@ -0,0 +1,96 @@ +package cn.lastwhisper.io.nio; + +import org.junit.Test; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.util.Date; +import java.util.Iterator; +import java.util.Scanner; +/** + * TCP + */ +public class TestNIO { + //客户端 + @Test + public void client() throws IOException { + //1.获取通道 + SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898)); + //2.切换非阻塞模式 + sChannel.configureBlocking(false); + //3.分配指定大小的缓冲区 + ByteBuffer buf = ByteBuffer.allocate(1024); + //4.发送数据给服务端 + Scanner scan = new Scanner(System.in); + while (scan.hasNext()) { + String str = scan.next(); + buf.put((new Date().toString() + "\n" + str).getBytes()); + buf.flip(); + sChannel.write(buf); + buf.clear(); + } + //5.关闭通道 + sChannel.close(); + } + + //服务端 + @Test + public void server() throws IOException { + //1.获取通道 + ServerSocketChannel ssChannel = ServerSocketChannel.open(); + + //2.切换非阻塞式模式 + ssChannel.configureBlocking(false); + + //3.绑定连接 + ssChannel.bind(new InetSocketAddress(9898)); + + //4.获取选择器 + Selector selector = Selector.open(); + + //5.将通道注册到选择器上,并且指定“监听接收事件” + ssChannel.register(selector, SelectionKey.OP_ACCEPT); + + //6.轮询式的获取选择器上已经“准备就绪”的事件 + while (selector.select() > 0) { + + //7.获取当前选择器中所有注册的“选择键(已就绪的监听事件)” + Iterator it = selector.selectedKeys().iterator(); + + while (it.hasNext()) { + //8.获取准备“就绪”的事件 + SelectionKey sk = it.next(); + + //9.判断具体是什么时间准备就绪 + if (sk.isAcceptable()) { + //10.若“接收就绪”,获取客户端连接 + SocketChannel sChannel = ssChannel.accept(); + + //11.切换非阻塞模式 + sChannel.configureBlocking(false); + + //12.将该通道注册到选择器上 + sChannel.register(selector, SelectionKey.OP_READ); + } else if (sk.isReadable()) { + //13.获取当前选择器上“读就绪”状态的通道 + SocketChannel sChannel = (SocketChannel) sk.channel(); + //14.读取数据 + ByteBuffer buf = ByteBuffer.allocate(1024); + int len = 0; + while ((len = sChannel.read(buf)) > 0) { + buf.flip(); + System.out.println(new String(buf.array(), 0, len)); + buf.clear(); + } + } + //15.取消选择键SelectionKey + it.remove(); + } + } + } +} \ No newline at end of file diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestNIOPathFiles.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestNIOPathFiles.java new file mode 100644 index 00000000..ab552555 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestNIOPathFiles.java @@ -0,0 +1,158 @@ +package cn.lastwhisper.io.nio; + +import org.junit.Test; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.SeekableByteChannel; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.DosFileAttributeView; + +public class TestNIOPathFiles { + + + //自动资源管理:自动关闭实现 AutoCloseable 接口的资源 + @Test + public void test8() { + try (FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ); + FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE)) { + + ByteBuffer buf = ByteBuffer.allocate(1024); + inChannel.read(buf); + + } catch (IOException e) { + + } + } + + /* + Files常用方法:用于操作内容 + SeekableByteChannel newByteChannel(Path path, OpenOption…how) : 获取与指定文件的连接,how 指定打开方式。 + DirectoryStream newDirectoryStream(Path path) : 打开 path 指定的目录 + InputStream newInputStream(Path path, OpenOption…how):获取 InputStream 对象 + OutputStream newOutputStream(Path path, OpenOption…how) : 获取 OutputStream 对象 + */ + @Test + public void test7() throws IOException { + SeekableByteChannel newByteChannel = Files.newByteChannel(Paths.get("1.jpg"), StandardOpenOption.READ); + + DirectoryStream newDirectoryStream = Files.newDirectoryStream(Paths.get("e:/")); + + for (Path path : newDirectoryStream) { + System.out.println(path); + } + } + + /* + Files常用方法:用于判断 + boolean exists(Path path, LinkOption … opts) : 判断文件是否存在 + boolean isDirectory(Path path, LinkOption … opts) : 判断是否是目录 + boolean isExecutable(Path path) : 判断是否是可执行文件 + boolean isHidden(Path path) : 判断是否是隐藏文件 + boolean isReadable(Path path) : 判断文件是否可读 + boolean isWritable(Path path) : 判断文件是否可写 + boolean notExists(Path path, LinkOption … opts) : 判断文件是否不存在 + public static A readAttributes(Path path,Class type,LinkOption... options) : 获取与 path 指定的文件相关联的属性。 + */ + @Test + public void test6() throws IOException { + Path path = Paths.get("e:/nio/hello7.txt"); +// System.out.println(Files.exists(path, LinkOption.NOFOLLOW_LINKS)); + + BasicFileAttributes readAttributes = Files.readAttributes(path, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS); + System.out.println(readAttributes.creationTime()); + System.out.println(readAttributes.lastModifiedTime()); + + DosFileAttributeView fileAttributeView = Files.getFileAttributeView(path, DosFileAttributeView.class, LinkOption.NOFOLLOW_LINKS); + + fileAttributeView.setHidden(false); + } + + /* + Files常用方法: + Path copy(Path src, Path dest, CopyOption … how) : 文件的复制 + Path createDirectory(Path path, FileAttribute … attr) : 创建一个目录 + Path createFile(Path path, FileAttribute … arr) : 创建一个文件 + void delete(Path path) : 删除一个文件 + Path move(Path src, Path dest, CopyOption…how) : 将 src 移动到 dest 位置 + long size(Path path) : 返回 path 指定文件的大小 + */ + @Test + public void test5() throws IOException { + Path path1 = Paths.get("e:/nio/hello2.txt"); + Path path2 = Paths.get("e:/nio/hello7.txt"); + + System.out.println(Files.size(path2)); + +// Files.move(path1, path2, StandardCopyOption.ATOMIC_MOVE); + } + + @Test + public void test4() throws IOException { + Path dir = Paths.get("e:/nio/nio2"); +// Files.createDirectory(dir); + + Path file = Paths.get("e:/nio/nio2/hello3.txt"); +// Files.createFile(file); + + Files.deleteIfExists(file); + } + + @Test + public void test3() throws IOException { + Path path1 = Paths.get("e:/nio/hello.txt"); + Path path2 = Paths.get("e:/nio/hello2.txt"); + + Files.copy(path1, path2, StandardCopyOption.REPLACE_EXISTING); + } + + /* + Paths 提供的 get() 方法用来获取 Path 对象: + Path get(String first, String … more) : 用于将多个字符串串连成路径。 + Path 常用方法: + boolean endsWith(String path) : 判断是否以 path 路径结束 + boolean startsWith(String path) : 判断是否以 path 路径开始 + boolean isAbsolute() : 判断是否是绝对路径 + Path getFileName() : 返回与调用 Path 对象关联的文件名 + Path getName(int idx) : 返回的指定索引位置 idx 的路径名称 + int getNameCount() : 返回Path 根目录后面元素的数量 + Path getParent() :返回Path对象包含整个路径,不包含 Path 对象指定的文件路径 + Path getRoot() :返回调用 Path 对象的根路径 + Path resolve(Path p) :将相对路径解析为绝对路径 + Path toAbsolutePath() : 作为绝对路径返回调用 Path 对象 + String toString() : 返回调用 Path 对象的字符串表示形式 + */ + @Test + public void test2() { + Path path = Paths.get("e:/nio/hello.txt"); + + System.out.println(path.getParent()); + System.out.println(path.getRoot()); + +// Path newPath = path.resolve("e:/hello.txt"); +// System.out.println(newPath); + + Path path2 = Paths.get("1.jpg"); + Path newPath = path2.toAbsolutePath(); + System.out.println(newPath); + + System.out.println(path.toString()); + } + + @Test + public void test1() { + Path path = Paths.get("e:/", "nio/hello.txt"); + + System.out.println(path.endsWith("hello.txt")); + System.out.println(path.startsWith("e:/")); + + System.out.println(path.isAbsolute()); + System.out.println(path.getFileName()); + + for (int i = 0; i < path.getNameCount(); i++) { + System.out.println(path.getName(i)); + } + } +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestNIO_UDP.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestNIO_UDP.java new file mode 100644 index 00000000..4bfe6287 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestNIO_UDP.java @@ -0,0 +1,59 @@ +package cn.lastwhisper.io.nio; + +import org.junit.Test; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.DatagramChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.util.Date; +import java.util.Iterator; +import java.util.Scanner; +/** + * UDP + */ +public class TestNIO_UDP { + + @Test + public void send() throws IOException { + DatagramChannel dc = DatagramChannel.open(); + dc.configureBlocking(false); + ByteBuffer buf = ByteBuffer.allocate(1024); + Scanner scan = new Scanner(System.in); + while (scan.hasNext()) { + String str = scan.next(); + buf.put((new Date().toString() + "\n" + str).getBytes()); + buf.flip(); + dc.send(buf, new InetSocketAddress("127.0.0.1", 9898)); + buf.clear(); + } + dc.close(); + } + + @Test + public void receive() throws IOException { + DatagramChannel dc = DatagramChannel.open(); + dc.configureBlocking(false); + dc.bind(new InetSocketAddress(9898)); + Selector selector = Selector.open(); + dc.register(selector, SelectionKey.OP_READ); + while (selector.select() > 0) { + Iterator it = selector.selectedKeys().iterator(); + while (it.hasNext()) { + SelectionKey sk = it.next(); + + if (sk.isReadable()) { + ByteBuffer buf = ByteBuffer.allocate(1024); + dc.receive(buf) + ; + buf.flip(); + System.out.println(new String(buf.array(), 0, buf.limit())); + buf.clear(); + } + } + it.remove(); + } + } +} \ No newline at end of file diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestPipe.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestPipe.java similarity index 95% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestPipe.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestPipe.java index 292f229d..ff792a9d 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestPipe.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/TestPipe.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.io.nio; +package cn.lastwhisper.io.nio; import org.junit.Test; diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v1/BIOServer.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v1/BIOServer.java new file mode 100644 index 00000000..c899ce00 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v1/BIOServer.java @@ -0,0 +1,33 @@ +package cn.lastwhisper.io.nio.v1; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; + +/** + * @author lastwhisper + */ +public class BIOServer { + static byte[] bytes = new byte[1024]; + + public static void main(String[] args) { + try (ServerSocket serverSocket = new ServerSocket();) { + serverSocket.bind(new InetSocketAddress(8080)); + while (true) { + System.out.println("wait conn"); + // 等待连接阻塞 + Socket socket = serverSocket.accept(); + System.out.println("conn success"); + // 等待数据阻塞 + socket.getInputStream().read(bytes); + + String content = new String(bytes); + System.out.println("receive data success || content:" + content); + } + + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v1/Client.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v1/Client.java new file mode 100644 index 00000000..abdb9d1d --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v1/Client.java @@ -0,0 +1,25 @@ +package cn.lastwhisper.io.nio.v1; + +import java.io.IOException; +import java.net.Socket; +import java.util.Scanner; + +/** + * 三个socket + * @author lastwhisper + */ +public class Client { + public static void main(String[] args) { + try (Socket socket = new Socket("127.0.0.1", 8080);) { + // client阻塞 等待数据 + Scanner scanner = new Scanner(System.in); + String txt = scanner.next(); + + socket.getOutputStream().write(txt.getBytes()); + + } catch (IOException e) { + e.printStackTrace(); + } + + } +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v2/MockNIOServer.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v2/MockNIOServer.java new file mode 100644 index 00000000..64d80957 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v2/MockNIOServer.java @@ -0,0 +1,81 @@ +package cn.lastwhisper.io.nio.v2; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +/** + * 单线程并发 + * 应用程序循环 + * + * @author lastwhisper + */ +public class MockNIOServer { + static List list = new ArrayList<>(); + static ByteBuffer byteBuffer = ByteBuffer.allocate(512); + + public static void main(String[] args) throws InterruptedException { + try { + ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); + serverSocketChannel.bind(new InetSocketAddress(8080)); + // 设置非阻塞 + serverSocketChannel.configureBlocking(false); + while (true) { + SocketChannel socketChannel = serverSocketChannel.accept(); + if (socketChannel == null) { + Thread.sleep(500); + boolean empty = handleChannelList(); + System.out.printf("date:%s,没有新的连接,处理已有通道集合 empty:%s\n", new Date(),empty); + } else { + System.out.printf("date:%s,有新的连接,加入通道集合,处理通道集合\n", new Date()); + // 设置客户端和服务端之间的通道非阻塞,不设置的话socketChannel#read无数据就会阻塞 + socketChannel.configureBlocking(false); + list.add(socketChannel); + handleChannelList(); + } + + } + + } catch (IOException e) { + e.printStackTrace(); + } + } + + private static boolean handleChannelList() throws IOException, InterruptedException { + if(list.isEmpty()){ + return true; + } + Iterator iterator = list.iterator(); + while (iterator.hasNext()){ + SocketChannel socketChannel = iterator.next(); + Thread.sleep(500);// 减少日志打印 + Date current = new Date(); + // 如果前面没有设置socketChannel.configureBlocking(false),这里read不到数据就会阻塞 +// System.out.printf("date:%s,通道id:%s,尝试读数据\n", current, socketChannel.hashCode()); + int length = socketChannel.read(byteBuffer);// length=2('1'、'\n') + if (length > 0) { + byteBuffer.flip();// 切换到读模式 + Thread.sleep(500);// 模拟业务处理耗时 + byte[] dst = new byte[byteBuffer.limit()]; + byteBuffer.get(dst);//读取数据到dst数组 + String content = new String(dst, 0, dst.length); + byteBuffer.clear();// 清空Buffer + System.out.printf("date:%s,通道id:%s,读到了数据:%s\n", current, socketChannel.hashCode(), content); + if (content.equals("exit") || content.equals("exit\n")) { + socketChannel.close(); + iterator.remove(); + System.out.printf("date:%s,通道id:%s,客户端通过exit命令退出连接\n", new Date(), socketChannel.hashCode()); + } + } else { + System.out.printf("date:%s,通道id:%s,没读到了数据,处理别的通道\n", current, socketChannel.hashCode()); + } + } + return false; + } +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v2/MyNIOServer.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v2/MyNIOServer.java new file mode 100644 index 00000000..f5546678 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v2/MyNIOServer.java @@ -0,0 +1,53 @@ +package cn.lastwhisper.io.nio.v2; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; + +/** + * 应用层做轮询 + * @author lastwhisper + */ +public class MyNIOServer { + static byte[] bytes = new byte[1024]; + static List list = new ArrayList<>(); + + public static void main(String[] args) { + try (ServerSocket serverSocket = new ServerSocket();) { + serverSocket.bind(new InetSocketAddress(8080)); + // 设置serverSocket非阻塞 +// serverSocket.setConfigureBlocking(false); + while (true) { + // serverSocket.accept()阻塞 + Socket socket = serverSocket.accept(); + if (socket == null) { + System.out.println("没有人连接,处理已有连接"); + handleSocketList(); + } else { + // 设置Socket非阻塞 + // socket.setConfigureBlocking(false); + System.out.println("有人连接,处理已有连接"); + list.add(socket); + handleSocketList(); + } + + } + + } catch (IOException e) { + e.printStackTrace(); + } + } + + private static void handleSocketList() throws IOException { + for (Socket s : list) { + int length = s.getInputStream().read(bytes); + if (length != 0) { + String content = new String(bytes); + System.out.println(content); + } + } + } +} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v3/NIOClient.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v3/NIOClient.java similarity index 88% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v3/NIOClient.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v3/NIOClient.java index 0fc92f96..0e6064a4 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v3/NIOClient.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v3/NIOClient.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.io.nio.v3; +package cn.lastwhisper.io.nio.v3; import java.io.IOException; import java.io.OutputStream; diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v3/NIOServer.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v3/NIOServer.java similarity index 98% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v3/NIOServer.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v3/NIOServer.java index 38a4d6bb..3a408401 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v3/NIOServer.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/nio/v3/NIOServer.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.io.nio.v3; +package cn.lastwhisper.io.nio.v3; import java.io.IOException; import java.net.InetSocketAddress; diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/socket/TCPClient.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/socket/TCPClient.java similarity index 95% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/socket/TCPClient.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/socket/TCPClient.java index 3ec3f661..97dfd6b7 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/socket/TCPClient.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/socket/TCPClient.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.io.socket; +package cn.lastwhisper.io.socket; import java.io.IOException; import java.io.InputStream; diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/socket/TCPServer.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/socket/TCPServer.java new file mode 100644 index 00000000..105e6ee8 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/socket/TCPServer.java @@ -0,0 +1,47 @@ +package cn.lastwhisper.io.socket; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.ServerSocket; +import java.net.Socket; + +/** + * @author lastwhisper + */ +public class TCPServer { + public static void main(String[] args) { + try { + ServerSocket ss = new ServerSocket(65000); + while (true) { + // 监听请求 + Socket socket = ss.accept(); + new Thread() { + @Override + public void run() { + // 获取socket的输出流 + // 获取socket的输入流 + try (OutputStream os = socket.getOutputStream(); + InputStream is = socket.getInputStream();) { + int ch; + byte[] buff = new byte[1024]; + // buff主要用来读取输入的内容,存入byte数组,ch读取数组的长度 + ch = is.read(buff); + // 将接收的byte数组转成字符串 + String content = new String(buff, 0, ch); + System.out.println(content); + + os.write(String.valueOf(content.length()).getBytes()); + } catch (IOException e) { + e.printStackTrace(); + } + + } + }.start(); + } + } catch (IOException e) { + e.printStackTrace(); + } + + } +} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/socket/UDPClient.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/socket/UDPClient.java similarity index 95% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/socket/UDPClient.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/socket/UDPClient.java index 5e3bff9b..1760930c 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/socket/UDPClient.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/socket/UDPClient.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.io.socket; +package cn.lastwhisper.io.socket; import java.io.IOException; import java.net.*; diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/socket/UDPServer.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/socket/UDPServer.java similarity index 96% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/socket/UDPServer.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/socket/UDPServer.java index 3a1a4696..6ac137bf 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/socket/UDPServer.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/io/socket/UDPServer.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.io.socket; +package cn.lastwhisper.io.socket; import java.io.IOException; import java.net.DatagramPacket; diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectExecutMain.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectExecutMain.java similarity index 93% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectExecutMain.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectExecutMain.java index 293832df..140c48bb 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectExecutMain.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectExecutMain.java @@ -1,6 +1,5 @@ -package cn.lastwhisper.jdk5.feature.reflect; +package cn.lastwhisper.reflect; -import java.io.FileInputStream; import java.io.InputStream; import java.lang.reflect.Method; import java.util.Properties; diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectForClass.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectForClass.java new file mode 100644 index 00000000..18b2c536 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectForClass.java @@ -0,0 +1,49 @@ +package cn.lastwhisper.reflect; + +import org.junit.Test; + +/** + * 反射之Class对象 + * @author lastwhisper + */ +public class ReflectForClass { + public static void main(String[] args) throws ClassNotFoundException { + String str1 = "abc"; + Class cls1 = str1.getClass(); + Class cls2 = String.class; + Class cls3 = Class.forName("java.lang.String"); + System.out.println(cls1 == cls2); + System.out.println(cls1 == cls3); + + System.out.println(cls1.isPrimitive()); + System.out.println(int.class.isPrimitive()); + System.out.println(int.class == Integer.class); + System.out.println(int.class == Integer.TYPE); + System.out.println(int[].class.isPrimitive()); + } + + /** + * 测试同一个类加载器,Class.forName拿到的Class是不是同一个 + * @throws Exception + */ + @Test + public void classforName() throws Exception { + Class clazz1 = Class.forName("cn.lastwhisper.reflect.pojo.MyObject"); + Class clazz2 = Class.forName("cn.lastwhisper.reflect.pojo.MyObject"); + System.out.println(clazz1 == clazz2); + } + + /** + * 测试同一个Class对象反射创建目标对象时,是不是永远是同一个 + * @throws Exception + */ + @Test + public void reflectNewObj() throws Exception { + Class clazz = Class.forName("cn.lastwhisper.reflect.pojo.MyObject"); + Object newObj1 = clazz.newInstance(); + Object newObj2 = clazz.newInstance(); + System.out.println(newObj1 == newObj2); + } + + +} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectForConstructor.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectForConstructor.java similarity index 89% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectForConstructor.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectForConstructor.java index 6b93263c..554cb768 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectForConstructor.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectForConstructor.java @@ -1,10 +1,11 @@ -package cn.lastwhisper.jdk5.feature.reflect; +package cn.lastwhisper.reflect; import java.lang.reflect.Constructor; /** * 反射之Constructor类 - * Constructor类代表某个类中的一个构造方法 + * Constructor类代表某个类中的一个构造方法 + * * @author lastwhisper */ public class ReflectForConstructor { @@ -21,4 +22,7 @@ public static void main(String[] args) throws Exception { // 3.2 反射方式 constructor.newInstance与clazz.newInstance String str2 = constructor.newInstance(new StringBuffer("constructor.newInstance String")); } + + + } diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectForField.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectForField.java similarity index 93% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectForField.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectForField.java index 37097fd5..07cedfa5 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectForField.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectForField.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.reflect; +package cn.lastwhisper.reflect; import java.lang.reflect.Field; diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectForMethod.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectForMethod.java similarity index 94% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectForMethod.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectForMethod.java index 53ce1d4e..69e0ee2a 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectForMethod.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectForMethod.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.reflect; +package cn.lastwhisper.reflect; import java.lang.reflect.Method; diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectPoint.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectPoint.java similarity index 95% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectPoint.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectPoint.java index 6df6a535..64dbff33 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectPoint.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectPoint.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.reflect; +package cn.lastwhisper.reflect; import java.util.Objects; @@ -38,7 +38,6 @@ public int hashCode() { return Objects.hash(x, y); } - public int getX() { return x; } diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectToArray.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectToArray.java similarity index 93% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectToArray.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectToArray.java index 21367616..7f3412d0 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectToArray.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectToArray.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.reflect; +package cn.lastwhisper.reflect; import java.lang.reflect.Array; diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectUpdateField.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectUpdateField.java similarity index 96% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectUpdateField.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectUpdateField.java index 76aa09ee..a7436a77 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectUpdateField.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectUpdateField.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.reflect; +package cn.lastwhisper.reflect; import java.lang.reflect.Field; diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectUtils.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectUtils.java new file mode 100644 index 00000000..5c079305 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/ReflectUtils.java @@ -0,0 +1,121 @@ +package cn.lastwhisper.reflect; + +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +public class ReflectUtils { + /** + * 通过字段名从对象或对象的父类中得到字段的值 + * @param object 对象实例 + * @param fieldName 字段名 + * @return 字段对应的值 + */ + public static Object getValue(Object object, String fieldName) { + if (object == null) { + return null; + } + if ("".equals(fieldName)) { + return null; + } + Field field = null; + Class clazz = object.getClass(); + for (; clazz != Object.class; clazz = clazz.getSuperclass()) { + try { + field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + return field.get(object); + } catch (Exception e) { + //这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。 + //如果这里的异常打印或者往外抛,则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了 + } + } + return null; + } + + + /** + * 通过字段名从对象或对象的父类中得到字段的值(调用字典的get方法) + * @param object 对象实例 + * @param fieldName 字段名 + * @return 字段对应的值 + * @throws Exception + */ + public static Object getValueOfGet(Object object, String fieldName){ + if (object == null) { + return null; + } + if ("".equals(fieldName)) { + return null; + } + Field field; + Class clazz = object.getClass(); + for (; clazz != Object.class; clazz = clazz.getSuperclass()) { + try { + field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + + PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz); + //获得get方法 + Method getMethod = pd.getReadMethod(); + //执行get方法返回一个Object + return getMethod.invoke(object); + } catch (Exception e) { + //这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。 + //如果这里的异常打印或者往外抛,则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了 + } + } + + return null; + } + + /** + * 通过字段名从对象或对象的父类中得到字段的值(调用字典的get方法,可以取出复杂的对象的值) + * @param object 对象实例 + * @param fieldName 字段名 + * @return 字段对应的值 + * @throws Exception + */ + public static Object getValueOfGetIncludeObjectFeild(Object object, String fieldName) + throws Exception { + + if (object == null) { + return null; + } + if ("".equals(fieldName)) { + return null; + } + + if (HashMap.class.equals(object.getClass())) { + return ((Map) object).get(fieldName); + } + + Field field = null; + Class clazz = object.getClass(); + for (; clazz != Object.class; clazz = clazz.getSuperclass()) { + try { + if (fieldName.contains(".")) { + // 如:operatorUser.name、operatorUser.org.name,递归调用 + String[] splitFiledName = fieldName.split("\\."); + return getValueOfGetIncludeObjectFeild( + getValueOfGetIncludeObjectFeild(object, splitFiledName[0]), + splitFiledName[1]); + } + field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + + PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz); + //获得get方法 + Method getMethod = pd.getReadMethod(); + //执行get方法返回一个Object + return getMethod.invoke(object); + } catch (Exception e) { + //这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。 + //如果这里的异常打印或者往外抛,则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了 + } + } + return null; + } +} diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/pojo/MyObject.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/pojo/MyObject.java new file mode 100644 index 00000000..84ac9727 --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/reflect/pojo/MyObject.java @@ -0,0 +1,5 @@ +package cn.lastwhisper.reflect.pojo; + +public class MyObject { + +} \ No newline at end of file diff --git a/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/serializable/Test.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/serializable/Test.java new file mode 100644 index 00000000..7e6ea47b --- /dev/null +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/serializable/Test.java @@ -0,0 +1,36 @@ +package cn.lastwhisper.serializable; + +import java.io.*; +/** + * 静态变量序列化 + */ +public class Test implements Serializable { + + private static final long serialVersionUID = 1L; + public static int staticVar = 5; + + public static void main(String[] args) { + try { + //初始时staticVar为5 + ObjectOutputStream out = new ObjectOutputStream( + new FileOutputStream("D:\\result.obj")); + out.writeObject(new Test()); + out.close(); + //序列化后修改为10 + Test.staticVar = 10; + ObjectInputStream oin = new ObjectInputStream(new FileInputStream( + "D:\\result.obj")); + Test t = (Test) oin.readObject(); + oin.close(); + //再读取,通过t.staticVar打印新的值 + // 打印10说明,序列化并没有保存static字段,如果保存了staticVar应该为5 + System.out.println(t.staticVar); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/serializable/Test2.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/serializable/Test2.java similarity index 95% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/serializable/Test2.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/serializable/Test2.java index 9ad58b2c..81ef993a 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/serializable/Test2.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/serializable/Test2.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.serializable; +package cn.lastwhisper.serializable; import java.io.*; diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/serializable/Test3.java b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/serializable/Test3.java similarity index 92% rename from java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/serializable/Test3.java rename to java-basic/feature-jdk5/src/main/java/cn/lastwhisper/serializable/Test3.java index d19f6798..bf7432f4 100644 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/serializable/Test3.java +++ b/java-basic/feature-jdk5/src/main/java/cn/lastwhisper/serializable/Test3.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk5.feature.serializable; +package cn.lastwhisper.serializable; import java.io.*; @@ -38,9 +38,7 @@ private void readObject(ObjectInputStream in) { Object object = readFields.get("password", ""); System.out.println("要解密的字符串:" + object.toString()); password = "pass";//模拟解密,需要获得本地的密钥 - } catch (IOException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { + } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } diff --git a/java-basic/feature-jdk5/src/main/resources/ExtClassloaderJar.jar b/java-basic/feature-jdk5/src/main/resources/ExtClassloaderJar.jar new file mode 100644 index 00000000..010ce5ec Binary files /dev/null and b/java-basic/feature-jdk5/src/main/resources/ExtClassloaderJar.jar differ diff --git a/java-basic/feature-jdk5/src/main/resources/config.properties b/java-basic/feature-jdk5/src/main/resources/config.properties new file mode 100644 index 00000000..7a986afa --- /dev/null +++ b/java-basic/feature-jdk5/src/main/resources/config.properties @@ -0,0 +1,4 @@ +# +className=TestArrayArguments + + diff --git a/java-basic/feature-jdk8/README.md b/java-basic/feature-jdk8/README.md new file mode 100644 index 00000000..17b65ae5 --- /dev/null +++ b/java-basic/feature-jdk8/README.md @@ -0,0 +1,18 @@ + +# Jdk8的一些新特性学习 +- annotation 注解 +- date 日期 +- interfa 接口 +- lambda lambda +- optional optional +- stream stream + +参考 https://blog.csdn.net/zxm1306192988/article/details/73744378 + + +# jdk6~7特性 +- spi + - http://www.spring4all.com/article/260 + - resources/META-INF/services下为spi配置文件 + + diff --git a/java-basic/feature-jdk8/pom.xml b/java-basic/feature-jdk8/pom.xml new file mode 100644 index 00000000..98cbb2ce --- /dev/null +++ b/java-basic/feature-jdk8/pom.xml @@ -0,0 +1,18 @@ + + + + 4.0.0 + cn.lastwhisper + feature-jdk8 + 1.0-SNAPSHOT + + + + junit + junit + 4.13 + + + \ No newline at end of file diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/annotation/MyAnnotation.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/annotation/MyAnnotation.java new file mode 100644 index 00000000..091e9dc7 --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/annotation/MyAnnotation.java @@ -0,0 +1,15 @@ +package cn.cunchang.annotation; + +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.*; + +@Repeatable(MyAnnotations.class)//指定重复注解的容器 +@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, TYPE_PARAMETER})//可以修饰的目标 +@Retention(RetentionPolicy.RUNTIME)//生命周期 +public @interface MyAnnotation { + String value() default "java"; +} \ No newline at end of file diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/annotation/MyAnnotations.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/annotation/MyAnnotations.java similarity index 91% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/annotation/MyAnnotations.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/annotation/MyAnnotations.java index bc0c4fa2..3b74e0e5 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/annotation/MyAnnotations.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/annotation/MyAnnotations.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk8.annotation; +package cn.cunchang.annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/annotation/TestAnnotation.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/annotation/TestAnnotation.java similarity index 94% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/annotation/TestAnnotation.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/annotation/TestAnnotation.java index 115f5c0f..b85751d3 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/annotation/TestAnnotation.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/annotation/TestAnnotation.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk8.annotation; +package cn.cunchang.annotation; import org.junit.Test; diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/date/LocalDateTest.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/date/LocalDateTest.java new file mode 100644 index 00000000..c42cec9c --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/date/LocalDateTest.java @@ -0,0 +1,16 @@ +package cn.cunchang.date; + +import java.time.LocalDate; + +/** + * @author cunchang + * @date 2021/1/10 6:18 下午 + */ +public class LocalDateTest { + + public static void main(String[] args) { + LocalDate localDate = LocalDate.ofEpochDay(1610273688163L); + System.out.println(localDate); + } + +} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/date/TestLocalDateTime.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/date/TestLocalDateTime.java similarity index 99% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/date/TestLocalDateTime.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/date/TestLocalDateTime.java index e698728e..7809980e 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/date/TestLocalDateTime.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/date/TestLocalDateTime.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk8.date; +package cn.cunchang.date; import org.junit.Test; diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/date/TestLocalDateTime2.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/date/TestLocalDateTime2.java similarity index 98% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/date/TestLocalDateTime2.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/date/TestLocalDateTime2.java index 3ac0ea9f..0b7b671a 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/date/TestLocalDateTime2.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/date/TestLocalDateTime2.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk8.date; +package cn.cunchang.date; import org.junit.Test; diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/interfa/MyInterface.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/interfa/MyInterface.java similarity index 91% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/interfa/MyInterface.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/interfa/MyInterface.java index eba8d714..00a0cc28 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/interfa/MyInterface.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/interfa/MyInterface.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk8.interfa; +package cn.cunchang.interfa; public interface MyInterface { diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/Employee.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/Employee.java new file mode 100644 index 00000000..f03acac6 --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/Employee.java @@ -0,0 +1,102 @@ +package cn.cunchang.lambda; + +import java.util.Objects; + +public class Employee { + + private Integer id; + private String name; + private Integer age; + private double salary; + + public Employee() { + } + + public Employee(Integer id) { + this.id = id; + } + + public Employee(String name) { + this.name = name; + } + + public Employee(String name, Integer age) { + this.name = name; + this.age = age; + } + + public Employee(String name, Integer age, double salary) { + this.name = name; + this.age = age; + this.salary = salary; + } + + public Employee(Integer id, String name, Integer age, double salary) { + this.id = id; + this.name = name; + this.age = age; + this.salary = salary; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public double getSalary() { + return salary; + } + + public void setSalary(double salary) { + this.salary = salary; + } + + public String show() { + return "测试方法引用!"; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Employee employee = (Employee) o; + return id.equals(employee.id) && + age.equals(employee.age) && + Double.compare(employee.salary, salary) == 0 && + Objects.equals(name, employee.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, age, salary); + } + + @Override + public String toString() { + return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + "]"; + } + +} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/MyFun.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/MyFun.java similarity index 77% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/MyFun.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/MyFun.java index 01530476..04d40788 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/MyFun.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/MyFun.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk8.lambda; +package cn.cunchang.lambda; /** * @author lastwhisper diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/TestLambda.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/TestLambda.java new file mode 100644 index 00000000..d3cf0e02 --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/TestLambda.java @@ -0,0 +1,137 @@ +package cn.cunchang.lambda; + +import cn.cunchang.lambda.strategy.EmployeeAgeFilter; +import cn.cunchang.lambda.strategy.Filter; +import cn.cunchang.lambda.strategy.EmployeeSalaryFilter; +import org.junit.Test; + +import java.util.*; + +/** + * @author lastwhisper + */ +public class TestLambda { + List employees = Arrays.asList( + new Employee("张三", 18, 9496.2), + new Employee("李四", 52, 2396.2), + new Employee("王五", 56, 996.2), + new Employee("赵六", 38, 940.2) + ); + + // 原来匿名内部类 + @Test + public void testInnerClass() { + Comparator comparator = new Comparator() { + @Override + public int compare(Integer o1, Integer o2) { + return 0; + } + }; + + TreeSet treeSet = new TreeSet<>(comparator); + } + + // 将匿名内部类优化为lambda表达式 + @Test + public void testLambda() { + Comparator comparator = (o1, o2) -> Integer.compare(o1, o2); + TreeSet treeSet = new TreeSet<>(comparator); + } + + // 传统方式进行条件过滤 + @Test + public void test3() { + //需求:获取当前公司中员工年龄大于35的员工信息 + List emps = filterEmployeesByAge(employees); + for (Employee e : emps) { + System.out.println(e); + } + System.out.println("---------------------"); + + //需求:获取当前公司中员工工资大于2000的员工信息 + List emps2 = filterEmployeesBySalary(employees); + for (Employee e : emps2) { + System.out.println(e); + } + } + + public List filterEmployeesByAge(List list) { + List emps = new ArrayList<>(); + for (Employee emp : list) { + if (emp.getAge() >= 35) { + emps.add(emp); + } + } + return emps; + } + + public List filterEmployeesBySalary(List list) { + List emps = new ArrayList<>(); + for (Employee emp : list) { + if (emp.getSalary() >= 2000) { + emps.add(emp); + } + } + return emps; + } + + // test3 优化方式一:策略设计模式 + @Test + public void test4() { + List emps = filterEmployees(employees, new EmployeeAgeFilter()); + for (Employee e : emps) { + System.out.println(e); + } + System.out.println("---------------------"); + List emps2 = filterEmployees(employees, new EmployeeSalaryFilter()); + for (Employee e : emps2) { + System.out.println(e); + } + } + + public List filterEmployees(List list, Filter filter) { + List emps = new ArrayList(); + for (Employee emp : list) { + if (filter.eqCondition(emp)) { + emps.add(emp); + } + } + return emps; + } + + // test3 优化方式二:匿名内部类 + @Test + public void test5() { + List list = filterEmployees(employees, new Filter() { + @Override + public boolean eqCondition(Employee t) { + return t.getSalary() >= 2000; + } + }); + for (Employee employee : list) { + System.out.println(employee); + } + } + + // test3 优化方式三:Lambda表达式 + @Test + public void test6() { + List list = filterEmployees(employees, (e) -> e.getSalary() >= 2000); + list.forEach(System.out::println); + } + + // test3 优化方式四:stream API + @Test + public void test7(){ + employees.stream() + .filter((e)->e.getSalary()>=2000) + .forEach(System.out::println); + System.out.println("------------------"); + employees.stream() + .map(Employee::getName) + .forEach(System.out::println); + } + + + +} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/TestLambda2.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/TestLambda2.java similarity index 98% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/TestLambda2.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/TestLambda2.java index 2b202c29..397bcd3d 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/TestLambda2.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/TestLambda2.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk8.lambda; +package cn.cunchang.lambda; import org.junit.Test; diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/TestLambda3.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/TestLambda3.java similarity index 98% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/TestLambda3.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/TestLambda3.java index 84705098..83212fc3 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/TestLambda3.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/TestLambda3.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk8.lambda; +package cn.cunchang.lambda; import org.junit.Test; diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/TestMethodRef.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/TestMethodRef.java similarity index 97% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/TestMethodRef.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/TestMethodRef.java index d398f8bd..b0059d00 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/TestMethodRef.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/TestMethodRef.java @@ -1,6 +1,5 @@ -package cn.lastwhisper.jdk8.lambda; +package cn.cunchang.lambda; -import cn.lastwhisper.jdk8.lambda.Employee; import org.junit.Test; import java.io.PrintStream; diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/example/MyFun2.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/example/MyFun2.java new file mode 100644 index 00000000..3584ebeb --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/example/MyFun2.java @@ -0,0 +1,11 @@ +package cn.cunchang.lambda.example; + +/** + * @author lastwhisper + */ +@FunctionalInterface +public interface MyFun2 { + + public String getValue(String str); + +} diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/example/MyFun3.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/example/MyFun3.java new file mode 100644 index 00000000..1945ea1d --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/example/MyFun3.java @@ -0,0 +1,8 @@ +package cn.cunchang.lambda.example; + +@FunctionalInterface +public interface MyFun3 { + + public R operation(T t1, T t2); + +} diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/example/TestLambda.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/example/TestLambda.java new file mode 100644 index 00000000..f8c89557 --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/example/TestLambda.java @@ -0,0 +1,93 @@ +package cn.cunchang.lambda.example; + +import cn.cunchang.lambda.Employee; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * @author lastwhisper + */ +public class TestLambda { + + List emps = Arrays.asList( + new Employee(101, "a", 18, 9999.99), + new Employee(102, "b", 59, 6666.66), + new Employee(103, "c", 28, 3333.33), + new Employee(104, "d", 8, 7777.77), + new Employee(105, "e", 38, 5555.55) + ); + + /** + * 调用Collections.sort()方法,通过定制排序, + * 比较两个Employee(先按年龄比,年龄相同按姓名比),使用Lambda表达式作为参数传递。 + */ + @Test + public void test1() { + //Collections.sort(emps, new Comparator() { + // @Override + // public int compare(Employee o1, Employee o2) { + // if (o1.getAge() == o2.getAge()) { + // return o1.getName().compareTo(o2.getName()); + // } + // return o1.getAge() - o2.getAge(); + // } + //}); + + Collections.sort(emps, (o1, o2) -> { + if (o1.getAge() == o2.getAge()) { + return o1.getName().compareTo(o2.getName()); + } + return o1.getAge() - o2.getAge(); + }); + for (Employee emp : emps) { + System.out.println(emp); + } + } + + /** + * (1)声明函数式接口,接口中声明抽象方法:public String getValue(String str); + * (2)声明类LambdaTest,类中编写方法使用接口作为参数,将一个字符串转换成大写,并作为方法的返回值。 + * (3)再将一个字符串的第2个到第4个索引位置进行截取子串。 + */ + @Test + public void test2() { + String str = "abcde"; + System.out.println(bridge(str, x -> x.toUpperCase())); + System.out.println(bridge(str, x -> x.substring(2, 4))); + } + + public String bridge(String str, MyFun2 mf) { + return mf.getValue(str); + } + + /** + * (1)声明一个带两个泛型的函数式接口,泛型类型为 : T 为参数,R 为返回值。 + * (2)接口中声明对应抽象方法 + * (3)在LambdaTest类中声明方法,使用接口作为参数,计算两个long型参数的和。 + * (4)再计算两个long型参数的乘积 + */ + @Test + public void test3() { + Long num1 = 10l; + Long num2 = 15l; + System.out.println(bridge2(num1, num2, (x, y) -> x + y)); + System.out.println(bridge2(num1, num2, (x, y) -> x * y)); + } + + public Long bridge2(Long num1, Long num2, MyFun3 mf) { + return mf.operation(num1, num2); + } + + /** + * + */ + @Test + public void test4() { + + } + + +} diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/strategy/EmployeeAgeFilter.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/strategy/EmployeeAgeFilter.java new file mode 100644 index 00000000..950d2830 --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/strategy/EmployeeAgeFilter.java @@ -0,0 +1,13 @@ +package cn.cunchang.lambda.strategy; + +import cn.cunchang.lambda.Employee; + +/** + * @author lastwhisper + */ +public class EmployeeAgeFilter implements Filter { + @Override + public boolean eqCondition(Employee employee) { + return employee.getAge() >= 35; + } +} diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/strategy/EmployeeSalaryFilter.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/strategy/EmployeeSalaryFilter.java new file mode 100644 index 00000000..5bf8de49 --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/strategy/EmployeeSalaryFilter.java @@ -0,0 +1,13 @@ +package cn.cunchang.lambda.strategy; + +import cn.cunchang.lambda.Employee; + +/** + * @author lastwhisper + */ +public class EmployeeSalaryFilter implements Filter { + @Override + public boolean eqCondition(Employee employee) { + return employee.getSalary() >= 2000; + } +} diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/strategy/Filter.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/strategy/Filter.java new file mode 100644 index 00000000..29f79cc7 --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/lambda/strategy/Filter.java @@ -0,0 +1,8 @@ +package cn.cunchang.lambda.strategy; + +/** + * 过滤接口 + */ +public interface Filter { + boolean eqCondition(T t); +} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/optional/Godness.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/optional/Godness.java similarity index 89% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/optional/Godness.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/optional/Godness.java index b0bf6e95..cd35a531 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/optional/Godness.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/optional/Godness.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk8.optional; +package cn.cunchang.optional; public class Godness { diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/optional/Man.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/optional/Man.java new file mode 100644 index 00000000..c9a33df4 --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/optional/Man.java @@ -0,0 +1,27 @@ +package cn.cunchang.optional; + +public class Man { + + private Godness god; + + public Man() { + } + + public Man(Godness god) { + this.god = god; + } + + public Godness getGod() { + return god; + } + + public void setGod(Godness god) { + this.god = god; + } + + @Override + public String toString() { + return "Man [god=" + god + "]"; + } + +} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/optional/NewMan.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/optional/NewMan.java similarity index 93% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/optional/NewMan.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/optional/NewMan.java index b406d210..7efbd803 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/optional/NewMan.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/optional/NewMan.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk8.optional; +package cn.cunchang.optional; import java.util.Optional; diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/optional/TestOptional.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/optional/TestOptional.java similarity index 91% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/optional/TestOptional.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/optional/TestOptional.java index 963a98b4..210373a7 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/optional/TestOptional.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/optional/TestOptional.java @@ -1,6 +1,6 @@ -package cn.lastwhisper.jdk8.optional; +package cn.cunchang.optional; -import cn.lastwhisper.jdk8.stream.Employee; +import cn.cunchang.stream.Employee; import org.junit.Test; import java.util.Optional; @@ -114,4 +114,17 @@ public String getGodnessName2(Optional man){ .getName(); } + @Test + public void test7() { + Optional.ofNullable(null).map(o -> { + if (o == null) { + return null; + } else { + return o; + } + }).ifPresent(o -> { + System.out.println(o+"1"); + }); + } + } diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/CollectorsTest.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/CollectorsTest.java new file mode 100644 index 00000000..c96c48e2 --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/CollectorsTest.java @@ -0,0 +1,30 @@ +package cn.cunchang.stream; + +import cn.cunchang.lambda.Employee; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author cunchang + * @date 2022/5/25 6:02 PM + */ +public class CollectorsTest { + + static List employees = Arrays.asList( + new cn.cunchang.lambda.Employee("张三", 18, 9999.99), + new cn.cunchang.lambda.Employee("张三", 58, 5555.55)); + + public static void main(String[] args) { + Map map = employees.stream() + .collect(Collectors.toMap(Employee::getName, employee -> employee)); + // merge 策略 +// Map map = employees.stream() +// .collect(Collectors.toMap(Employee::getName, employee -> employee, (t, t2) -> t)); + System.out.println(map); + } + + +} diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/Employee.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/Employee.java new file mode 100644 index 00000000..cf10d055 --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/Employee.java @@ -0,0 +1,127 @@ +package cn.cunchang.stream; + + + +public class Employee { + + private Integer id; + private String name; + private Integer age; + private double salary; + private Status status; + + public Employee() { + } + + public Employee(String name) { + this.name = name; + } + + public Employee(String name, Integer age) { + this.name = name; + this.age = age; + } + + public Employee(Integer id, String name, Integer age, double salary) { + this.id = id; + this.name = name; + this.age = age; + this.salary = salary; + } + + public Employee(Integer id, String name, Integer age, double salary, Status status) { + this.id = id; + this.name = name; + this.age = age; + this.salary = salary; + this.status = status; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public double getSalary() { + return salary; + } + + public void setSalary(double salary) { + this.salary = salary; + } + + public String show() { + return "测试方法引用!"; + } + + @Override + public int hashCode() { + final Integer prime = 31; + Integer result = 1; + result = prime * result + age; + result = prime * result + id; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + long temp; + temp = Double.doubleToLongBits(salary); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Employee other = (Employee) obj; + if (age != other.age) + return false; + if (id != other.id) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary)) + return false; + return true; + } + + @Override + public String toString() { + return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + ", status=" + status + + "]"; + } + + +} diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/Status.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/Status.java new file mode 100644 index 00000000..803709a1 --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/Status.java @@ -0,0 +1,5 @@ +package cn.cunchang.stream; + +public enum Status { + FREE, BUSY, VOCATION; +} \ No newline at end of file diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/StreamMapFlatMapDemo.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/StreamMapFlatMapDemo.java new file mode 100644 index 00000000..0382ac50 --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/StreamMapFlatMapDemo.java @@ -0,0 +1,78 @@ +package cn.cunchang.stream; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.toList; + +/** + * map和flatmap的区别 + *

+ * https://www.cnblogs.com/wangjing666/p/9999666.html + * + * @author cunchang + * @date 2021/10/5 4:43 下午 + */ +public class StreamMapFlatMapDemo { + + // 对给定单词列表 ["Hello","World"],你想返回字母去重列表["H","e","l","o","W","r","d"] + + /** + * 错误方式 + */ + @Test + public void test1() { + String[] words = new String[]{"Hello", "World"}; + List a = Arrays.stream(words) + .map(word -> word.split("")) + .distinct() + .collect(toList()); + a.forEach(System.out::print); + } + + /** + * 正确 + */ + @Test + public void test2() { + String[] words = new String[]{"Hello","World"}; + List a = Arrays.stream(words) + // Arrays.stream(words)得到 [Hello, World] + .map(word -> word.split("")) + // map 输入一个元素,返回一个元素 + // "Hello" -> "Hello".split("") => ["H","e","l","l","o"] + // "World" -> "World".split("") => ["W","o","r","l","d"] + // map处理后得到 Stream 内容 [H, e, l, l, o],[W, o, r, l, d] + .flatMap(Arrays::stream) + // flatMap 输入一个元素,返回多个元素 + // flatMap将 Stream 平铺 Stream + // [H, e, l, l, o],[W, o, r, l, d] =>[H, e, l, l, o, W, o, r, l, d] + .distinct() + .collect(toList()); + System.out.println(a); //[H, e, l, o, W, r, d] + } + + @Test + public void test3() { + String[] words = new String[]{"Hello","World"}; + Stream stringStream = Arrays.stream(words); + // [Hello, World] +// System.out.println(stringStream.collect(toList())); + + Stream stringArrStream = stringStream.map(word -> word.split("")); + // [[Ljava.lang.String;@136432db, [Ljava.lang.String;@7382f612] +// System.out.println(stringArrStream.collect(toList())); + // [H, e, l, l, o],[W, o, r, l, d] +// List strArrList = stringArrStream.collect(toList()); +// for (String[] strArr : strArrList) { +// System.out.println(Arrays.toString(strArr)); +// } + + // [H, e, l, l, o, W, o, r, l, d] + stringArrStream.flatMap(Arrays::stream).forEach(System.out::println); + } + +} diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/TestStreamAPI.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/TestStreamAPI.java new file mode 100644 index 00000000..48f5ebf4 --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/TestStreamAPI.java @@ -0,0 +1,53 @@ +package cn.cunchang.stream; + +import cn.cunchang.lambda.Employee; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; + +/* + * 一、Stream API 的操作步骤: + * 1. 创建 Stream + * 2. 中间操作 + * 3. 终止操作(终端操作) + */ +public class TestStreamAPI { + + /** + * 创建Stream + */ + @Test + public void test1() { + // 1.可以通过Collection 系列集合提供的stream()或parallelStream() + List list = new ArrayList<>(); + Stream stream1 = list.stream(); + + // 2.通过 Arrays 中的静态方法stream()获取数组流 + cn.cunchang.lambda.Employee[] emps = new cn.cunchang.lambda.Employee[10]; + Stream stream2 = Arrays.stream(emps); + + // 3.通过Stream 类中的静态方法of() + Stream stream3 = Stream.of("a", "b", "c"); + + // 4.创建无限流 + // 迭代 + Stream stream4 = Stream.iterate(0, (x) -> x + 2); + stream4.limit(10).forEach(System.out::println); + // 生成 + Stream.generate(Math::random) + .limit(5) + .forEach(System.out::println); + } + + @Test + public void test2(){ + Stream.of(1,2,3,4,5,6,7,8,9) + .parallel(); + Stream.of(1,2,3,4,5,6,7,8,9) + .sequential(); + } + +} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/TestStreamAPI2.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/TestStreamAPI2.java similarity index 85% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/TestStreamAPI2.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/TestStreamAPI2.java index 9462401d..aeaec51c 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/TestStreamAPI2.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/TestStreamAPI2.java @@ -1,6 +1,6 @@ -package cn.lastwhisper.jdk8.stream; +package cn.cunchang.stream; -import cn.lastwhisper.jdk8.lambda.Employee; +import cn.cunchang.lambda.Employee; import org.junit.Test; import java.util.ArrayList; @@ -18,19 +18,19 @@ */ public class TestStreamAPI2 { - List employees = Arrays.asList( - new Employee("张三", 18, 9999.99), - new Employee("李四", 58, 5555.55), - new Employee("王五", 26, 3333.33), - new Employee("赵六", 36, 6666.66), - new Employee("田七", 12, 8888.88) + List employees = Arrays.asList( + new cn.cunchang.lambda.Employee("张三", 18, 9999.99), + new cn.cunchang.lambda.Employee("李四", 58, 5555.55), + new cn.cunchang.lambda.Employee("王五", 26, 3333.33), + new cn.cunchang.lambda.Employee("赵六", 36, 6666.66), + new cn.cunchang.lambda.Employee("田七", 12, 8888.88) //, //new Employee("田七", 12, 8888.88) ); /** * 中间操作:筛选与切片 - * filter——接收 Lambda , 从流中排除某些元素。 + * filter——接收 Lambda ,true留下, 从流中排除某些元素。 * limit——截断流,使其元素不超过给定数量。 * skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补 * distinct——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素 @@ -39,7 +39,7 @@ public class TestStreamAPI2 { @Test public void test1() { //中间操作:不会执行任何操作 - Stream stream = employees.stream() + Stream stream = employees.stream() .filter((e) -> e.getAge() > 35); //终止操作:一次性执行全部内容,即 惰性求值 @@ -49,7 +49,7 @@ public void test1() { //外部迭代 @Test public void test2() { - Iterator it = employees.iterator(); + Iterator it = employees.iterator(); while (it.hasNext()) { System.out.println(it.next()); diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/TestStreamAPI3.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/TestStreamAPI3.java similarity index 88% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/TestStreamAPI3.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/TestStreamAPI3.java index 07905d1a..aa65b29f 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/TestStreamAPI3.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/TestStreamAPI3.java @@ -1,8 +1,9 @@ -package cn.lastwhisper.jdk8.stream; +package cn.cunchang.stream; import org.junit.Test; import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; /* @@ -156,13 +157,25 @@ public void test5() { public void test6() { // 根据状态分组 - Map> map = employees.stream() - .collect(Collectors.groupingBy(Employee::getStatus)); - for (Map.Entry> entry : map.entrySet()) { - System.out.println("----------------根据状态分组-----------------"); - System.out.println(entry.getKey()); - entry.getValue().forEach(System.out::println); - } +// Map> map = employees.stream() +// .collect(Collectors.groupingBy(Employee::getStatus)); +// for (Map.Entry> entry : map.entrySet()) { +// System.out.println("----------------根据状态分组-----------------"); +// System.out.println(entry.getKey()); +// entry.getValue().forEach(System.out::println); +// } + + // 根据非唯一键分组,将相同值分到一组 +// Map> map = employees.stream() +// .collect(Collectors.groupingBy(Employee::getStatus)); + + Map map2 = employees.stream() + .collect(Collectors.toMap(Employee::getStatus, Function.identity(),(o1,o2)->{return o1;})); + + // 根据唯一键分组,每一组只有一个数据 + Map map3 = employees.stream() + .collect(Collectors.toMap(Employee::getId,o->{return o;})); + } // 根据状态进行分组求和 diff --git a/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/example/TestStreamAPI.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/example/TestStreamAPI.java new file mode 100644 index 00000000..8d62df3c --- /dev/null +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/example/TestStreamAPI.java @@ -0,0 +1,57 @@ +package cn.cunchang.stream.example; + +import cn.cunchang.stream.Employee; +import cn.cunchang.stream.Status; +import org.junit.Test; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + +/** + * @author lastwhisper + */ +public class TestStreamAPI { + + List emps = Arrays.asList( + new Employee(102, "李四", 59, 6666.66, Status.BUSY), + new Employee(101, "张三", 18, 9999.99, Status.FREE), + new Employee(103, "王五", 28, 3333.33, Status.VOCATION), + new Employee(104, "赵六", 8, 7777.77, Status.BUSY), + new Employee(104, "赵六", 8, 7777.77, Status.FREE), + new Employee(104, "赵六", 8, 7777.77, Status.FREE), + new Employee(105, "田七", 38, 5555.55, Status.BUSY) + ); + + /** + * 给定一个数字列表,如何返回一个由每个数的平方构成的列表呢? + * 给定【1,2,3,4,5】, 应该返回【1,4,9,16,25】。 + */ + @Test + public void test1() { + Stream.of(1, 2, 3, 4, 5).map(x -> x * x).forEach(System.out::println); + } + + /** + * 怎样用 map 和 reduce 方法数一数流中有多少个Employee呢? + */ + @Test + public void test2() { + Optional reduce = emps.stream().map(e -> 1).reduce(Integer::sum); + System.out.println(reduce.get()); + } + + /** + * BigDecimal相加 + */ + @Test + public void test3() { + BigDecimal reduce = emps.stream() + .map(employee -> BigDecimal.valueOf(employee.getSalary())) + .reduce(BigDecimal.ZERO, BigDecimal::add); + System.out.println(reduce); + } + +} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/example/TestTransaction.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/example/TestTransaction.java similarity index 97% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/example/TestTransaction.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/example/TestTransaction.java index 56448da0..2127b44e 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/example/TestTransaction.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/example/TestTransaction.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk8.stream.example; +package cn.cunchang.stream.example; import org.junit.Before; import org.junit.Test; @@ -7,7 +7,6 @@ import java.util.Comparator; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; /** * @author lastwhisper diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/example/Trader.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/example/Trader.java similarity index 93% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/example/Trader.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/example/Trader.java index 70854376..d6287464 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/example/Trader.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/example/Trader.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk8.stream.example; +package cn.cunchang.stream.example; //交易员类 public class Trader { diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/example/Transaction.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/example/Transaction.java similarity index 95% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/example/Transaction.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/example/Transaction.java index 1985404d..1c95bbd2 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/example/Transaction.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/example/Transaction.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk8.stream.example; +package cn.cunchang.stream.example; //交易类 public class Transaction { diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/parallel/ForkJoinCalculate.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/parallel/ForkJoinCalculate.java similarity index 96% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/parallel/ForkJoinCalculate.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/parallel/ForkJoinCalculate.java index 0426d4e9..25baab69 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/parallel/ForkJoinCalculate.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/parallel/ForkJoinCalculate.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.jdk8.stream.parallel; +package cn.cunchang.stream.parallel; import java.util.concurrent.RecursiveTask; diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/parallel/TestForkJoin.java b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/parallel/TestForkJoin.java similarity index 93% rename from java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/parallel/TestForkJoin.java rename to java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/parallel/TestForkJoin.java index ffd31e10..31bea0b1 100644 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/parallel/TestForkJoin.java +++ b/java-basic/feature-jdk8/src/main/java/cn/cunchang/stream/parallel/TestForkJoin.java @@ -1,9 +1,7 @@ -package cn.lastwhisper.jdk8.stream.parallel; +package cn.cunchang.stream.parallel; import org.junit.Test; -import java.time.Duration; -import java.time.Instant; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinTask; import java.util.stream.LongStream; diff --git "a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/\345\217\202\350\200\203.txt" "b/java-basic/feature-jdk8/src/main/java/cn/cunchang/\345\217\202\350\200\203.txt" similarity index 100% rename from "java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/\345\217\202\350\200\203.txt" rename to "java-basic/feature-jdk8/src/main/java/cn/cunchang/\345\217\202\350\200\203.txt" diff --git a/java-basic/interview/pom.xml b/java-basic/interview/pom.xml index 4648919a..eb0c5343 100644 --- a/java-basic/interview/pom.xml +++ b/java-basic/interview/pom.xml @@ -2,15 +2,32 @@ - - java-basic - cn.lastwhisper - 1.0-SNAPSHOT - 4.0.0 cn.lastwhisper interview + 1.0-SNAPSHOT + + + junit + junit + 4.13 + test + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + 1.8 + 1.8 + + + + \ No newline at end of file diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/ComparableAndComparator/my/DataSort.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/ComparableAndComparator/my/DataSort.java deleted file mode 100644 index 4d93896f..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/ComparableAndComparator/my/DataSort.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.lastwhisper.interview.ComparableAndComparator.my; - -//排序类 -public class DataSort { - public static void sort(Object[] objs) { - for (int i = 0; i < objs.length - 1; i++) { - for (int j = i + 1; j < objs.length; j++) { - MyComparable c1 = (MyComparable) objs[i]; - MyComparable c2 = (MyComparable) objs[j]; - if (c1.compareTo(c2) > 0) { - Object temp = objs[i]; - objs[i] = objs[j]; - objs[j] = temp; - } - } - } - } -} \ No newline at end of file diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/ComparableAndComparator/my/MyComparable.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/ComparableAndComparator/my/MyComparable.java deleted file mode 100644 index 3835f718..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/ComparableAndComparator/my/MyComparable.java +++ /dev/null @@ -1,8 +0,0 @@ -package cn.lastwhisper.interview.ComparableAndComparator.my; - -//使一个类本身具备比较性 -//优点:实现此接口的类可以自己重写自己规定比较的内容 -//缺点:因为只有一个方法,一个类只能有一种方式进行比较 -public interface MyComparable { - public int compareTo(E e); -} \ No newline at end of file diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/ComparableAndComparator/my/Person.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/ComparableAndComparator/my/Person.java deleted file mode 100644 index 55527d5f..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/ComparableAndComparator/my/Person.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.lastwhisper.interview.ComparableAndComparator.my; - -//人 -public class Person implements MyComparable{ - private int age; - - public Person(int age) { - super(); - this.age = age; - } - - public int compareTo(Object e) { - if(e instanceof Person){ - Person temp=(Person)e; - if(this.age>temp.getAge())return 1; - else if(this.age map.length) { - throw new IllegalArgumentException("进制数不允许大于" + map.length); - } - if (decimal < radix) { - return map[decimal]; - } - StringBuilder sb = new StringBuilder(); - // 余数 - int remainder; - // 被除数 - int divisor = decimal; - while (divisor != 0 && divisor / radix >= 0) { - remainder = divisor % radix; //取余 - divisor = divisor / radix; // 整除 - sb.append(map[remainder]); - } - return sb.reverse().toString(); - } -} diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/Initiative/SubClass.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/Initiative/SubClass.java deleted file mode 100644 index 276c2235..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/Initiative/SubClass.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.lastwhisper.interview.Initiative; - -/** - * 子类 - * @author lastwhisper - */ -public class SubClass extends SuperClass { - - static { - System.out.println("子类的静态代码块"); - } - - { - System.out.println("子类的代码块"); - } - - public SubClass() { - System.out.println("子类的构造函数"); - } - - public static void main(String[] args) { - new SubClass(); - } -} diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/Initiative/SuperClass.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/Initiative/SuperClass.java deleted file mode 100644 index a2c1fbae..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/Initiative/SuperClass.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.lastwhisper.interview.Initiative; - -/** - * 父类 - * @author lastwhisper - */ -public class SuperClass { - - static { - System.out.println("父类的静态代码块"); - } - - { - System.out.println("父类的代码块"); - } - - public SuperClass() { - System.out.println("父类的构造函数"); - } -} - diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/Initiative/Test.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/Initiative/Test.java deleted file mode 100644 index b873f5d2..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/Initiative/Test.java +++ /dev/null @@ -1,10 +0,0 @@ -package cn.lastwhisper.interview.Initiative; - -/** - * @author lastwhisper - */ -public class Test { - public static void main(String[] args) { - new SubClass(); - } -} diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/Int2String/Int2String.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/Int2String/Int2String.java deleted file mode 100644 index 55383ad8..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/Int2String/Int2String.java +++ /dev/null @@ -1,65 +0,0 @@ -package cn.lastwhisper.interview.Int2String; - -/** - * 数字类型转为String - * @author lastwhisper - * @date 2019/11/14 - */ -public class Int2String { - - public void longToString(int n) { - long startTime = System.currentTimeMillis(); - for (int i = 0; i < n; i++) { - long num = 123456789L + n; - String s = Long.toString(num); - } - long endTime = System.currentTimeMillis(); - System.out.println(n + "次long转String,使用longToString耗时:" + (endTime - startTime)); - } - - public void stringValueOf(int n) { - long startTime = System.currentTimeMillis(); - for (int i = 0; i < n; i++) { - long num = 123456789L + n; - String s = String.valueOf(num); - } - long endTime = System.currentTimeMillis(); - System.out.println(n + "次long转String,使用stringValueOf耗时:" + (endTime - startTime)); - } - - public void stringAdd(int n) { - long startTime = System.currentTimeMillis(); - for (int i = 0; i < n; i++) { - long num = 123456789L + n; - String s = num + ""; - } - long endTime = System.currentTimeMillis(); - System.out.println(n + "次long转String,使用stringAdd耗时:" + (endTime - startTime)); - } - - public void stringBuilder(int n) { - long startTime = System.currentTimeMillis(); - for (int i = 0; i < n; i++) { - long num = 123456789L + n; - StringBuilder sb = new StringBuilder(); - sb.append(num); - String s = sb.toString(); - } - long endTime = System.currentTimeMillis(); - System.out.println(n + "次long转String,使用stringBuilder耗时:" + (endTime - startTime)); - } - - /** - * 10000000次long转String,使用stringValueOf耗时:334 - * 10000000次long转String,使用stringBuilder耗时:395 - */ - public static void main(String[] args) { - int n = 10000000; - Int2String int2String = new Int2String(); - int2String.longToString(n); - int2String.stringValueOf(n); - int2String.stringBuilder(n); - int2String.stringAdd(n); - } - -} diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/RelationFile/DeleteFile.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/RelationFile/DeleteFile.java deleted file mode 100644 index e7c68089..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/RelationFile/DeleteFile.java +++ /dev/null @@ -1,61 +0,0 @@ -package cn.lastwhisper.interview.RelationFile; - -import java.io.File; - -/** - * 删除指定文件夹 - * @author lastwhisper - * @date 2019/11/22 - */ -public class DeleteFile { - - public static void main(String[] args) { - File file = new File("C:\\Users\\Administrator\\Code\\GitRepository\\Code"); - recursionFindDirectory(file); - } - - /** - * 递归找到target目录 - */ - public static void recursionFindDirectory(File file) { - File[] files = file.listFiles(); - if (files == null) { - return; - } - for (File f : files) { - System.out.println("log.info f.getName=" + f.getName() + " f.isDirectory=" + f.isDirectory()); - if ("target".equals(f.getName())) { - recursionDeleteFile(f); - f.delete(); - System.out.println("log.info f=" + f.getName() + " is delete"); - } else { - recursionFindDirectory(f); - } - } - } - - /** - * 递归删除target目录下的文件 - */ - public static void recursionDeleteFile(File file) { - if (file == null) { - return; - } - File[] files = file.listFiles(); - if (files == null) { - return; - } - for (File f : files) { - if (f.isDirectory()) { - System.out.println("log.info f=" + f.getName() + " f.isDirectory=" + f.isDirectory()); - recursionDeleteFile(f); - } else { - f.delete(); - System.out.println("log.info f=" + f.getName() + " is delete"); - } - } - file.delete(); - System.out.println("log.info f=" + file.getName() + " is delete"); - } - -} diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/Sax/Person.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/Sax/Person.java deleted file mode 100644 index 020c12b5..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/Sax/Person.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.lastwhisper.interview.Sax; - -public class Person { - private String name; - private int age; - - public Person() { - } - - public Person(String name, int age) { - super(); - this.name = name; - this.age = age; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } - -} diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/Sax/SaxTest.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/Sax/SaxTest.java deleted file mode 100644 index 4a1e2422..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/Sax/SaxTest.java +++ /dev/null @@ -1,101 +0,0 @@ -package cn.lastwhisper.interview.Sax; - -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; -import org.xml.sax.helpers.DefaultHandler; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; -import java.io.IOException; - -/** - * @author lastwhisper - * @desc SAX方式解析xml文件 - * @email gaojun56@163.com - */ -public class SaxTest { - public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException { - // SAX解析 - // 1.获取解析工厂 - SAXParserFactory factory = SAXParserFactory.newInstance(); - // 2.从解析工厂获取解析器 - SAXParser parse = factory.newSAXParser(); - // 3.得到解读器 - XMLReader reader=parse.getXMLReader(); - // 4.设置内容处理器 - reader.setContentHandler(new PHandler()); - // 5.读取xml的文档内容 - reader.parse("src/main/java/cn/lastwhisper/cn.lastwhisper.javabasic/Sax/person.xml"); - - } - -} - -class PHandler extends DefaultHandler { - /** - * @author lastwhisper - * @desc 文档解析开始时调用,该方法只会调用一次 - * @param - * @return void - */ - @Override - public void startDocument() throws SAXException { - System.out.println("----解析文档开始----"); - } - - /** - * @author lastwhisper - * @desc 每当遇到起始标签时调用 - * @param uri xml文档的命名空间 - * @param localName 标签的名字 - * @param qName 带命名空间的标签的名字 - * @param attributes 标签的属性集 - * @return void - */ - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - System.out.println("标签<"+qName + ">解析开始"); - } - - /** - * @author lastwhisper - * @desc 解析标签内的内容的时候调用 - * @param ch 当前读取到的TextNode(文本节点)的字节数组 - * @param start 字节开始的位置,为0则读取全部 - * @param length 当前TextNode的长度 - * @return void - */ - @Override - public void characters(char[] ch, int start, int length) throws SAXException { - String contents = new String(ch, start, length).trim(); - if (contents.length() > 0) { - System.out.println("内容为-->" + contents); - } else { - System.out.println("内容为-->" + "空"); - } - } - /** - * @author lastwhisper - * @desc 每当遇到结束标签时调用 - * @param uri xml文档的命名空间 - * @param localName 标签的名字 - * @param qName 带命名空间的标签的名字 - * @return void - */ - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - System.out.println("标签解析结束"); - } - /** - * @author lastwhisper - * @desc 文档解析结束后调用,该方法只会调用一次 - * @param - * @return void - */ - @Override - public void endDocument() throws SAXException { - System.out.println("----解析文档结束----"); - } -} \ No newline at end of file diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/Sax/SaxXmlToPojo.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/Sax/SaxXmlToPojo.java deleted file mode 100644 index 42aec8ea..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/Sax/SaxXmlToPojo.java +++ /dev/null @@ -1,126 +0,0 @@ -package cn.lastwhisper.interview.Sax; - -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; -import org.xml.sax.helpers.DefaultHandler; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * @author lastwhisper - * @desc 将xml数据解析到pojo中 - * - * @email gaojun56@163.com - */ -public class SaxXmlToPojo { - public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException { - // SAX解析 - // 1.获取解析工厂 - SAXParserFactory factory = SAXParserFactory.newInstance(); - // 2.从解析工厂获取解析器 - SAXParser parse = factory.newSAXParser(); - // 3.得到解读器 - XMLReader reader = parse.getXMLReader(); - // 4.设置内容处理器 - PersonHandler personHandler = new PersonHandler(); - reader.setContentHandler(personHandler); - // 5.读取xml的文档内容 - reader.parse("src/main/java/cn/lastwhisper/cn.lastwhisper.javabasic/Sax/person.xml"); - - List persons = personHandler.getPersons(); - for (Person person : persons) { - System.out.println("姓名:" + person.getName() + " 年龄:" + person.getAge()); - } - } - -} - -class PersonHandler extends DefaultHandler { - private List persons; - private Person person; - private String tag; // 存储操作标签 - - /** - * @author lastwhisper - * @desc 文档解析开始时调用,该方法只会调用一次 - * @param - * @return void - */ - @Override - public void startDocument() throws SAXException { - persons = new ArrayList(); - } - - /** - * @author lastwhisper - * @desc 标签(节点)解析开始时调用 - * @param uri xml文档的命名空间 - * @param localName 标签的名字 - * @param qName 带命名空间的标签的名字 - * @param attributes 标签的属性集 - * @return void - */ - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - tag = qName; - if ("person".equals(tag)) { - person = new Person(); - } - } - - /** - * @author lastwhisper - * @desc 解析标签的内容的时候调用 - * @param ch 字符 - * @param start 字符数组中的起始位置 - * @param length 要从字符数组使用的字符数 - * @return void - */ - @Override - public void characters(char[] ch, int start, int length) throws SAXException { - String contents = new String(ch, start, length).trim(); - if ("name".equals(tag)) { - person.setName(contents); - } else if ("age".equals(tag)) { - if (contents.length() > 0) { - person.setAge(Integer.valueOf(contents)); - } - } - } - - /** - * @author lastwhisper - * @desc 标签(节点)解析结束后调用 - * @param uri xml文档的命名空间 - * @param localName 标签的名字 - * @param qName 带命名空间的标签的名字 - * @return void - */ - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - if ("person".equals(qName)) { - persons.add(person); - } - tag = null; //tag丢弃了 - } - - /** - * @author lastwhisper - * @desc 文档解析结束后调用,该方法只会调用一次 - * @param - * @return void - */ - @Override - public void endDocument() throws SAXException { - } - - public List getPersons() { - return persons; - } -} \ No newline at end of file diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/Sax/person.xml b/java-basic/interview/src/main/java/cn/lastwhisper/interview/Sax/person.xml deleted file mode 100644 index b2072b04..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/Sax/person.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - 韩信 - 25 - - - 李白 - 23 - - diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/array/ArrayCopy.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/array/ArrayCopy.java deleted file mode 100644 index ceaea7f5..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/array/ArrayCopy.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.lastwhisper.interview.array; - -/** - * - * @author lastwhisper - * @date 2019/11/24 - */ -public class ArrayCopy { - - public static void main(String[] args) { - //char[][] Array2D = {{a, b, c}, {d, e, f}}; - //char[][] Array2Dnew = {{a, a, a, b, b, b, c, c, c}, - // {a, a, a, b, b, b, c, c, c}, - // {a, a, a, b, b, b, c, c, c}, - // {d, d, d, e, e, e, f, f, f}, - // {d, d, d, e, e, e, f, f, f}, - // {d, d, d, e, e, e, f, f, f}}; - - - - } - -} diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/string/StringMethodTest.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/string/StringMethodTest.java deleted file mode 100644 index cdb76b70..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/string/StringMethodTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.lastwhisper.interview.string; - -import org.junit.Test; - -/** - * - * @author lastwhisper - * @date 12/27/2019 - */ -public class StringMethodTest { - - /** - * 测试indexOf与lastIndexOf方法 - */ - @Test - public void indexTest() { - //String str = "JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJXXXJJJ"; - String str = "XXXJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ"; - long startTime = System.currentTimeMillis(); - for (int i = 0; i < 100000; i++) { - str.indexOf("XXXJJJ");//17 7 - } - long endTime1 = System.currentTimeMillis(); - System.out.println(endTime1 - startTime); - for (int i = 0; i < 100000; i++) { - str.lastIndexOf("XXXJJJ");//8 54 - } - System.out.println(System.currentTimeMillis() - endTime1); - } - - /** - * 测试subString方法 - */ - @Test - public void subStringTest() { - String s = "010010"; - System.out.println(s.substring(0,1)); - System.out.println(s.substring(1,1)); - System.out.println(s.substring(1,2)); - System.out.println(s.substring(2,3)); - System.out.println(s.substring(3)); - } - -} diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/string/StringTest.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/string/StringTest.java deleted file mode 100644 index 8bdf2993..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/string/StringTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package time; - -/** - * @author lastwhisper - */ -public class StringTest { - - public void test() { - String s = "a"; - s = s + "b" + "c"; - s = s + "b" + "c" + "d"; - System.out.println(s); - } - -} diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/test1/Main.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/test1/Main.java deleted file mode 100644 index 65b15cd3..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/test1/Main.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.lastwhisper.interview.test1; - -import java.util.*; - -/** - * - * @author lastwhisper - * @date 2019/12/16 - */ -public class Main { - private static List> listMap = new ArrayList<>(); - - static { - Map user1 = new LinkedHashMap<>(); - user1.put("username", "tom"); - user1.put("age", "18"); - listMap.add(user1); - } - - public static void main(String[] args) { - for (Map map : listMap) { - if (map.containsKey("username")) { - map.put("username", "netty"); - } - } - for (Map map : listMap) { - for (Map.Entry entry : map.entrySet()) { - System.out.println("k=" + entry.getKey() + " v=" + entry.getValue()); - } - } - } - -} diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/timestamp/TimeStampTest.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/timestamp/TimeStampTest.java deleted file mode 100644 index d4bea7d5..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/timestamp/TimeStampTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.interview.timestamp; - -/** - * 时间戳 - * @author lastwhisper - * @date 2019/11/24 - */ -public class TimeStampTest { - /** - * 时间戳的二进制为41位 - */ - public static void main(String[] args){ - long currentTimeMillis = System.currentTimeMillis(); - System.out.println(Long.toBinaryString(currentTimeMillis).length()); - } -} diff --git a/java-basic/interview/src/main/java/cn/lastwhisper/interview/uuid/UUIDTest.java b/java-basic/interview/src/main/java/cn/lastwhisper/interview/uuid/UUIDTest.java deleted file mode 100644 index f503156b..00000000 --- a/java-basic/interview/src/main/java/cn/lastwhisper/interview/uuid/UUIDTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.lastwhisper.interview.uuid; - -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; - -/** - * - * @author lastwhisper - * @date 2019/11/23 - */ -public class UUIDTest { - private static Set set = new HashSet(); - - public static void main(String[] args) throws InterruptedException { - long busyTime = 7; - int i = 0; - while (true) { - long nowSys = System.currentTimeMillis(); - while ((System.currentTimeMillis() - nowSys) <= busyTime) { - i++; - String uuid = UUID.randomUUID().toString(); - System.out.println("log info 第 " + i + " 次生成uuid:" + uuid); - if (set.contains(uuid)) { - System.err.println("log error 第 " + i + " 次生成uuid:" + uuid + " 发生重复"); - break; - } else { - set.add(uuid); - } - } - Thread.sleep(1); - } - - } - -} diff --git a/java-basic/jdk11/pom.xml b/java-basic/jdk11/pom.xml deleted file mode 100644 index 4573058f..00000000 --- a/java-basic/jdk11/pom.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - java-basic - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - cn.lastwhisper - jdk11 - - - \ No newline at end of file diff --git a/java-basic/jdk12/pom.xml b/java-basic/jdk12/pom.xml deleted file mode 100644 index 858593bd..00000000 --- a/java-basic/jdk12/pom.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - java-basic - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - cn.lastwhisper - jdk12 - - - \ No newline at end of file diff --git a/java-basic/jdk13/pom.xml b/java-basic/jdk13/pom.xml deleted file mode 100644 index d5e9dedd..00000000 --- a/java-basic/jdk13/pom.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - java-basic - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - cn.lastwhisper - jdk13 - - - \ No newline at end of file diff --git a/java-basic/jdk5/README.md b/java-basic/jdk5/README.md deleted file mode 100644 index de5c3894..00000000 --- a/java-basic/jdk5/README.md +++ /dev/null @@ -1,21 +0,0 @@ -参考“传智 张孝详 Java高新技术” - -# Jdk5的一些新特性以及基础知识 -1. 自动拆装箱 AutoBox -2. 静态导入 StaticImport -3. 可变参数 VariableParameter -4. 枚举 enumtest -5. 注解 annotation -6. 反省与JavaBean introspection -7. beanutils beanutils -8. 反射 reflect -9. 泛型 generic -10. 类加载器 classloader -11. 动态代理与SpringAop实现 proxy - -12. spi -http://www.spring4all.com/article/260 -resources/META-INF/services下为spi配置文件 -13. throwable -14. collection -15. apt 注解处理器 diff --git a/java-basic/jdk5/pom.xml b/java-basic/jdk5/pom.xml deleted file mode 100644 index 86da5ddf..00000000 --- a/java-basic/jdk5/pom.xml +++ /dev/null @@ -1,130 +0,0 @@ - - - - java-basic - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - jdk5 - - - UTF-8 - 4.0.3.RELEASE - 5.1.24 - - - - - org.springframework - spring-test - ${org.springframework.version} - - - org.springframework - spring-beans - ${org.springframework.version} - - - org.springframework - spring-core - ${org.springframework.version} - - - org.springframework - spring-context - ${org.springframework.version} - - - org.springframework - spring-web - ${org.springframework.version} - - - org.springframework - spring-aop - ${org.springframework.version} - - - org.springframework - spring-expression - ${org.springframework.version} - - - org.springframework - spring-context-support - ${org.springframework.version} - - - org.springframework - spring-webmvc - ${org.springframework.version} - - - org.springframework - spring-jdbc - ${org.springframework.version} - - - org.springframework - spring-tx - ${org.springframework.version} - - - - mysql - mysql-connector-java - ${mysql.connector} - - - - - com.thoughtworks.qdox - qdox - 1.12.1 - - - - - com.squareup - javapoet - 1.11.1 - - - - - - - - - - - - - demos - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 1.8 - 1.8 - - - - - - src/main/java - - **/*.xml - - true - - - - - \ No newline at end of file diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/annotation/AnnotationTest.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/annotation/AnnotationTest.java deleted file mode 100644 index af0a86f4..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/annotation/AnnotationTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.lastwhisper.jdk5.feature.annotation; - -import java.util.Arrays; - -/** - * jdk5新特性:注解 - * @author lastwhisper - */ -public class AnnotationTest { - - public static void main(String[] args) { - if (UseAnnotation.class.isAnnotationPresent(MyAnnotation.class)) { - MyAnnotation annotation = UseAnnotation.class.getAnnotation(MyAnnotation.class); - System.out.println(annotation.color()); - System.out.println(annotation.value()); - System.out.println(Arrays.toString(annotation.arrayAttr())); - System.out.println(annotation.annotation().value()); - System.out.println(annotation.clazz()); - System.out.println(annotation.enumLevel()); - } - } - -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/annotation/Level.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/annotation/Level.java deleted file mode 100644 index 01e8f0f2..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/annotation/Level.java +++ /dev/null @@ -1,3 +0,0 @@ -package cn.lastwhisper.jdk5.feature.annotation; - -public enum Level {BAD, INDIFFERENT, GOOD} \ No newline at end of file diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/annotation/MetaAnnotation.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/annotation/MetaAnnotation.java deleted file mode 100644 index 81ee2b36..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/annotation/MetaAnnotation.java +++ /dev/null @@ -1,5 +0,0 @@ -package cn.lastwhisper.jdk5.feature.annotation; - -public @interface MetaAnnotation { - String value(); -} \ No newline at end of file diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/annotation/MyAnnotation.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/annotation/MyAnnotation.java deleted file mode 100644 index 007948ea..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/annotation/MyAnnotation.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.lastwhisper.jdk5.feature.annotation; - -// 自定义注解 - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - - -@Retention(RetentionPolicy.RUNTIME)//保留策略 -@Target({ElementType.METHOD, ElementType.TYPE})//作用目标 // 为什么是TYPE,因为Class的父类是Type -public @interface MyAnnotation { - // 八大基本数据类型、String、Class、Enum、注解类型对应的数组类型 - - String color() default "green"; - - String value();//value比较特殊 - - int[] arrayAttr() default {1, 2, 3}; - - Class clazz() default Formatter.class; - - Level enumLevel() default Level.GOOD; - - MetaAnnotation annotation() default @MetaAnnotation("xxxx"); - -} - - -interface Formatter { -} - diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/annotation/UseAnnotation.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/annotation/UseAnnotation.java deleted file mode 100644 index 292c6b81..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/annotation/UseAnnotation.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.lastwhisper.jdk5.feature.annotation; - -/** - * @author lastwhisper - */ -@MyAnnotation(color = "red", value = "xxx", - arrayAttr = {4, 5, 6}, enumLevel = Level.INDIFFERENT, - annotation = @MetaAnnotation("yyy"), clazz = Formatter.class) -public class UseAnnotation { - - - @MyAnnotation("yyy") - @SuppressWarnings("deprecation") - public static void deprecatedFun() { - sayHello(); - } - - @Deprecated - public static void sayHello() { - System.out.println("被弃用的函数"); - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/ClassLoaderObject.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/ClassLoaderObject.java deleted file mode 100644 index 8b356421..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/ClassLoaderObject.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.lastwhisper.jdk5.feature.classloader; - -import java.lang.reflect.Field; -import java.util.Vector; - -/** - * 获取ClassLoader下面加载的类 - * @author lastwhisper - */ -public class ClassLoaderObject { - /** - * @author lastwhisper - */ - public static void main(String[] args) throws Exception { - - Field f = ClassLoader.class.getDeclaredField("classes"); - f.setAccessible(true); - Vector classes = (Vector) f.get(ClassLoader.getSystemClassLoader()); - for (Object object : classes) { - System.out.println(object); - } - - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/ClassLoaderStructure.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/ClassLoaderStructure.java deleted file mode 100644 index d6b3b251..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/ClassLoaderStructure.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.lastwhisper.jdk5.feature.classloader; - -/** - * 类加载器的结构、以及对应类加载器加载类的范围 - * @author lastwhisper - */ -public class ClassLoaderStructure { - - public static void main(String[] args) throws ClassNotFoundException { - Object obj = new Object(); - System.out.println("Object的类加载器:"+obj.getClass().getClassLoader()); - - Class clazz = Class.forName("cn.lastwhisper.cn.lastwhisper.javabasic.ClassLoader.other.Hello"); - System.out.println("ext下的类加载器:"+clazz.getClassLoader()); - - ClassLoaderStructure test01 = new ClassLoaderStructure(); - System.out.println("classpath下的类加载器:"+test01.getClass().getClassLoader()); - - System.out.println(""); - - System.out.println("classpath下的类加载器:"+test01.getClass().getClassLoader()); - System.out.println("classpath下的类加载器的父类加载器:"+test01.getClass().getClassLoader().getParent()); - System.out.println("classpath下的类加载器的父类加载器的父类加载器:"+test01.getClass().getClassLoader().getParent().getParent()); - - // java.lang.ClassLoader - - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/ClassLoaderUnique.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/ClassLoaderUnique.java deleted file mode 100644 index 066cea61..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/ClassLoaderUnique.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.lastwhisper.jdk5.feature.classloader; - -import java.io.IOException; -import java.io.InputStream; - -/** - * 类加载器与instanceof关键字演示 - * @author lastwhisper - */ -public class ClassLoaderUnique { - - /** - * 对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立 - * 其在Java虚拟机中的唯一性,每一个类加载器,都有一个独立的名称空间。 - * 即,两个类来自同一个Class文件,被同一个虚拟机加载,只要类加载器不同,两个类就不相等。 - * 不相等包括:equals()、isAssignableFrom()、isInstance()、instanceof - * @author lastwhisper - */ - public static void main(String[] args) throws Exception { - ClassLoader classLoader = new ClassLoader() { - @Override - public Class loadClass(String name) throws ClassNotFoundException { - try { - String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class"; - InputStream is = getClass().getResourceAsStream(fileName); - if (is == null) { - return super.loadClass(name); - } - byte[] b = new byte[is.available()]; - is.read(b); - return defineClass(name, b, 0, b.length); - } catch (IOException e) { - - throw new ClassNotFoundException(name); - } - - } - }; - - Object obj = classLoader.loadClass("cn.lastwhisper.cn.lastwhisper.javabasic.ClassLoader.ClassLoaderUnique").newInstance(); - - System.out.println(obj.getClass()); - // obj由自定义的类加载器加载、cn.lastwhisper.cn.lastwhisper.javabasic.ClassLoader.ClassLoaderTest由系统类加载器加载的。 - System.out.println(obj instanceof ClassLoaderUnique); - - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/DemoObj.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/DemoObj.java deleted file mode 100644 index ba26a729..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/DemoObj.java +++ /dev/null @@ -1,10 +0,0 @@ -package cn.lastwhisper.jdk5.feature.classloader; - -/** - * @author lastwhisper - */ -public class DemoObj { - static { - System.out.println("类构造器"); - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/LoadDiff.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/LoadDiff.java deleted file mode 100644 index 783961d3..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/LoadDiff.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.lastwhisper.jdk5.feature.classloader; - -/** - * 隐式加载与显示加载 - * @author lastwhisper - */ -public class LoadDiff { - public static void main(String[] args) throws ClassNotFoundException { - // 在SpringIOC中,为了加快初始化速度,大量使用了延迟加载技术,使用ClassLoader不会执行“链接”、“初始化”的步骤。 - ClassLoader classLoader = DemoObj.class.getClassLoader(); - // 连接Mysql,注册驱动com.mysql.jdbc.Driver - //Class clazz = Class.forName("cn.lastwhisper.jdk5.feature.classloader.DemoObj"); - - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/custom/ClassLoader1.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/custom/ClassLoader1.java deleted file mode 100644 index a8b53d20..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/custom/ClassLoader1.java +++ /dev/null @@ -1,63 +0,0 @@ -package cn.lastwhisper.jdk5.feature.classloader.custom; - -import java.io.*; - -/** - * 自定义类加载器并证明双亲委派机制 - * 以及解释loadClass、findClass、defineClass的功能 - * resolveClass的功能以及resolveClass与forName的区别 - * @author lastwhisper - */ -public class ClassLoader1 extends ClassLoader { - - private String rootDir; - - public ClassLoader1(String rootDir) { - this.rootDir = rootDir; - } - - /** - * 重写loadClass会破坏双亲委派机制 - * 重写findClass不会破坏双亲委派机制 - * 不管重写loadClass还是findClass,都需要直接使用defineClass实现类加载 - * resolveClass用于链接(加载、链接、初始化) - * @param name - * @return java.lang.Class - */ - @Override - public Class findClass(String name) throws ClassNotFoundException { - byte[] bytes = loadClassData(name); - return defineClass(name, bytes, 0, bytes.length); - } - - private byte[] loadClassData(String className) { - // 获取class文件的路径 - String path = classNameToPath(className); - InputStream is = null; - ByteArrayOutputStream out = null; - try { - is = new FileInputStream(new File(path)); - out = new ByteArrayOutputStream(); - byte[] buffer = new byte[2048]; - int b = 0; - while ((b = is.read(buffer)) != -1) { - out.write(buffer, 0, b); - } - } catch (Exception e) { - e.printStackTrace(); - } finally { - try { - if (is != null) is.close(); - if (out != null) out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - return out.toByteArray(); - } - - private String classNameToPath(String className) { - return rootDir + File.separatorChar - + className.replace('.', File.separatorChar) + ".class"; - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/custom/Test.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/custom/Test.java deleted file mode 100644 index d0852ba2..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/custom/Test.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.jdk5.feature.classloader.custom; - -/** - * 用于测试 - * @author lastwhisper - */ -public class Test { - public static void main(String[] args) throws Exception { - ClassLoader1 classLoader1 = new ClassLoader1("D:\\code\\GitRepository\\JavaNotes\\java-basic\\jdk5\\target\\classes\\cn\\lastwhisper\\jdk5\\feature\\classloader\\custom\\"); - Class clazz1 = classLoader1.loadClass("cn.lastwhisper.jdk5.feature.classloader.DemoObj"); - //Class clazz1 = classLoader1.loadClass("DemoObj"); - Object obj = clazz1.newInstance(); - System.out.println(obj.getClass().getClassLoader()); - - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/encrypt/ClassLoader2.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/encrypt/ClassLoader2.java deleted file mode 100644 index 0299fca9..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/encrypt/ClassLoader2.java +++ /dev/null @@ -1,73 +0,0 @@ -package cn.lastwhisper.jdk5.feature.classloader.encrypt; - -import java.io.*; - -/** - * 讲解classloader的实际作用,如自定义类加载器加载加密的字节码文件 - * @author lastwhisper - */ -public class ClassLoader2 extends ClassLoader { - - public static void main(String[] args) throws Exception { - // 1. 将正常的.class文件加密 - //encryptClass(); - // 2. 加载并解密字节码.class文件 - decryptAndLoadClass(); - } - - @Override - protected Class findClass(String name) throws ClassNotFoundException { - String classPathFile = "D:\\code\\GitRepository\\JavaNotes\\java-basic\\jdk5\\src\\main\\java\\cn\\lastwhisper\\jdk5\\feature\\classloader\\encrypt\\ClassLoaderAttachment.class"; - try { - FileInputStream fis = new FileInputStream(classPathFile); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - // 将fos加密到fis - cypher(fis, bos); - byte[] bytes = bos.toByteArray(); - //return this.defineClass(bytes, 0, bytes.length); - return this.defineClass(name, bytes, 0, bytes.length); - }catch (Exception e) { - e.printStackTrace(); - } - return super.findClass(name); - } - - public static void decryptAndLoadClass()throws Exception { - ClassLoader2 classLoader2 = new ClassLoader2(); - // cn.lastwhisper.jdk5.feature.classloader.encrypt.ClassLoader2@5cad8086 - //Class clazz = classLoader2.loadClass("ClassLoaderAttachment"); - // sun.misc.Launcher$AppClassLoader@18b4aac2 - Class clazz = classLoader2.loadClass("cn.lastwhisper.jdk5.feature.classloader.encrypt.ClassLoaderAttachment"); - Object obj = clazz.newInstance(); - System.out.println(obj.getClass().getClassLoader()); - System.out.println(obj); - } - - // 将正常的.class文件加密 - public static void encryptClass() throws Exception { - String srcPath = "D:\\code\\GitRepository\\JavaNotes\\java-basic\\jdk5\\target\\classes\\cn\\lastwhisper\\jdk5\\feature\\classloader\\encrypt\\ClassLoaderAttachment.class"; - String destPath = "D:\\code\\GitRepository\\JavaNotes\\java-basic\\jdk5\\src\\main\\java\\cn\\lastwhisper\\jdk5\\feature\\classloader\\encrypt\\ClassLoaderAttachment.class"; - FileInputStream fis = new FileInputStream(srcPath); - FileOutputStream fos = new FileOutputStream(destPath); - // 将fis加密到fos - cypher(fis, fos); - fis.close(); - fos.close(); - } - - // 异或加密解密 - public static void cypher(InputStream istream, OutputStream ostream) throws Exception { - //下面这段代码可能遇到255的字节,当成byte就成了-1 - /*byte b = 0; - while((b = (byte)istream.read()) != -1) - { - ostream.write(b ^ 0xff); - }*/ - - int b = 0; - while ((b = istream.read()) != -1) { - ostream.write(((byte) b) ^ 0xff); - } - } - -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/encrypt/ClassLoaderAttachment.class b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/encrypt/ClassLoaderAttachment.class deleted file mode 100644 index f4ffbeef..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/encrypt/ClassLoaderAttachment.class +++ /dev/null @@ -1 +0,0 @@ -5EA�����������������������Ö��������֩���������𳖑����������������������������������������������Г����������Е���Й������М����������К������м������������������������������������ֳ����Г���Ь���������������������弓�������������������ѕ����������췚���߻���ߋ������������Г����������Е���Й������М����������К������м����������������������񕞉�Њ���л��������������������������������������H��N����������������������������������������������������������O�������������������������������������������� \ No newline at end of file diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/encrypt/ClassLoaderAttachment.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/encrypt/ClassLoaderAttachment.java deleted file mode 100644 index d1bcbca5..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/encrypt/ClassLoaderAttachment.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.lastwhisper.jdk5.feature.classloader.encrypt; - -import java.util.Date; - -/** - * 继承Date是有原因的!!!自己定义的类加载器还原字节码后,创建的对象由Date变量接收。 - * @author lastwhisper - */ -public class ClassLoaderAttachment extends Date { - @Override - public String toString() { - return "Hello Date toString"; - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/hotdeploy/ClassLoaderHotDeploy.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/hotdeploy/ClassLoaderHotDeploy.java deleted file mode 100644 index f858ae1c..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/hotdeploy/ClassLoaderHotDeploy.java +++ /dev/null @@ -1,93 +0,0 @@ -package cn.lastwhisper.jdk5.feature.classloader.hotdeploy; - -import java.io.ByteArrayOutputStream; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.HashSet; -import java.util.Set; -import java.util.Timer; -import java.util.TimerTask; - -/** - * 代码热部署 - * @author lastwhisper - */ -public class ClassLoaderHotDeploy { - - - public static void main(String[] args) { - new Timer().schedule(new TimerTask() { - @Override - public void run() { - String path = MyClassLoader.class.getResource("").getPath(); - System.out.println(path); - String className = "cn.lastwhisper.jdk5.feature.classloader.hotdeploy.HotCodeTest"; - - Set set = new HashSet<>(); - set.add(className); - - MyClassLoader myClassLoader = new MyClassLoader(path, set); - - try { - Object object = myClassLoader.loadClass(className).newInstance(); - object.getClass().getMethod("printVersion").invoke(object); - } catch (Exception e) { - e.printStackTrace(); - } - - - } - }, 0, 2000); - } - - -} - -class MyClassLoader extends ClassLoader { - // 用于读取.class文件的路径 - private String path; - // 用于标记这些name的类是先由自身加载的 - private Set useMyClassLoader; - - public MyClassLoader(String path, Set useMyClassLoader) { - this.path = path; - this.useMyClassLoader = useMyClassLoader; - } - - @Override - public Class loadClass(String name) throws ClassNotFoundException { - Class c = findLoadedClass(name); - if (c == null && useMyClassLoader.contains(name)) { - c = findClass(name); - if (c != null) { - return c; - } - } - return super.loadClass(name); - } - - @Override - protected Class findClass(String name) { - //根据文件系统路径加载class文件,并返回byte数组 - byte[] classBytes = getClassByte(name); - //调用ClassLoader提供的方法,将二进制数组转换成Class类的实例 - return defineClass(name, classBytes, 0, classBytes.length); - } - - private byte[] getClassByte(String name) { - String className = name.substring(name.lastIndexOf('.') + 1, name.length()) + ".class"; - try { - FileInputStream fileInputStream = new FileInputStream(path + className); - byte[] buffer = new byte[1024]; - int length = 0; - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - while ((length = fileInputStream.read(buffer)) > 0) { - byteArrayOutputStream.write(buffer, 0, length); - } - return byteArrayOutputStream.toByteArray(); - } catch (IOException e) { - e.printStackTrace(); - } - return new byte[]{}; - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/hotdeploy/HotCodeTest.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/hotdeploy/HotCodeTest.java deleted file mode 100644 index ead8326b..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/classloader/hotdeploy/HotCodeTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package cn.lastwhisper.jdk5.feature.classloader.hotdeploy; - -public class HotCodeTest { - public void printVersion(){ - System.out.println("当前版本是2哦"); - } -} \ No newline at end of file diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/ArrayListGrowTest.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/ArrayListGrowTest.java deleted file mode 100644 index 267eb3ec..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/ArrayListGrowTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.lastwhisper.jdk5.feature.collection; - -import cn.lastwhisper.jdk5.feature.reflect.ReflectUtils; -import org.junit.Assert; - -import java.util.ArrayList; - -/** - * 测试ArrayList的扩容机制 - * @author lastwhisper - * @date 2019/10/24 - */ -public class ArrayListGrowTest { - /** - * 创建ArrayList不指定初始容量,第一次add时直接扩容到DEFAULT_CAPACITY=10 - * 所以如果能确定ArrayList的大小一定要指定初始容量 - * - * add逻辑: - * ensureCapacityInternal——确保内部需要的容量够用minCapacity=size + 1 - * calculateCapacity——判断ArrayList是否是第一次创建且未指定初始容量,如果是minCapacity=DEFAULT_CAPACITY - * ensureExplicitCapacity——minCapacity>elementData.length,扩容1.5*elementData.length - */ - public static void main(String[] args) { - ArrayList arrayList = new ArrayList<>(); - - Object[] elementData = (Object[]) ReflectUtils.getValue(arrayList, "elementData"); - Assert.assertEquals(0, elementData.length); - - // 此处应该扩容 0->10 - arrayList.add(1); - elementData = (Object[]) ReflectUtils.getValue(arrayList, "elementData"); - Assert.assertEquals(10, elementData.length); - arrayList.add(2); - arrayList.add(3); - arrayList.add(4); - arrayList.add(5); - arrayList.add(6); - arrayList.add(7); - arrayList.add(8); - arrayList.add(9); - arrayList.add(10); - // 此处应该扩容 10->15 - arrayList.add(11); - arrayList.add(12); - - - elementData = (Object[]) ReflectUtils.getValue(arrayList, "elementData"); - Assert.assertEquals(15, elementData.length); - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/ArraysAsList.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/ArraysAsList.java deleted file mode 100644 index 62b2f552..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/ArraysAsList.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.lastwhisper.jdk5.feature.collection; - -import org.junit.Test; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * 数组与集合的转换 - * @author lastwhisper - */ -public class ArraysAsList { - /** - * 将String数组转为集合 - */ - @Test - public void testStringArrAsList(){ - String[] stringArray = new String[3]; - stringArray[0] = "one"; - stringArray[1] = "two"; - stringArray[2] = "three"; - - List stringList = Arrays.asList(stringArray); - // 修改集合中的元素,数组会发生变化 - stringList.set(0,"oneList"); - System.out.println(stringArray[0]); - // 修改数组中的元素,集合会发生变化 - stringArray[1] = "twoArr"; - System.out.println(stringList.get(1)); - } - - @Test - public void testIntArrAsList(){ - int[] intArr = {1,2,3}; - String[] stringArr = {"1","2","3"}; - System.out.println(intArr.getClass()); //class [I - System.out.println(stringArr.getClass()); //class [Ljava.lang.String - List intList = Arrays.asList(intArr); - List stringList = Arrays.asList(stringArr); - - } - - -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/LRUCache.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/LRUCache.java deleted file mode 100644 index 4517011f..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/LRUCache.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.lastwhisper.jdk5.feature.collection; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * @author lastwhisper - */ -public class LRUCache extends LinkedHashMap { - private static final int MAX_ENTRIES = 3; - - LRUCache() { - super(MAX_ENTRIES, 0.75f, true); - } - - @Override - protected boolean removeEldestEntry(Map.Entry eldest) { - boolean flag = size() > MAX_ENTRIES; - if (flag) { - System.out.println("移除的key=" + eldest.getKey()); - } - return flag; - } - - public static void main(String[] args) { - LRUCache cache = new LRUCache<>(); - cache.put(1, "a"); - cache.put(2, "b"); - cache.put(3, "c");//1,2,3 - cache.get(1);//2,3,1 - cache.put(4, "d");//3,1,4 - System.out.println(cache.keySet()); - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/SafeHashMapDemo.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/SafeHashMapDemo.java deleted file mode 100644 index 20fb6e84..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/SafeHashMapDemo.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.lastwhisper.jdk5.feature.collection; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * @author lastwhisper - */ -public class SafeHashMapDemo { - public static void main(String[] args){ - Map hashMap = new HashMap<>(); - Map synchronizedMap = Collections.synchronizedMap(hashMap); - synchronizedMap.put("map","1"); - synchronizedMap.put("list","2"); - System.out.println(synchronizedMap.get("map")); - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/TestList.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/TestList.java deleted file mode 100644 index ea787357..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/TestList.java +++ /dev/null @@ -1,119 +0,0 @@ -package cn.lastwhisper.jdk5.feature.collection; - -import org.junit.Assert; -import org.junit.Test; - -import java.util.*; - -/** - * @author lastwhisper - */ -public class TestList { - - public static class modification extends Thread { - private List arrayList; - - public modification(List arrayList) { - this.arrayList = arrayList; - } - - @Override - public void run() { - // 需要同步机制 - Iterator iterator = arrayList.iterator(); - while (iterator.hasNext()) { - String data = iterator.next(); - if ("a".equals(data)) { - iterator.remove();//Exception in thread "Thread-1" java.util.ConcurrentModificationException - } - System.out.print(Thread.currentThread().getId() + " " + data + "\n"); - } - } - } - - // 测试ArrayList在创建迭代器后,使用iterator.remove()并发修改 - @Test - public void testThreadFailFast() { - List arrayList = new ArrayList<>(); - arrayList.add("a"); - arrayList.add("b"); - arrayList.add("c"); - arrayList.add("d"); - new modification(arrayList).start(); - new modification(arrayList).start(); - new modification(arrayList).start(); - } - - // 测试ArrayList在创建迭代器后,使用iterator.remove()单线程修改 - // fail-fast - @Test - public void testArrayList() { - List arrayList = new ArrayList<>(); - arrayList.add("a"); - arrayList.add("b"); - arrayList.add("c"); - arrayList.add("d"); - //for (String data : arrayList) { - // if (data.equals("a")) { - // arrayList.remove("a"); - // } - // System.out.println(data); - //} - - //Iterator iterator = arrayList.iterator(); - //while (iterator.hasNext()) { - // String data = iterator.next(); - // if (data.equals("a")) { - // arrayList.remove("a"); - // } - // System.out.println(data); - //} - - Iterator iterator = arrayList.iterator(); - while (iterator.hasNext()) { - String data = iterator.next(); - if (data.equals("a")) { - iterator.remove(); - } - System.out.println(data); - } - System.out.println("size=" + arrayList.size()); - } - - @Test - public void testLinkedList() { - List linkedList = new LinkedList<>(); - linkedList.add("a"); - linkedList.add("b"); - linkedList.add("c"); - linkedList.add("d"); - - Iterator iterator = linkedList.iterator(); - while (iterator.hasNext()) { - String data = iterator.next(); - if (data.equals("a")) { - linkedList.remove("a"); - } - System.out.println(data); - } - System.out.println("size=" + linkedList.size()); - } - - /** - * 测试集合的并交差集操作 - */ - @Test - public void testUnion() { - List list1 = new ArrayList<>(); - list1.add("1"); - list1.add("2"); - List list2 = new ArrayList<>(); - list2.add("1"); - list2.add("3"); - list1.retainAll(list2) ; - Objects.requireNonNull(list1); - //Assert.assertNotNull(list1); - list1.forEach(System.out::println); - } - -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/TestMap.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/TestMap.java deleted file mode 100644 index ca6f19d8..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/TestMap.java +++ /dev/null @@ -1,146 +0,0 @@ -package cn.lastwhisper.jdk5.feature.collection; - -import org.junit.Test; - -import java.util.*; - -/** - * @author lastwhisper - */ -public class TestMap { - - static class Person { - public Long id; - public String name; - - public Person(Long id, String name) { - this.id = id; - this.name = name; - } - - } - - /* - * JDK1.7 - * 为什么要用数组+链表? - * 1、Object的hashcode太大 - * 2、为什么冲突后插到链表的头部?效率快 - * 3、为什么数组的大小是2^n? - * indexFor函数算下标 (范围 00001111),hashcode高位怎么变都不影响结果 - * &比%快 - * 4、hashmap的扩容机制 - * 在元素插入之前扩容 - * 扩容——》空间换时间 - * put——addEntry——resize——transfer(transfer会导致倒序) - * transfer多线程扩容会出现循环链表 - * transfer中的indexFor会将原链表中元素打散 - * - * 5、getEntry - * if (e.hash == hash && - * ((k = e.key) == key || (key != null && key.equals(k)))) - * 为什么重写equals方法,一定要重写hashcode方法 - * 对象做hashmap做key,要声明成final - * - * 6、public HashMap(int initialCapacity, float loadFactor)什么时候用? - * 解决循环链表,不让hashmap扩容 - * - * JDK1.8 - * 为什么要用数组+链表(红黑树)? - * 新元素加到尾结点 - * hashmap的扩容机制 - * - * 在元素插入之后扩容 - * put——resize - * - * - */ - @Test - public void testHashMap() { - HashMap hashMap = new HashMap<>(); - hashMap.put(null, null); - /* - * put方法 - * 1、key==null单独处理 - * putForNullKey,null没有hash值,强制放到table[0] - * 2、key已经存在覆盖value,并返回oldValue; - * 不存在addEntry头插法,添加新value,返回null - * - */ - String a1 = hashMap.put("a", "old"); - String a2 = hashMap.put("a", "new"); - System.out.println(a1 + "\t" + a2); - hashMap.get("a"); - } - - /** - * 测试hashmap去集合重 - */ - @Test - public void testHashList() { - HashSet set = new HashSet<>(); - List list1 = new ArrayList<>(); - list1.add(1); - list1.add(2); - list1.add(3); - List list2 = new ArrayList<>(); - list2.add(1); - list2.add(2); - list2.add(3); - List list3 = new ArrayList<>(); - list3.add(1); - list3.add(2); - list3.add(2); - - set.add(list1); - set.add(list2); - set.add(list3); - System.out.println(set.size()); - } - - /** - * LinkedHashMap可以保证put的kv有序 - * - */ - @Test - public void testLinkedHashMap() { - LinkedHashMap linkedHashMap = new LinkedHashMap<>(); - linkedHashMap.put(1L, "1"); - linkedHashMap.put(4L, "4"); - linkedHashMap.put(3L, "3"); - linkedHashMap.put(7L, "7"); - for (Map.Entry entry : linkedHashMap.entrySet()) { - System.out.println(entry.getKey() + "\t" + entry.getValue()); - } - } - - /** - * TreeMap可以保证put的kv有序 - * 按key实现的comparable接口的compareTo方法规则进行排序 - */ - @Test - public void testTreeMap() { - TreeMap treeMap = new TreeMap<>(); - treeMap.put(1L, "1"); - treeMap.put(4L, "4"); - treeMap.put(3L, "3"); - treeMap.put(7L, "7"); - for (Map.Entry entry : treeMap.entrySet()) { - System.out.println(entry.getKey() + "\t" + entry.getValue()); - } - } - - /** - * TreeMap的key一定要重写comparable接口 - * 因为在插入时key需要比较顺序 - */ - @Test - public void testTreeMapKeyNoComparable() { - //java.lang.ClassCastException: - // Person cannot be cast to class java.lang.Comparable - TreeMap treeMap = new TreeMap(); - Person tom = new Person(1L, "tom"); - treeMap.put(tom, 1L); - } - - -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/TestPriorityQueue.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/TestPriorityQueue.java deleted file mode 100644 index be2b41cb..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/collection/TestPriorityQueue.java +++ /dev/null @@ -1,59 +0,0 @@ -package cn.lastwhisper.jdk5.feature.collection; - -import org.junit.Test; - -import java.util.Comparator; -import java.util.PriorityQueue; -import java.util.Queue; - -/** - * 优先队列 - * @author lastwhisper - * @date 1/18/2020 - */ -public class TestPriorityQueue { - - //自定义比较器,降序排列 - static Comparator comparator = new Comparator() { - public int compare(Integer e1, Integer e2) { - return e2 - e1; - } - }; - - /** - * peek()//返回队首元素 - * poll()//返回队首元素,队首元素出队列 - * add()//添加元素 - * size()//返回队列元素个数 - * isEmpty()//判断队列是否为空,为空返回true,不空返回false - */ - @Test - public void testTPriority() { - //不用比较器,默认升序排列 - Queue q = new PriorityQueue<>(); - q.add(3); - q.add(2); - q.add(4); - while (!q.isEmpty()) { - System.out.print(q.poll() + " "); - } - System.out.println(); - /* - * 输出结果 - * 2 3 4 - */ - //使用自定义比较器,降序排列 - Queue qq = new PriorityQueue<>(comparator); - qq.add(3); - qq.add(2); - qq.add(4); - while (!qq.isEmpty()) { - System.out.print(qq.poll() + " "); - } - /* - * 输出结果 - * 4 3 2 - */ - } - -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/Client.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/Client.java deleted file mode 100644 index 275a9190..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/Client.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.lastwhisper.jdk5.feature.generic.Generic4; - -/** - * 该层模拟service - * @author lastwhisper - */ -public class Client { - public static void main(String[] args) { - Person person = new Person(); - person.setId(1L); - person.setName("张三"); - // 交给Spring的IOC容器管理 - PersonDao personDao = new PersonDaoImpl(); - // 持久化到数据库 - personDao.save(person); - - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/Person.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/Person.java deleted file mode 100644 index 23c154bf..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/Person.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.lastwhisper.jdk5.feature.generic.Generic4; - -public class Person { - - // 编号 - private Long id; - - // 姓名 - private String name; - - public Person() { - } - - public Person(Long id, String name) { - this.id = id; - this.name = name; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public String toString() { - return "Person [id=" + id + ", name=" + name + "]"; - } - -} \ No newline at end of file diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/PersonDao.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/PersonDao.java deleted file mode 100644 index 9542399b..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/generic/Generic4/PersonDao.java +++ /dev/null @@ -1,8 +0,0 @@ -package cn.lastwhisper.jdk5.feature.generic.Generic4; - -/** - * extends BaseDao是为了可以使用通用的方法 - * @author lastwhisper - */ -public interface PersonDao extends BaseDao { -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestBlockingNIO2.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestBlockingNIO2.java deleted file mode 100644 index a8ad8486..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestBlockingNIO2.java +++ /dev/null @@ -1,74 +0,0 @@ -package cn.lastwhisper.jdk5.feature.io.nio; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; - -import org.junit.Test; - -public class TestBlockingNIO2 { - - //客户端 - @Test - public void client() throws IOException{ - SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898)); - - FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ); - - ByteBuffer buf = ByteBuffer.allocate(1024); - - while(inChannel.read(buf) != -1){ - buf.flip(); - sChannel.write(buf); - buf.clear(); - } - - sChannel.shutdownOutput(); - - //接收服务端的反馈 - int len = 0; - while((len = sChannel.read(buf)) != -1){ - buf.flip(); - System.out.println(new String(buf.array(), 0, len)); - buf.clear(); - } - - inChannel.close(); - sChannel.close(); - } - - //服务端 - @Test - public void server() throws IOException{ - ServerSocketChannel ssChannel = ServerSocketChannel.open(); - - FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE); - - ssChannel.bind(new InetSocketAddress(9898)); - - SocketChannel sChannel = ssChannel.accept(); - - ByteBuffer buf = ByteBuffer.allocate(1024); - - while(sChannel.read(buf) != -1){ - buf.flip(); - outChannel.write(buf); - buf.clear(); - } - - //发送反馈给客户端 - buf.put("服务端接收数据成功".getBytes()); - buf.flip(); - sChannel.write(buf); - - sChannel.close(); - outChannel.close(); - ssChannel.close(); - } - -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestNIO_2.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestNIO_2.java deleted file mode 100644 index dd85e35a..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestNIO_2.java +++ /dev/null @@ -1,158 +0,0 @@ -package cn.lastwhisper.jdk5.feature.io.nio; - -import org.junit.Test; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.channels.SeekableByteChannel; -import java.nio.file.*; -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.attribute.DosFileAttributeView; - -public class TestNIO_2 { - - - //自动资源管理:自动关闭实现 AutoCloseable 接口的资源 - @Test - public void test8() { - try (FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ); - FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE)) { - - ByteBuffer buf = ByteBuffer.allocate(1024); - inChannel.read(buf); - - } catch (IOException e) { - - } - } - - /* - Files常用方法:用于操作内容 - SeekableByteChannel newByteChannel(Path path, OpenOption…how) : 获取与指定文件的连接,how 指定打开方式。 - DirectoryStream newDirectoryStream(Path path) : 打开 path 指定的目录 - InputStream newInputStream(Path path, OpenOption…how):获取 InputStream 对象 - OutputStream newOutputStream(Path path, OpenOption…how) : 获取 OutputStream 对象 - */ - @Test - public void test7() throws IOException { - SeekableByteChannel newByteChannel = Files.newByteChannel(Paths.get("1.jpg"), StandardOpenOption.READ); - - DirectoryStream newDirectoryStream = Files.newDirectoryStream(Paths.get("e:/")); - - for (Path path : newDirectoryStream) { - System.out.println(path); - } - } - - /* - Files常用方法:用于判断 - boolean exists(Path path, LinkOption … opts) : 判断文件是否存在 - boolean isDirectory(Path path, LinkOption … opts) : 判断是否是目录 - boolean isExecutable(Path path) : 判断是否是可执行文件 - boolean isHidden(Path path) : 判断是否是隐藏文件 - boolean isReadable(Path path) : 判断文件是否可读 - boolean isWritable(Path path) : 判断文件是否可写 - boolean notExists(Path path, LinkOption … opts) : 判断文件是否不存在 - public static A readAttributes(Path path,Class type,LinkOption... options) : 获取与 path 指定的文件相关联的属性。 - */ - @Test - public void test6() throws IOException { - Path path = Paths.get("e:/nio/hello7.txt"); -// System.out.println(Files.exists(path, LinkOption.NOFOLLOW_LINKS)); - - BasicFileAttributes readAttributes = Files.readAttributes(path, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS); - System.out.println(readAttributes.creationTime()); - System.out.println(readAttributes.lastModifiedTime()); - - DosFileAttributeView fileAttributeView = Files.getFileAttributeView(path, DosFileAttributeView.class, LinkOption.NOFOLLOW_LINKS); - - fileAttributeView.setHidden(false); - } - - /* - Files常用方法: - Path copy(Path src, Path dest, CopyOption … how) : 文件的复制 - Path createDirectory(Path path, FileAttribute … attr) : 创建一个目录 - Path createFile(Path path, FileAttribute … arr) : 创建一个文件 - void delete(Path path) : 删除一个文件 - Path move(Path src, Path dest, CopyOption…how) : 将 src 移动到 dest 位置 - long size(Path path) : 返回 path 指定文件的大小 - */ - @Test - public void test5() throws IOException { - Path path1 = Paths.get("e:/nio/hello2.txt"); - Path path2 = Paths.get("e:/nio/hello7.txt"); - - System.out.println(Files.size(path2)); - -// Files.move(path1, path2, StandardCopyOption.ATOMIC_MOVE); - } - - @Test - public void test4() throws IOException { - Path dir = Paths.get("e:/nio/nio2"); -// Files.createDirectory(dir); - - Path file = Paths.get("e:/nio/nio2/hello3.txt"); -// Files.createFile(file); - - Files.deleteIfExists(file); - } - - @Test - public void test3() throws IOException { - Path path1 = Paths.get("e:/nio/hello.txt"); - Path path2 = Paths.get("e:/nio/hello2.txt"); - - Files.copy(path1, path2, StandardCopyOption.REPLACE_EXISTING); - } - - /* - Paths 提供的 get() 方法用来获取 Path 对象: - Path get(String first, String … more) : 用于将多个字符串串连成路径。 - Path 常用方法: - boolean endsWith(String path) : 判断是否以 path 路径结束 - boolean startsWith(String path) : 判断是否以 path 路径开始 - boolean isAbsolute() : 判断是否是绝对路径 - Path getFileName() : 返回与调用 Path 对象关联的文件名 - Path getName(int idx) : 返回的指定索引位置 idx 的路径名称 - int getNameCount() : 返回Path 根目录后面元素的数量 - Path getParent() :返回Path对象包含整个路径,不包含 Path 对象指定的文件路径 - Path getRoot() :返回调用 Path 对象的根路径 - Path resolve(Path p) :将相对路径解析为绝对路径 - Path toAbsolutePath() : 作为绝对路径返回调用 Path 对象 - String toString() : 返回调用 Path 对象的字符串表示形式 - */ - @Test - public void test2() { - Path path = Paths.get("e:/nio/hello.txt"); - - System.out.println(path.getParent()); - System.out.println(path.getRoot()); - -// Path newPath = path.resolve("e:/hello.txt"); -// System.out.println(newPath); - - Path path2 = Paths.get("1.jpg"); - Path newPath = path2.toAbsolutePath(); - System.out.println(newPath); - - System.out.println(path.toString()); - } - - @Test - public void test1() { - Path path = Paths.get("e:/", "nio/hello.txt"); - - System.out.println(path.endsWith("hello.txt")); - System.out.println(path.startsWith("e:/")); - - System.out.println(path.isAbsolute()); - System.out.println(path.getFileName()); - - for (int i = 0; i < path.getNameCount(); i++) { - System.out.println(path.getName(i)); - } - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestNonBlockingNIO.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestNonBlockingNIO.java deleted file mode 100644 index d397aff4..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestNonBlockingNIO.java +++ /dev/null @@ -1,96 +0,0 @@ -package cn.lastwhisper.jdk5.feature.io.nio; - -import org.junit.Test; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; -import java.util.Date; -import java.util.Iterator; -import java.util.Scanner; -/** - * TCP - */ -public class TestNonBlockingNIO { - //客户端 - @Test - public void client() throws IOException { - //1.获取通道 - SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898)); - //2.切换非阻塞模式 - sChannel.configureBlocking(false); - //3.分配指定大小的缓冲区 - ByteBuffer buf = ByteBuffer.allocate(1024); - //4.发送数据给服务端 - Scanner scan = new Scanner(System.in); - while (scan.hasNext()) { - String str = scan.next(); - buf.put((new Date().toString() + "\n" + str).getBytes()); - buf.flip(); - sChannel.write(buf); - buf.clear(); - } - //5.关闭通道 - sChannel.close(); - } - - //服务端 - @Test - public void server() throws IOException { - //1.获取通道 - ServerSocketChannel ssChannel = ServerSocketChannel.open(); - - //2.切换非阻塞式模式 - ssChannel.configureBlocking(false); - - //3.绑定连接 - ssChannel.bind(new InetSocketAddress(9898)); - - //4.获取选择器 - Selector selector = Selector.open(); - - //5.将通道注册到选择器上,并且指定“监听接收事件” - ssChannel.register(selector, SelectionKey.OP_ACCEPT); - - //6.轮询式的获取选择器上已经“准备就绪”的事件 - while (selector.select() > 0) { - - //7.获取当前选择器中所有注册的“选择键(已就绪的监听事件)” - Iterator it = selector.selectedKeys().iterator(); - - while (it.hasNext()) { - //8.获取准备“就绪”的事件 - SelectionKey sk = it.next(); - - //9.判断具体是什么时间准备就绪 - if (sk.isAcceptable()) { - //10.若“接收就绪”,获取客户端连接 - SocketChannel sChannel = ssChannel.accept(); - - //11.切换非阻塞模式 - sChannel.configureBlocking(false); - - //12.将该通道注册到选择器上 - sChannel.register(selector, SelectionKey.OP_READ); - } else if (sk.isReadable()) { - //13.获取当前选择器上“读就绪”状态的通道 - SocketChannel sChannel = (SocketChannel) sk.channel(); - //14.读取数据 - ByteBuffer buf = ByteBuffer.allocate(1024); - int len = 0; - while ((len = sChannel.read(buf)) > 0) { - buf.flip(); - System.out.println(new String(buf.array(), 0, len)); - buf.clear(); - } - } - //15.取消选择键SelectionKey - it.remove(); - } - } - } -} \ No newline at end of file diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestNonBlockingNIO2.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestNonBlockingNIO2.java deleted file mode 100644 index 90619e48..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/TestNonBlockingNIO2.java +++ /dev/null @@ -1,59 +0,0 @@ -package cn.lastwhisper.jdk5.feature.io.nio; - -import org.junit.Test; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.nio.channels.DatagramChannel; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.util.Date; -import java.util.Iterator; -import java.util.Scanner; -/** - * UDP - */ -public class TestNonBlockingNIO2 { - - @Test - public void send() throws IOException { - DatagramChannel dc = DatagramChannel.open(); - dc.configureBlocking(false); - ByteBuffer buf = ByteBuffer.allocate(1024); - Scanner scan = new Scanner(System.in); - while (scan.hasNext()) { - String str = scan.next(); - buf.put((new Date().toString() + "\n" + str).getBytes()); - buf.flip(); - dc.send(buf, new InetSocketAddress("127.0.0.1", 9898)); - buf.clear(); - } - dc.close(); - } - - @Test - public void receive() throws IOException { - DatagramChannel dc = DatagramChannel.open(); - dc.configureBlocking(false); - dc.bind(new InetSocketAddress(9898)); - Selector selector = Selector.open(); - dc.register(selector, SelectionKey.OP_READ); - while (selector.select() > 0) { - Iterator it = selector.selectedKeys().iterator(); - while (it.hasNext()) { - SelectionKey sk = it.next(); - - if (sk.isReadable()) { - ByteBuffer buf = ByteBuffer.allocate(1024); - dc.receive(buf) - ; - buf.flip(); - System.out.println(new String(buf.array(), 0, buf.limit())); - buf.clear(); - } - } - it.remove(); - } - } -} \ No newline at end of file diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v1/BIOServer.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v1/BIOServer.java deleted file mode 100644 index 2bb7559d..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v1/BIOServer.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.lastwhisper.jdk5.feature.io.nio.v1; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; - -/** - * @author lastwhisper - */ -public class BIOServer { - static byte[] bytes = new byte[1024]; - - public static void main(String[] args) { - try (ServerSocket serverSocket = new ServerSocket();){ - serverSocket.bind(new InetSocketAddress(8080)); - while (true){ - System.out.println("wait conn"); - // 等待连接阻塞 - Socket socket = serverSocket.accept(); - System.out.println("conn success"); - // 等待数据阻塞 - socket.getInputStream().read(bytes); - - System.out.println("data success"); - String content = new String(bytes); - System.out.println(content); - } - - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v1/Client.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v1/Client.java deleted file mode 100644 index b3912dee..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v1/Client.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.lastwhisper.jdk5.feature.io.nio.v1; - -import java.io.IOException; -import java.net.Socket; -import java.util.Scanner; - -/** - * 三个socket - * @author lastwhisper - */ -public class Client { - public static void main(String[] args) { - try (Socket socket = new Socket("127.0.0.1", 8080);) { - // client阻塞 等待数据 - Scanner scanner = new Scanner(System.in); - String txt = scanner.next(); - - socket.getOutputStream().write(txt.getBytes()); - - } catch (IOException e) { - e.printStackTrace(); - } - - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v2/MockNIOServer.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v2/MockNIOServer.java deleted file mode 100644 index 3576bd3b..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v2/MockNIOServer.java +++ /dev/null @@ -1,65 +0,0 @@ -package cn.lastwhisper.jdk5.feature.io.nio.v2; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; -import java.util.ArrayList; -import java.util.List; - -/** - * 单线程并发 - * 应用程序循环 - * @author lastwhisper - */ -public class MockNIOServer { - static List list = new ArrayList<>(); - static ByteBuffer byteBuffer = ByteBuffer.allocate(512); - - public static void main(String[] args) { - try { - ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); - serverSocketChannel.bind(new InetSocketAddress(8080)); - // 设置非阻塞 - serverSocketChannel.configureBlocking(false); - while (true) { - SocketChannel socketChannel = serverSocketChannel.accept(); - if (socketChannel == null) { - try { - Thread.sleep(500); - System.out.println("no conn"); - for (SocketChannel client : list) { - int length = client.read(byteBuffer); - if(length>0){ - byteBuffer.flip(); - // 处理业务 - String content = new String(byteBuffer.array()); - System.out.println(content); - } - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - }else { - System.out.println("conn-----------------------------"); - socketChannel.configureBlocking(false); - list.add(socketChannel); - for (SocketChannel client : list) { - int length = client.read(byteBuffer); - if(length>0){ - byteBuffer.flip(); - // 处理业务 - String content = new String(byteBuffer.array()); - System.out.println(content); - } - } - } - - } - - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v2/MyNIOServer.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v2/MyNIOServer.java deleted file mode 100644 index a4f17f06..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/v2/MyNIOServer.java +++ /dev/null @@ -1,53 +0,0 @@ -package cn.lastwhisper.jdk5.feature.io.nio.v2; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.util.ArrayList; -import java.util.List; - -/** - * 应用层做轮询 - * @author lastwhisper - */ -public class MyNIOServer { - static byte[] bytes = new byte[1024]; - static List list = new ArrayList<>(); - - public static void main(String[] args) { - try (ServerSocket serverSocket = new ServerSocket();) { - serverSocket.bind(new InetSocketAddress(8080)); - // 设置serverSocket非阻塞 - // serverSocket.setConfigureBlocking(false); - while (true) { - Socket socket = serverSocket.accept(); - if (socket == null) { - System.out.println("没有人连接"); - for (Socket s : list) { - int length = s.getInputStream().read(bytes); - if (length != 0) { - String content = new String(bytes); - System.out.println(content); - } - } - } else { - // 设置Socket非阻塞 - // socket.setConfigureBlocking(false); - list.add(socket); - for (Socket s : list) { - int length = s.getInputStream().read(bytes); - if (length != 0) { - String content = new String(bytes); - System.out.println(content); - } - } - } - - } - - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git "a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/\345\217\202\350\200\203" "b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/\345\217\202\350\200\203" deleted file mode 100644 index a4263056..00000000 --- "a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/nio/\345\217\202\350\200\203" +++ /dev/null @@ -1 +0,0 @@ -https://blog.csdn.net/zxm1306192988/article/details/60581173 diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/socket/LengthCalculator.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/socket/LengthCalculator.java deleted file mode 100644 index 4ae9b1b6..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/socket/LengthCalculator.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.lastwhisper.jdk5.feature.io.socket; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; - -/** - * @author lastwhisper - */ -public class LengthCalculator extends Thread { - private Socket socket; - - public LengthCalculator(Socket socket) { - this.socket = socket; - } - - @Override - public void run() { - // 获取socket的输出流 - // 获取socket的输入流 - try (OutputStream os = socket.getOutputStream(); - InputStream is = socket.getInputStream();) { - int ch = 0; - byte[] buff = new byte[1024]; - // buff主要用来读取输入的内容,存入byte数组,ch读取数组的长度 - ch = is.read(buff); - // 将接收的byte数组转成字符串 - String content = new String(buff, 0, ch); - System.out.println(content); - - os.write(String.valueOf(content.length()).getBytes()); - } catch (IOException e) { - e.printStackTrace(); - } - - } - -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/socket/TCPServer.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/socket/TCPServer.java deleted file mode 100644 index 7b9e48ab..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/io/socket/TCPServer.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.lastwhisper.jdk5.feature.io.socket; - -import java.io.IOException; -import java.net.ServerSocket; -import java.net.Socket; - -/** - * @author lastwhisper - */ -public class TCPServer { - public static void main(String[] args) { - try { - ServerSocket ss = new ServerSocket(65000); - while (true) { - // 监听请求 - Socket socket = ss.accept(); - new LengthCalculator(socket).start(); - } - } catch (IOException e) { - e.printStackTrace(); - } - - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/Proxy1.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/Proxy1.java deleted file mode 100644 index da20b74d..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/Proxy1.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.lastwhisper.jdk5.feature.proxy; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.Collection; - -/** - * 创建代理类,并查看其方法列表 - * @author lastwhisper - */ -public class Proxy1 { - public static void main(String[] args) throws Exception { - // 代理类 - Class proxyClass = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class); - // 构造方法 - Constructor[] constructors = proxyClass.getConstructors(); - for (Constructor constructor : constructors) { - System.out.println(constructor); - } - // 普通方法 - Method[] methods = proxyClass.getMethods(); - for (Method method : methods) { - System.out.println(method); - } - } - -} - diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/Proxy2.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/Proxy2.java deleted file mode 100644 index 51ee13a3..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/Proxy2.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.lastwhisper.jdk5.feature.proxy; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.Collection; - -/** - * 创建代理类的实例,并完善InvocationHandler - * @author lastwhisper - */ -public class Proxy2 { - public static void main(String[] args) throws Exception { - // 第一种方法、创建代理对象;使用有参构造 - Class proxyClass = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class); - Constructor constructor = proxyClass.getConstructor(InvocationHandler.class); - Collection proxy1 = (Collection) constructor.newInstance(new InvocationHandler() { - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - return null; - } - }); - proxy1.clear(); - // 为什么待返回值的方法会报错? - // 因为InvocationHandler的invoke方法返回值为null - //proxy1.size(); - - // 第二种方法、创建代理对象;使用Proxy提供的静态方法newProxyInstance - // 参数一:目标增强类的类加载器(用于加载代理类); - // 参数二:目标增强类的接口(代理类实现接口); - // 参数三:InvocationHandler执行增强代码和目标方法 - Collection proxy2 = (Collection) Proxy.newProxyInstance(Collection.class.getClassLoader(), - new Class[]{Collection.class}, - new InvocationHandler() { - ArrayList target = new ArrayList(); - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - long start = System.currentTimeMillis(); - // 使用反射调用目标对象的方法 - Object retVal = method.invoke(target, args); - long end = System.currentTimeMillis(); - System.out.println("性能监控:" + method.getName() + "方法耗时 " + (end - start)); - // 修改代理类的返回值(过滤器) - // retVal = false; - return retVal; - } - }); - boolean retVal = proxy2.add("普通代理"); - proxy2.add("静态代理"); - proxy2.add("动态代理"); - proxy2.add("CGLIB代理"); - //System.out.println(retVal); - System.out.println(proxy2.size()); - - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aop/Advice.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aop/Advice.java deleted file mode 100644 index 51bfd1fe..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aop/Advice.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.lastwhisper.jdk5.feature.proxy.aop; - -import java.lang.reflect.Method; - -/** - * 方法增强的接口 - */ -public interface Advice { - - void afterMethod(Method method); - - void beforeMethod(Method method); - -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aop/MonitorAdvice.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aop/MonitorAdvice.java deleted file mode 100644 index bce10a23..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aop/MonitorAdvice.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.lastwhisper.jdk5.feature.proxy.aop; - -import java.lang.reflect.Method; - -/** - * 性能监控 - * @author lastwhisper - */ -public class MonitorAdvice implements Advice { - - private long startTime; - private long endTime; - - public void beforeMethod(Method method) { - startTime = System.nanoTime(); - System.out.println(method.getDeclaringClass() + "." + method.getName() + "函数执行开始."); - } - - public void afterMethod(Method method) { - endTime = System.nanoTime(); - System.out.println(method.getDeclaringClass() + "." + method.getName() + "函数执行结束. 耗时:" + (endTime - startTime)); - } - - -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aop/Proxy3.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aop/Proxy3.java deleted file mode 100644 index 0ab5374d..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aop/Proxy3.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.lastwhisper.jdk5.feature.proxy.aop; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.Collection; - -/** - * 创建代理类的实例,并完善InvocationHandler - * @author lastwhisper - */ -public class Proxy3 { - public static void main(String[] args) throws Exception { - // 查看生成的代理类 - System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); - // 原类 - Collection list = new ArrayList(); - // 代理类 - Collection proxyClass = (Collection) getProxy(list, new MonitorAdvice()); - proxyClass.add("1111"); - proxyClass.add("2222"); - proxyClass.add("3333"); - System.out.println(proxyClass.size()); - } - - private static Object getProxy(final Object target, final Advice advice) { - // 目标增强类的类加载器(用于加载代理类); - // 目标增强类的接口(代理类实现接口); - // InvocationHandler执行增强代码和目标方法 - Object proxyClass = Proxy.newProxyInstance(target.getClass().getClassLoader(), - target.getClass().getInterfaces(), - new InvocationHandler() { - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - advice.beforeMethod(method); - Object obj = method.invoke(target, args); - advice.afterMethod(method); - return obj; - } - }); - return proxyClass; - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aopframework/AopFrameworkTest.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aopframework/AopFrameworkTest.java deleted file mode 100644 index 1d87fadb..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aopframework/AopFrameworkTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.lastwhisper.jdk5.feature.proxy.aopframework; - -import java.io.InputStream; -import java.util.Collection; - -public class AopFrameworkTest { - - /** - * @param args - */ - public static void main(String[] args) throws Exception { - InputStream ips = AopFrameworkTest.class.getClassLoader().getResourceAsStream("config.properties"); - Object bean = new BeanFactory(ips).getBean("xxx"); - System.out.println(bean.getClass().getName()); - Collection proxyClass = (Collection) bean; - proxyClass.add("1111"); - proxyClass.add("2222"); - proxyClass.add("3333"); - System.out.println(proxyClass.size()); - } - -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aopframework/BeanFactory.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aopframework/BeanFactory.java deleted file mode 100644 index ccb6c2b1..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aopframework/BeanFactory.java +++ /dev/null @@ -1,67 +0,0 @@ -package cn.lastwhisper.jdk5.feature.proxy.aopframework; - -import cn.lastwhisper.jdk5.feature.proxy.aop.Advice; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -/** - * - * @author lastwhisper - */ -public class BeanFactory { - Properties props = new Properties(); - - public BeanFactory(InputStream is) { - try { - props.load(is); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * 根据name判断是否增强bean - * - * @param name - * @return java.lang.Object - */ - public Object getBean(String name) { - String className = props.getProperty(name); - Class clazz = null; - Object bean = null; - try { - clazz = Class.forName(className); - bean = clazz.newInstance(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } - // - if (bean instanceof ProxyFactoryBean) { - ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean) bean; - Advice advice = null; - Object target = null; - try { - advice = (Advice) Class.forName(props.getProperty(name + ".advice")).newInstance(); - target = Class.forName(props.getProperty(name + ".target")).newInstance(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - //proxyFactoryBean.setAdvice(advice); - //proxyFactoryBean.setTarget(target); - // 代理对象 - return proxyFactoryBean.getProxy(target,advice); - } - return bean; - } - -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aopframework/ProxyFactoryBean.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aopframework/ProxyFactoryBean.java deleted file mode 100644 index ac8f5271..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/aopframework/ProxyFactoryBean.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.lastwhisper.jdk5.feature.proxy.aopframework; - -import cn.lastwhisper.jdk5.feature.proxy.aop.Advice; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - -/** - * - * @author lastwhisper - */ -public class ProxyFactoryBean { - - public Object getProxy(final Object target, final Advice advice) { - - Object proxyClass = Proxy.newProxyInstance(target.getClass().getClassLoader(), - target.getClass().getInterfaces(), - new InvocationHandler() { - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - advice.beforeMethod(method); - Object obj = method.invoke(target, args); - advice.afterMethod(method); - return obj; - } - }); - return proxyClass; - } - -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/$MyProxy0.class b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/$MyProxy0.class deleted file mode 100644 index bb007c93..00000000 Binary files a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/$MyProxy0.class and /dev/null differ diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/$MyProxy0.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/$MyProxy0.java deleted file mode 100644 index 74ee47ad..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/$MyProxy0.java +++ /dev/null @@ -1 +0,0 @@ -package cn.lastwhisper.jdk5.feature.proxy.myproxy; import java.lang.reflect.Method; public class $MyProxy0 implements cn.lastwhisper.jdk5.feature.proxy.myproxy.Man { MyInvocationHandler h; public $MyProxy0(MyInvocationHandler h) { this.h = h; } public void findObj() throws Throwable { Method method1 = cn.lastwhisper.jdk5.feature.proxy.myproxy.Man.class.getMethod("findObj", new Class[]{}); this.h.invoke(this, method1, null); } } \ No newline at end of file diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/LiuWang.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/LiuWang.java deleted file mode 100644 index 2be50ff5..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/LiuWang.java +++ /dev/null @@ -1,8 +0,0 @@ -package cn.lastwhisper.jdk5.feature.proxy.myproxy; - -public class LiuWang implements Man { - @Override - public void findObj() throws Throwable { - System.out.println("找个毛 写代码去吧!"); - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/Man.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/Man.java deleted file mode 100644 index 2d41fd6a..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/Man.java +++ /dev/null @@ -1,5 +0,0 @@ -package cn.lastwhisper.jdk5.feature.proxy.myproxy; - -public interface Man { - public void findObj() throws Throwable; -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/MyClassLoader.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/MyClassLoader.java deleted file mode 100644 index d79a1088..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/MyClassLoader.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.lastwhisper.jdk5.feature.proxy.myproxy; - -import org.springframework.util.FileCopyUtils; - -import java.io.File; -import java.io.IOException; - -public class MyClassLoader extends ClassLoader { - private File dir; - private String proxyClassPackage; - - public File getDir() { - return dir; - } - - public String getProxyClassPackage() { - return proxyClassPackage; - } - - public MyClassLoader(String path, String proxyClassPackage) { - this.dir = new File(path); - this.proxyClassPackage = proxyClassPackage; - } - - @Override - protected Class findClass(String name) throws ClassNotFoundException { - if(null != dir){ - File classFile = new File(dir, name + ".class"); - if(classFile.exists()){ - try { - byte[] classBytes = FileCopyUtils.copyToByteArray(classFile); - - return defineClass(proxyClassPackage + "." + name,classBytes,0, classBytes.length); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - return super.findClass(name); - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/MyHandler.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/MyHandler.java deleted file mode 100644 index 92aa64b5..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/MyHandler.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.lastwhisper.jdk5.feature.proxy.myproxy; - -import java.lang.reflect.Method; - -public class MyHandler implements MyInvocationHandler { - private Man man; - - public MyHandler(Man man) { - this.man = man; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - before(); - Object invoke = method.invoke(man, null); - after(); - return invoke; - } - - void before(){ - System.out.println("before"); - } - void after(){ - System.out.println("after"); - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/MyInvocationHandler.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/MyInvocationHandler.java deleted file mode 100644 index 01090fec..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/MyInvocationHandler.java +++ /dev/null @@ -1,7 +0,0 @@ -package cn.lastwhisper.jdk5.feature.proxy.myproxy; - -import java.lang.reflect.Method; - -public interface MyInvocationHandler { - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/MyProxy.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/MyProxy.java deleted file mode 100644 index d70386f2..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/MyProxy.java +++ /dev/null @@ -1,89 +0,0 @@ -package cn.lastwhisper.jdk5.feature.proxy.myproxy; - -import org.springframework.util.FileCopyUtils; - -import javax.tools.JavaCompiler; -import javax.tools.StandardJavaFileManager; -import javax.tools.ToolProvider; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; - -public class MyProxy { - private static final String rt = "\r"; - - public static Object newProxyInstance(MyClassLoader loader, Class interfaces, MyInvocationHandler h) throws IllegalArgumentException { - - if (null == h) { - throw new NullPointerException(); - } - //根据代理接口构造代理类 - Method[] methods = interfaces.getMethods(); - StringBuffer proxyClassString = new StringBuffer(); - proxyClassString.append("package ") - .append(loader.getProxyClassPackage()).append(";").append(rt) - .append("import java.lang.reflect.Method;").append(rt) - .append("public class $MyProxy0 implements ").append(interfaces.getName()).append("{").append(rt) - .append("MyInvocationHandler h;").append(rt) - .append("public $MyProxy0(MyInvocationHandler h){") - .append("this.h = h;}").append(rt) - .append(getMethodString(methods, interfaces)) - .append("}"); - //写入JAVA文件 进行编译 - String filename = loader.getDir() + File.separator + "$MyProxy0.java"; - File myProxyFile = new File(filename); - try { - compile(proxyClassString, myProxyFile); - - //利用自定义的classloader加载 - Class $myProxy0 = loader.findClass("$MyProxy0"); - //$MyProxy0初始化 - Constructor constructor = $myProxy0.getConstructor(MyInvocationHandler.class); - - Object o = constructor.newInstance(h); - - return o; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - private static String getMethodString(Method[] methods, Class interfaces) { - StringBuffer methodStringBuff = new StringBuffer(); - for (Method method : methods) { - methodStringBuff.append("public void ").append(method.getName()) - .append("()").append("throws Throwable{") - .append("Method method1 = ").append(interfaces.getName()) - .append(".class.getMethod(\"").append(method.getName()) - .append("\",new Class[]{});") - .append("this.h.invoke(this,method1,null);}").append(rt); - } - return methodStringBuff.toString(); - } - - /** - * @param proxyClassString 代理类的代码 - * @param myProxyFile 代理类的Java文件 - * @throws IOException - */ - private static void compile(StringBuffer proxyClassString, File myProxyFile) throws IOException { - // in out - FileCopyUtils.copy(proxyClassString.toString().getBytes(), myProxyFile); - // 调用系统编译器 - JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); - - StandardJavaFileManager standardJavaFileManager = javaCompiler.getStandardFileManager(null, null, null); - - Iterable javaFileObjects = standardJavaFileManager.getJavaFileObjects(myProxyFile); - - JavaCompiler.CompilationTask task = javaCompiler.getTask(null, standardJavaFileManager, null, null, null, javaFileObjects); - - task.call(); - - standardJavaFileManager.close(); - } - - -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/Test.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/Test.java deleted file mode 100644 index 4441daf5..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/proxy/myproxy/Test.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.lastwhisper.jdk5.feature.proxy.myproxy; - -public class Test { - public static void main(String[] args) throws Throwable { - Man man = new LiuWang(); - MyHandler myHandler = new MyHandler(man); - Man proxyMan = (Man) MyProxy.newProxyInstance( - new MyClassLoader( - "D:\\code\\GitRepository\\JavaNotes\\java-basic\\jdk5\\src\\main\\java\\cn\\lastwhisper\\jdk5\\feature\\proxy\\myproxy" - ,"cn.lastwhisper.jdk5.feature.proxy.myproxy") - ,Man.class, myHandler); - - - System.out.println(proxyMan.getClass().getName()); - proxyMan.findObj(); - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectForClass.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectForClass.java deleted file mode 100644 index 37ee4a1e..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectForClass.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.lastwhisper.jdk5.feature.reflect; - -/** - * 反射之Class对象 - * @author lastwhisper - */ -public class ReflectForClass { - public static void main(String[] args) throws ClassNotFoundException { - String str1 = "abc"; - Class cls1 = str1.getClass(); - Class cls2 = String.class; - Class cls3 = Class.forName("java.lang.String"); - System.out.println(cls1 == cls2); - System.out.println(cls1 == cls3); - - System.out.println(cls1.isPrimitive()); - System.out.println(int.class.isPrimitive()); - System.out.println(int.class == Integer.class); - System.out.println(int.class == Integer.TYPE); - System.out.println(int[].class.isPrimitive()); - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectUtils.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectUtils.java deleted file mode 100644 index 85abb840..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/ReflectUtils.java +++ /dev/null @@ -1,121 +0,0 @@ -package cn.lastwhisper.jdk5.feature.reflect; - -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; - -public class ReflectUtils { - /** - * 通过字段名从对象或对象的父类中得到字段的值 - * @param object 对象实例 - * @param fieldName 字段名 - * @return 字段对应的值 - */ - public static Object getValue(Object object, String fieldName) { - if (object == null) { - return null; - } - if ("".equals(fieldName)) { - return null; - } - Field field = null; - Class clazz = object.getClass(); - for (; clazz != Object.class; clazz = clazz.getSuperclass()) { - try { - field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - return field.get(object); - } catch (Exception e) { - //这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。 - //如果这里的异常打印或者往外抛,则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了 - } - } - return null; - } - - - /** - * 通过字段名从对象或对象的父类中得到字段的值(调用字典的get方法) - * @param object 对象实例 - * @param fieldName 字段名 - * @return 字段对应的值 - * @throws Exception - */ - public static Object getValueOfGet(Object object, String fieldName){ - if (object == null) { - return null; - } - if ("".equals(fieldName)) { - return null; - } - Field field; - Class clazz = object.getClass(); - for (; clazz != Object.class; clazz = clazz.getSuperclass()) { - try { - field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - - PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz); - //获得get方法 - Method getMethod = pd.getReadMethod(); - //执行get方法返回一个Object - return getMethod.invoke(object); - } catch (Exception e) { - //这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。 - //如果这里的异常打印或者往外抛,则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了 - } - } - - return null; - } - - /** - * 通过字段名从对象或对象的父类中得到字段的值(调用字典的get方法,可以取出复杂的对象的值) - * @param object 对象实例 - * @param fieldName 字段名 - * @return 字段对应的值 - * @throws Exception - */ - public static Object getValueOfGetIncludeObjectFeild(Object object, String fieldName) - throws Exception { - - if (object == null) { - return null; - } - if ("".equals(fieldName)) { - return null; - } - - if (HashMap.class.equals(object.getClass())) { - return ((Map) object).get(fieldName); - } - - Field field = null; - Class clazz = object.getClass(); - for (; clazz != Object.class; clazz = clazz.getSuperclass()) { - try { - if (fieldName.contains(".")) { - // 如:operatorUser.name、operatorUser.org.name,递归调用 - String[] splitFiledName = fieldName.split("\\."); - return getValueOfGetIncludeObjectFeild( - getValueOfGetIncludeObjectFeild(object, splitFiledName[0]), - splitFiledName[1]); - } - field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - - PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz); - //获得get方法 - Method getMethod = pd.getReadMethod(); - //执行get方法返回一个Object - return getMethod.invoke(object); - } catch (Exception e) { - //这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。 - //如果这里的异常打印或者往外抛,则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了 - } - } - return null; - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/TestClass.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/TestClass.java deleted file mode 100644 index 79992ab6..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/reflect/TestClass.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.lastwhisper.jdk5.feature.reflect; - -import com.thoughtworks.qdox.JavaDocBuilder; -import com.thoughtworks.qdox.model.JavaSource; - -import java.io.FileNotFoundException; -import java.io.FileReader; - -/** - * @author lastwhisper - */ -public class TestClass { - public static void main(String[] args) throws FileNotFoundException { - String fileFullPath = "D:\\code\\GitRepository\\Code\\java-basic\\jdk5\\src\\main\\java\\cn\\lastwhisper\\jdk5\\feature\\reflect\\TestClass.java"; - JavaDocBuilder builder = new JavaDocBuilder(); - builder.addSource(new FileReader(fileFullPath)); - - JavaSource src = builder.getSources()[0]; - String[] imports = src.getImports(); - - for (String imp : imports) { - System.out.println(imp); - } - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/serializable/Test.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/serializable/Test.java deleted file mode 100644 index 9f8d1636..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/serializable/Test.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.lastwhisper.jdk5.feature.serializable; - -import java.io.*; -/** - * 静态变量序列化 - */ -public class Test implements Serializable { - - private static final long serialVersionUID = 1L; - public static int staticVar = 5; - - public static void main(String[] args) { - try { - //初始时staticVar为5 - ObjectOutputStream out = new ObjectOutputStream( - new FileOutputStream("D:\\result.obj")); - out.writeObject(new Test()); - out.close(); - //序列化后修改为10 - Test.staticVar = 10; - ObjectInputStream oin = new ObjectInputStream(new FileInputStream( - "D:\\result.obj")); - Test t = (Test) oin.readObject(); - oin.close(); - //再读取,通过t.staticVar打印新的值 - // 打印10说明,序列化并没有保存static字段,如果保存了staticVar应该为5 - System.out.println(t.staticVar); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - } -} \ No newline at end of file diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/detail.txt b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/detail.txt deleted file mode 100644 index 47dec928..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/detail.txt +++ /dev/null @@ -1,2 +0,0 @@ -spi简单实现:http://www.spring4all.com/article/260 -https://www.jianshu.com/p/46b42f7f593c \ No newline at end of file diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/spi_boy/Boy.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/spi_boy/Boy.java deleted file mode 100644 index 5bec9614..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/spi_boy/Boy.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.lastwhisper.jdk5.feature.spi.spi_boy; - -import cn.lastwhisper.jdk5.feature.spi.spi_interface.People; - -/** - * spi-boy/spi-gril: 分别是两个厂商对interface的不同实现,所以他们会依赖于interface项目 - * @author lastwhisper - */ -public class Boy implements People { - @Override - public void sayHello() { - System.out.println("男孩说hello~~~"); - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/spi_client/Client.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/spi_client/Client.java deleted file mode 100644 index adbdd05a..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/spi_client/Client.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.lastwhisper.jdk5.feature.spi.spi_client; - -import cn.lastwhisper.jdk5.feature.spi.spi_interface.People; - -import java.util.ServiceLoader; - -/** - * 用来模拟用户测试, 依赖spi-core和spi-boy/spi-gril(至少一个实现,否则会报错) - * @author lastwhisper - */ -public class Client { - public static void main(String[] args) { - ServiceLoader serviceLoader = ServiceLoader.load(People.class); - for (People people : serviceLoader) { - people.sayHello(); - } - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/spi_core/PeopleFactory.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/spi_core/PeopleFactory.java deleted file mode 100644 index d4020792..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/spi_core/PeopleFactory.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.lastwhisper.jdk5.feature.spi.spi_core; - -import cn.lastwhisper.jdk5.feature.spi.spi_interface.People; - -import java.util.Iterator; -import java.util.ServiceLoader; - -/** - * spi-core: 是提供给用户使用的核心jar文件, - * 同样依赖于interface项目, 用户使用时需要引入spi-core.jar和厂商具体实现的jar - * @author lastwhisper - */ -public class PeopleFactory { - public void invoker(){ - ServiceLoader services = ServiceLoader.load(People.class); - Iterator iterator = services.iterator(); - boolean notFound = true; - while (iterator.hasNext()){ - notFound = false; - People people = iterator.next(); - people.sayHello(); - } - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/spi_gril/Gril.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/spi_gril/Gril.java deleted file mode 100644 index de41525c..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/spi_gril/Gril.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.lastwhisper.jdk5.feature.spi.spi_gril; - -import cn.lastwhisper.jdk5.feature.spi.spi_interface.People; - -/** - * spi-boy/spi-gril: 分别是两个厂商对interface的不同实现,所以他们会依赖于interface项目 - * @author lastwhisper - */ -public class Gril implements People { - @Override - public void sayHello() { - System.out.println("女孩说hello~~~"); - } -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/spi_interface/People.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/spi_interface/People.java deleted file mode 100644 index 57604eb4..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/spi/spi_interface/People.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.lastwhisper.jdk5.feature.spi.spi_interface; - -/** - * spi-interface: 是针对厂商定义的接口项目,只提供接口,不提供实现 - * @author lastwhisper - */ -public interface People { - void sayHello(); -} diff --git a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/throwable/ErrorAndException.java b/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/throwable/ErrorAndException.java deleted file mode 100644 index 148b3dd2..00000000 --- a/java-basic/jdk5/src/main/java/cn/lastwhisper/jdk5/feature/throwable/ErrorAndException.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.lastwhisper.jdk5.feature.throwable; - -import java.io.FileNotFoundException; - -/** - * 异常 - * @author lastwhisper - */ -public class ErrorAndException { - // Error - private void throwError(){ - throw new StackOverflowError(); - } - // uncheck exception - private void throwRuntimeException(){ - throw new RuntimeException(); - } - // check exception - - - private void throwCheckedException() throws FileNotFoundException { - throw new FileNotFoundException(); - } - - public static void main(String[] args) { - ErrorAndException errorAndException = new ErrorAndException(); - errorAndException.throwError(); - errorAndException.throwRuntimeException(); - // 受检查异常,声明throws FileNotFoundException或者try/catch - try { - errorAndException.throwCheckedException(); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - } -} diff --git a/java-basic/jdk5/src/main/resources/META-INF/services/cn.lastwhisper.jdk5.feature.spi.spi_interface.People b/java-basic/jdk5/src/main/resources/META-INF/services/cn.lastwhisper.jdk5.feature.spi.spi_interface.People deleted file mode 100644 index efd96406..00000000 --- a/java-basic/jdk5/src/main/resources/META-INF/services/cn.lastwhisper.jdk5.feature.spi.spi_interface.People +++ /dev/null @@ -1,2 +0,0 @@ -cn.lastwhisper.jdk5.feature.spi.spi_boy.Boy -cn.lastwhisper.jdk5.feature.spi.spi_gril.Gril \ No newline at end of file diff --git a/java-basic/jdk5/src/main/resources/config.properties b/java-basic/jdk5/src/main/resources/config.properties deleted file mode 100644 index 51072f6b..00000000 --- a/java-basic/jdk5/src/main/resources/config.properties +++ /dev/null @@ -1,7 +0,0 @@ -# -className=cn.lastwhisper.jdk5.feature.reflect.TestArrayArguments -# -#xxx=java.util.ArrayList -xxx=cn.lastwhisper.jdk5.feature.proxy.aopframework.ProxyFactoryBean -xxx.target=java.util.ArrayList -xxx.advice=cn.lastwhisper.jdk5.feature.proxy.aop.MonitorAdvice diff --git a/java-basic/jdk8/pom.xml b/java-basic/jdk8/pom.xml deleted file mode 100644 index 2f89273a..00000000 --- a/java-basic/jdk8/pom.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - java-basic - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - cn.lastwhisper - jdk8 - - - \ No newline at end of file diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/annotation/MyAnnotation.java b/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/annotation/MyAnnotation.java deleted file mode 100644 index ea240b5d..00000000 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/annotation/MyAnnotation.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.lastwhisper.jdk8.annotation; - -import java.lang.annotation.Repeatable; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.*; - -@Repeatable(MyAnnotations.class)//指定重复注解的容器 -@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, TYPE_PARAMETER})//可以修饰的目标 -@Retention(RetentionPolicy.RUNTIME)//生命周期 -public @interface MyAnnotation { - String value() default "java"; -} \ No newline at end of file diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/Employee.java b/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/Employee.java deleted file mode 100644 index 893470f3..00000000 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/Employee.java +++ /dev/null @@ -1,102 +0,0 @@ -package cn.lastwhisper.jdk8.lambda; - -import java.util.Objects; - -public class Employee { - - private Integer id; - private String name; - private Integer age; - private double salary; - - public Employee() { - } - - public Employee(Integer id) { - this.id = id; - } - - public Employee(String name) { - this.name = name; - } - - public Employee(String name, Integer age) { - this.name = name; - this.age = age; - } - - public Employee(String name, Integer age, double salary) { - this.name = name; - this.age = age; - this.salary = salary; - } - - public Employee(Integer id, String name, Integer age, double salary) { - this.id = id; - this.name = name; - this.age = age; - this.salary = salary; - } - - public Integer getId() { - return id; - } - - public void setId(Integer id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Integer getAge() { - return age; - } - - public void setAge(Integer age) { - this.age = age; - } - - public double getSalary() { - return salary; - } - - public void setSalary(double salary) { - this.salary = salary; - } - - public String show() { - return "测试方法引用!"; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Employee employee = (Employee) o; - return id.equals(employee.id) && - age.equals(employee.age) && - Double.compare(employee.salary, salary) == 0 && - Objects.equals(name, employee.name); - } - - @Override - public int hashCode() { - return Objects.hash(id, name, age, salary); - } - - @Override - public String toString() { - return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + "]"; - } - -} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/TestLambda.java b/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/TestLambda.java deleted file mode 100644 index 423c59ac..00000000 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/TestLambda.java +++ /dev/null @@ -1,137 +0,0 @@ -package cn.lastwhisper.jdk8.lambda; - -import cn.lastwhisper.jdk8.lambda.strategy.EmployeeAgeFilter; -import cn.lastwhisper.jdk8.lambda.strategy.EmployeeSalaryFilter; -import cn.lastwhisper.jdk8.lambda.strategy.Filter; -import org.junit.Test; - -import java.util.*; - -/** - * @author lastwhisper - */ -public class TestLambda { - List employees = Arrays.asList( - new Employee("张三", 18, 9496.2), - new Employee("李四", 52, 2396.2), - new Employee("王五", 56, 996.2), - new Employee("赵六", 38, 940.2) - ); - - // 原来匿名内部类 - @Test - public void testInnerClass() { - Comparator comparator = new Comparator() { - @Override - public int compare(Integer o1, Integer o2) { - return 0; - } - }; - - TreeSet treeSet = new TreeSet<>(comparator); - } - - // 将匿名内部类优化为lambda表达式 - @Test - public void testLambda() { - Comparator comparator = (o1, o2) -> Integer.compare(o1, o2); - TreeSet treeSet = new TreeSet<>(comparator); - } - - // 传统方式进行条件过滤 - @Test - public void test3() { - //需求:获取当前公司中员工年龄大于35的员工信息 - List emps = filterEmployeesByAge(employees); - for (Employee e : emps) { - System.out.println(e); - } - System.out.println("---------------------"); - - //需求:获取当前公司中员工工资大于2000的员工信息 - List emps2 = filterEmployeesBySalary(employees); - for (Employee e : emps2) { - System.out.println(e); - } - } - - public List filterEmployeesByAge(List list) { - List emps = new ArrayList<>(); - for (Employee emp : list) { - if (emp.getAge() >= 35) { - emps.add(emp); - } - } - return emps; - } - - public List filterEmployeesBySalary(List list) { - List emps = new ArrayList<>(); - for (Employee emp : list) { - if (emp.getSalary() >= 2000) { - emps.add(emp); - } - } - return emps; - } - - // test3 优化方式一:策略设计模式 - @Test - public void test4() { - List emps = filterEmployees(employees, new EmployeeAgeFilter()); - for (Employee e : emps) { - System.out.println(e); - } - System.out.println("---------------------"); - List emps2 = filterEmployees(employees, new EmployeeSalaryFilter()); - for (Employee e : emps2) { - System.out.println(e); - } - } - - public List filterEmployees(List list, Filter filter) { - List emps = new ArrayList(); - for (Employee emp : list) { - if (filter.eqCondition(emp)) { - emps.add(emp); - } - } - return emps; - } - - // test3 优化方式二:匿名内部类 - @Test - public void test5() { - List list = filterEmployees(employees, new Filter() { - @Override - public boolean eqCondition(Employee t) { - return t.getSalary() >= 2000; - } - }); - for (Employee employee : list) { - System.out.println(employee); - } - } - - // test3 优化方式三:Lambda表达式 - @Test - public void test6() { - List list = filterEmployees(employees, (e) -> e.getSalary() >= 2000); - list.forEach(System.out::println); - } - - // test3 优化方式四:stream API - @Test - public void test7(){ - employees.stream() - .filter((e)->e.getSalary()>=2000) - .forEach(System.out::println); - System.out.println("------------------"); - employees.stream() - .map(Employee::getName) - .forEach(System.out::println); - } - - - -} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/example/MyFun2.java b/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/example/MyFun2.java deleted file mode 100644 index 80415443..00000000 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/example/MyFun2.java +++ /dev/null @@ -1,11 +0,0 @@ -package cn.lastwhisper.jdk8.lambda.example; - -/** - * @author lastwhisper - */ -@FunctionalInterface -public interface MyFun2 { - - public String getValue(String str); - -} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/example/MyFun3.java b/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/example/MyFun3.java deleted file mode 100644 index c5690098..00000000 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/example/MyFun3.java +++ /dev/null @@ -1,8 +0,0 @@ -package cn.lastwhisper.jdk8.lambda.example; - -@FunctionalInterface -public interface MyFun3 { - - public R operation(T t1, T t2); - -} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/example/TestLambda.java b/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/example/TestLambda.java deleted file mode 100644 index 6bd36582..00000000 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/example/TestLambda.java +++ /dev/null @@ -1,93 +0,0 @@ -package cn.lastwhisper.jdk8.lambda.example; - -import cn.lastwhisper.jdk8.lambda.Employee; -import org.junit.Test; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * @author lastwhisper - */ -public class TestLambda { - - List emps = Arrays.asList( - new Employee(101, "a", 18, 9999.99), - new Employee(102, "b", 59, 6666.66), - new Employee(103, "c", 28, 3333.33), - new Employee(104, "d", 8, 7777.77), - new Employee(105, "e", 38, 5555.55) - ); - - /** - * 调用Collections.sort()方法,通过定制排序, - * 比较两个Employee(先按年龄比,年龄相同按姓名比),使用Lambda表达式作为参数传递。 - */ - @Test - public void test1() { - //Collections.sort(emps, new Comparator() { - // @Override - // public int compare(Employee o1, Employee o2) { - // if (o1.getAge() == o2.getAge()) { - // return o1.getName().compareTo(o2.getName()); - // } - // return o1.getAge() - o2.getAge(); - // } - //}); - - Collections.sort(emps, (o1, o2) -> { - if (o1.getAge() == o2.getAge()) { - return o1.getName().compareTo(o2.getName()); - } - return o1.getAge() - o2.getAge(); - }); - for (Employee emp : emps) { - System.out.println(emp); - } - } - - /** - * (1)声明函数式接口,接口中声明抽象方法:public String getValue(String str); - * (2)声明类LambdaTest,类中编写方法使用接口作为参数,将一个字符串转换成大写,并作为方法的返回值。 - * (3)再将一个字符串的第2个到第4个索引位置进行截取子串。 - */ - @Test - public void test2() { - String str = "abcde"; - System.out.println(bridge(str, x -> x.toUpperCase())); - System.out.println(bridge(str, x -> x.substring(2, 4))); - } - - public String bridge(String str, MyFun2 mf) { - return mf.getValue(str); - } - - /** - * (1)声明一个带两个泛型的函数式接口,泛型类型为 : T 为参数,R 为返回值。 - * (2)接口中声明对应抽象方法 - * (3)在LambdaTest类中声明方法,使用接口作为参数,计算两个long型参数的和。 - * (4)再计算两个long型参数的乘积 - */ - @Test - public void test3() { - Long num1 = 10l; - Long num2 = 15l; - System.out.println(bridge2(num1, num2, (x, y) -> x + y)); - System.out.println(bridge2(num1, num2, (x, y) -> x * y)); - } - - public Long bridge2(Long num1, Long num2, MyFun3 mf) { - return mf.operation(num1, num2); - } - - /** - * - */ - @Test - public void test4() { - - } - - -} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/strategy/EmployeeAgeFilter.java b/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/strategy/EmployeeAgeFilter.java deleted file mode 100644 index f8237951..00000000 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/strategy/EmployeeAgeFilter.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.jdk8.lambda.strategy; - -import cn.lastwhisper.jdk8.lambda.Employee; - -/** - * @author lastwhisper - */ -public class EmployeeAgeFilter implements Filter { - @Override - public boolean eqCondition(Employee employee) { - return employee.getAge() >= 35; - } -} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/strategy/EmployeeSalaryFilter.java b/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/strategy/EmployeeSalaryFilter.java deleted file mode 100644 index da8a9f55..00000000 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/strategy/EmployeeSalaryFilter.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.jdk8.lambda.strategy; - -import cn.lastwhisper.jdk8.lambda.Employee; - -/** - * @author lastwhisper - */ -public class EmployeeSalaryFilter implements Filter { - @Override - public boolean eqCondition(Employee employee) { - return employee.getSalary() >= 2000; - } -} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/strategy/Filter.java b/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/strategy/Filter.java deleted file mode 100644 index 23856998..00000000 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/lambda/strategy/Filter.java +++ /dev/null @@ -1,8 +0,0 @@ -package cn.lastwhisper.jdk8.lambda.strategy; - -/** - * 过滤接口 - */ -public interface Filter { - boolean eqCondition(T t); -} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/optional/Man.java b/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/optional/Man.java deleted file mode 100644 index a1f1ebf7..00000000 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/optional/Man.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.lastwhisper.jdk8.optional; - -public class Man { - - private Godness god; - - public Man() { - } - - public Man(Godness god) { - this.god = god; - } - - public Godness getGod() { - return god; - } - - public void setGod(Godness god) { - this.god = god; - } - - @Override - public String toString() { - return "Man [god=" + god + "]"; - } - -} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/Employee.java b/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/Employee.java deleted file mode 100644 index 65c5295a..00000000 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/Employee.java +++ /dev/null @@ -1,127 +0,0 @@ -package cn.lastwhisper.jdk8.stream; - - - -public class Employee { - - private Integer id; - private String name; - private Integer age; - private double salary; - private Status status; - - public Employee() { - } - - public Employee(String name) { - this.name = name; - } - - public Employee(String name, Integer age) { - this.name = name; - this.age = age; - } - - public Employee(Integer id, String name, Integer age, double salary) { - this.id = id; - this.name = name; - this.age = age; - this.salary = salary; - } - - public Employee(Integer id, String name, Integer age, double salary, Status status) { - this.id = id; - this.name = name; - this.age = age; - this.salary = salary; - this.status = status; - } - - public Status getStatus() { - return status; - } - - public void setStatus(Status status) { - this.status = status; - } - - public Integer getId() { - return id; - } - - public void setId(Integer id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Integer getAge() { - return age; - } - - public void setAge(Integer age) { - this.age = age; - } - - public double getSalary() { - return salary; - } - - public void setSalary(double salary) { - this.salary = salary; - } - - public String show() { - return "测试方法引用!"; - } - - @Override - public int hashCode() { - final Integer prime = 31; - Integer result = 1; - result = prime * result + age; - result = prime * result + id; - result = prime * result + ((name == null) ? 0 : name.hashCode()); - long temp; - temp = Double.doubleToLongBits(salary); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Employee other = (Employee) obj; - if (age != other.age) - return false; - if (id != other.id) - return false; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary)) - return false; - return true; - } - - @Override - public String toString() { - return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + ", status=" + status - + "]"; - } - - -} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/Status.java b/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/Status.java deleted file mode 100644 index 89bca775..00000000 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/Status.java +++ /dev/null @@ -1,5 +0,0 @@ -package cn.lastwhisper.jdk8.stream; - -public enum Status { - FREE, BUSY, VOCATION; -} \ No newline at end of file diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/TestStreamAPI.java b/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/TestStreamAPI.java deleted file mode 100644 index 48fe9468..00000000 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/TestStreamAPI.java +++ /dev/null @@ -1,53 +0,0 @@ -package cn.lastwhisper.jdk8.stream; - -import cn.lastwhisper.jdk8.lambda.Employee; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Stream; - -/* - * 一、Stream API 的操作步骤: - * 1. 创建 Stream - * 2. 中间操作 - * 3. 终止操作(终端操作) - */ -public class TestStreamAPI { - - /** - * 创建Stream - */ - @Test - public void test1() { - // 1.可以通过Collection 系列集合提供的stream()或parallelStream() - List list = new ArrayList<>(); - Stream stream1 = list.stream(); - - // 2.通过 Arrays 中的静态方法stream()获取数组流 - Employee[] emps = new Employee[10]; - Stream stream2 = Arrays.stream(emps); - - // 3.通过Stream 类中的静态方法of() - Stream stream3 = Stream.of("a", "b", "c"); - - // 4.创建无限流 - // 迭代 - Stream stream4 = Stream.iterate(0, (x) -> x + 2); - stream4.limit(10).forEach(System.out::println); - // 生成 - Stream.generate(Math::random) - .limit(5) - .forEach(System.out::println); - } - - @Test - public void test2(){ - Stream.of(1,2,3,4,5,6,7,8,9) - .parallel(); - Stream.of(1,2,3,4,5,6,7,8,9) - .sequential(); - } - -} diff --git a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/example/TestStreamAPI.java b/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/example/TestStreamAPI.java deleted file mode 100644 index 6083dcb4..00000000 --- a/java-basic/jdk8/src/main/java/cn/lastwhisper/jdk8/stream/example/TestStreamAPI.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.lastwhisper.jdk8.stream.example; - -import cn.lastwhisper.jdk8.stream.Employee; -import cn.lastwhisper.jdk8.stream.Status; -import org.junit.Test; - -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.stream.Stream; - -/** - * @author lastwhisper - */ -public class TestStreamAPI { - - List emps = Arrays.asList( - new Employee(102, "李四", 59, 6666.66, Status.BUSY), - new Employee(101, "张三", 18, 9999.99, Status.FREE), - new Employee(103, "王五", 28, 3333.33, Status.VOCATION), - new Employee(104, "赵六", 8, 7777.77, Status.BUSY), - new Employee(104, "赵六", 8, 7777.77, Status.FREE), - new Employee(104, "赵六", 8, 7777.77, Status.FREE), - new Employee(105, "田七", 38, 5555.55, Status.BUSY) - ); - - /** - * 给定一个数字列表,如何返回一个由每个数的平方构成的列表呢? - * 给定【1,2,3,4,5】, 应该返回【1,4,9,16,25】。 - */ - @Test - public void test1() { - Stream.of(1, 2, 3, 4, 5).map(x -> x * x).forEach(System.out::println); - } - - /** - * 怎样用 map 和 reduce 方法数一数流中有多少个Employee呢? - */ - @Test - public void test2() { - Optional reduce = emps.stream().map(e -> 1).reduce(Integer::sum); - System.out.println(reduce.get()); - } - -} diff --git a/java-basic/jdk9/pom.xml b/java-basic/jdk9/pom.xml deleted file mode 100644 index 399a85ca..00000000 --- a/java-basic/jdk9/pom.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - java-basic - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - cn.lastwhisper - jdk9 - - - \ No newline at end of file diff --git a/java-basic/jvm/README.md b/java-basic/jvm/README.md new file mode 100644 index 00000000..8865e681 --- /dev/null +++ b/java-basic/jvm/README.md @@ -0,0 +1,4 @@ +src +1. classloader 类加载相关 +2. classloading 类加载时机 +3. ms 内存结构 diff --git a/java-basic/jvm/jdk7-setting/pom.xml b/java-basic/jvm/jdk7-setting/pom.xml new file mode 100644 index 00000000..d99a01df --- /dev/null +++ b/java-basic/jvm/jdk7-setting/pom.xml @@ -0,0 +1,21 @@ + + + + + + + + 4.0.0 + + jdk7-setting + cn.lastwhisper + 1.0-SNAPSHOT + + + 7 + 7 + + + \ No newline at end of file diff --git a/java-basic/jvm/jdk7-setting/src/main/java/cn/cunchang/methodarea/OOMTest.java b/java-basic/jvm/jdk7-setting/src/main/java/cn/cunchang/methodarea/OOMTest.java new file mode 100644 index 00000000..86db4845 --- /dev/null +++ b/java-basic/jvm/jdk7-setting/src/main/java/cn/cunchang/methodarea/OOMTest.java @@ -0,0 +1,56 @@ +package cn.cunchang.methodarea; + +import com.sun.xml.internal.ws.org.objectweb.asm.ClassWriter; +import com.sun.xml.internal.ws.org.objectweb.asm.Opcodes; + +/** + * jdk6/7中: + * -XX:PermSize=10m -XX:MaxPermSize=10m + * + * jdk8中: + * -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m + * + * @author shkstart shkstart@126.com + * @create 2020 22:24 + */ +public class OOMTest extends ClassLoader { + + /** + * jdk7 + * 9429 + * Exception in thread "main" java.lang.OutOfMemoryError: PermGen space + * at java.lang.ClassLoader.defineClass(ClassLoader.java:800) + * at java.lang.ClassLoader.defineClass(ClassLoader.java:643) + * at cn.cunchang.methodarea.OOMTest.main(OOMTest.java:45) + * + * + * jdk8 + * 3331 + * Exception in thread "main" java.lang.OutOfMemoryError: Compressed class space + * at java.lang.ClassLoader.defineClass1(Native Method) + * at java.lang.ClassLoader.defineClass(ClassLoader.java:756) + * at java.lang.ClassLoader.defineClass(ClassLoader.java:635) + * at cn.lastwhisper.jvm.tmp.methodarea.java.OOMTest.main(OOMTest.java:29) + * + * @param args + */ + public static void main(String[] args) { + int j = 0; + try { + OOMTest test = new OOMTest(); + for (int i = 0; i < 10000; i++) { + //创建ClassWriter对象,用于生成类的二进制字节码 + ClassWriter classWriter = new ClassWriter(0); + //指明版本号,修饰符,类名,包名,父类,接口 + classWriter.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, "Class" + i, null, "java/lang/Object", null); + //返回byte[] + byte[] code = classWriter.toByteArray(); + //类的加载 + test.defineClass("Class" + i, code, 0, code.length);//Class对象 + j++; + } + } finally { + System.out.println(j); + } + } +} diff --git a/java-basic/jvm/pom.xml b/java-basic/jvm/pom.xml index e3aaacf3..9a5f8bec 100644 --- a/java-basic/jvm/pom.xml +++ b/java-basic/jvm/pom.xml @@ -2,15 +2,16 @@ - - java-basic - cn.lastwhisper - 1.0-SNAPSHOT - + 4.0.0 cn.lastwhisper jvm + pom + 1.0-SNAPSHOT + + jdk7-setting + UTF-8 @@ -80,5 +81,12 @@ mysql-connector-java ${mysql.connector} + + + junit + junit + 4.12 + + \ No newline at end of file diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/ClassLifeCycle.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/ClassLifeCycle.java new file mode 100644 index 00000000..a2da6888 --- /dev/null +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/ClassLifeCycle.java @@ -0,0 +1,17 @@ +package cn.lastwhisper.jvm.classloader; + +/** + * 加载、解析、初始化 + * @author lastwhisper + */ +public class ClassLifeCycle { + public static void main(String[] args) throws ClassNotFoundException { + // 类.class会加载,不会执行“链接”、“初始化”的步骤,因为AppClassLoad.loadClass的resolve=false + // 验证:DemoObj的类构造器未执行 + // Class clazz1 = DemoObj.class; + + // 通过Class.forName会执行加载、链接、初始化 + // 验证:DemoObj的类构造器执行了 + Class clazz2 = Class.forName("cn.lastwhisper.classloader.DemoObj"); + } +} diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/ClassLoaderPrintTest.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/ClassLoaderPrintTest.java new file mode 100644 index 00000000..71e484ba --- /dev/null +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/ClassLoaderPrintTest.java @@ -0,0 +1,38 @@ +package cn.lastwhisper.jvm.classloader; + +import sun.misc.Launcher; + +import java.net.URL; + +public class ClassLoaderPrintTest { + + public static void main(String[] args) { + System.out.println(String.class.getClassLoader()); + System.out.println(com.sun.crypto.provider.DESKeyFactory.class.getClassLoader().getClass().getName()); + System.out.println(ClassLoaderPrintTest.class.getClassLoader().getClass().getName()); + + System.out.println(); + ClassLoader appClassLoader = ClassLoader.getSystemClassLoader(); + ClassLoader extClassloader = appClassLoader.getParent(); + ClassLoader bootstrapLoader = extClassloader.getParent(); + System.out.println("the bootstrapLoader : " + bootstrapLoader); + System.out.println("the extClassloader : " + extClassloader); + System.out.println("the appClassLoader : " + appClassLoader); + + System.out.println(); + System.out.println("bootstrapLoader加载以下文件:"); + URL[] urls = Launcher.getBootstrapClassPath().getURLs(); + for (int i = 0; i < urls.length; i++) { + System.out.println(urls[i]); + } + + System.out.println(); + System.out.println("extClassloader加载以下文件:"); + System.out.println(System.getProperty("java.ext.dirs")); + + System.out.println(); + System.out.println("appClassLoader加载以下文件:"); + System.out.println(System.getProperty("java.class.path")); + + } +} \ No newline at end of file diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/ClassLoaderUnique.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/ClassLoaderUnique.java new file mode 100644 index 00000000..34296998 --- /dev/null +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/ClassLoaderUnique.java @@ -0,0 +1,51 @@ +package cn.lastwhisper.jvm.classloader; + +import java.io.IOException; +import java.io.InputStream; + +/** + * 类加载器与instanceof关键字演示 + * + * @author lastwhisper + */ +public class ClassLoaderUnique { + + /** + * 对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立 + * 其在Java虚拟机中的唯一性,每一个类加载器,都有一个独立的名称空间。 + * 即,两个类来自同一个Class文件,被同一个虚拟机加载,只要类加载器不同,两个类就不相等。 + * 不相等包括:equals()、isAssignableFrom()、isInstance()、instanceof + * + * @author lastwhisper + */ + public static void main(String[] args) throws Exception { + // myClassLoader的父类加载是appclassload, + ClassLoader myClassLoader = new ClassLoader() { + @Override + public Class loadClass(String name) throws ClassNotFoundException { + try { + String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class"; + InputStream is = getClass().getResourceAsStream(fileName); + // 类文件如果在当前项目下,就由自己加载,否则由父类加载器加载 + // 比如DemoObj就在当前项目下,java.lang.Object就不在当前项目下 + if (is == null) { + return super.loadClass(name); + } + byte[] b = new byte[is.available()]; + int ignore = is.read(b); + return defineClass(name, b, 0, b.length); + } catch (IOException e) { + throw new ClassNotFoundException(name); + } + } + }; + Class clazz = myClassLoader.loadClass("cn.lastwhisper.classloader.DemoObj"); + + Object obj = clazz.newInstance(); + + // obj由自定义的类加载器加载、DemoObj由系统类加载器加载的。 + System.out.println(obj instanceof DemoObj); + + System.out.println(obj.getClass() == DemoObj.class); + } +} diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/DemoObj.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/DemoObj.java new file mode 100644 index 00000000..54546e0e --- /dev/null +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/DemoObj.java @@ -0,0 +1,14 @@ +package cn.lastwhisper.jvm.classloader; + +/** + * @author lastwhisper + */ +public class DemoObj { + static { + System.out.println("类构造器"); + } + + { + System.out.println("对象构造器"); + } +} diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/READMD.md b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/READMD.md new file mode 100644 index 00000000..dad5f98c --- /dev/null +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/READMD.md @@ -0,0 +1,7 @@ + +1. ClassLoaderPrintTest 打印类加载器,Bootstrap、ext、app +2. ClassLoaderUnique 同一个类在同一个类加载器唯一 +3. ClassLifeCycle 类加载生命周期 +4. MyClassLoaderTest 自定义类加载器,查看双亲委派机制和父子关系构建 + + diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/hotdeploy/ClassLoaderHotDeploy.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/hotdeploy/ClassLoaderHotDeploy.java new file mode 100644 index 00000000..26d1e4cd --- /dev/null +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/hotdeploy/ClassLoaderHotDeploy.java @@ -0,0 +1,88 @@ +package cn.lastwhisper.jvm.classloader.hotdeploy; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.HashSet; +import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; + +/** + * 代码热部署 + * + * @author lastwhisper + */ +public class ClassLoaderHotDeploy { + + public static void main(String[] args) { + new Timer().schedule(new TimerTask() { + @Override + public void run() { + String path = ClassLoaderHotDeploy.class.getResource("").getPath(); + System.out.println(path); + // 这里一定要用全限定名,因为一个类唯一标志就是全限定名 + String className = "cn.lastwhisper.classloader.hotdeploy.HotCodeTest"; + + Set set = new HashSet(); + set.add(className); + + MyClassLoader myClassLoader = new MyClassLoader(path, set); + + try { + Object object = myClassLoader.loadClass(className).newInstance(); + object.getClass().getMethod("printVersion").invoke(object); + } catch (Exception e) { + e.printStackTrace(); + } + + + } + }, 0, 2000); + } + +} + +class MyClassLoader extends ClassLoader { + // 用于读取.class文件的路径 + private String classPath; + // 用于标记这些name的类是先由自身加载的 + private Set useMyClassLoader; + + public MyClassLoader(String classPath, Set useMyClassLoader) { + this.classPath = classPath; + this.useMyClassLoader = useMyClassLoader; + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + Class c = findLoadedClass(name); + if (c == null && useMyClassLoader.contains(name)) { + c = findClass(name); + if (c != null) { + return c; + } + } + return super.loadClass(name); + } + + @Override + protected Class findClass(String name) { + //根据文件系统路径加载class文件,并返回byte数组 + byte[] classBytes = getClassByte(name); + //调用ClassLoader提供的方法,将二进制数组转换成Class类的实例 + return defineClass(name, classBytes, 0, classBytes.length); + } + + private byte[] getClassByte(String className) { + String filePath = classPath + className.substring(className.lastIndexOf('.') + 1, className.length()) + ".class"; + try (InputStream is = Files.newInputStream(new File(filePath).toPath())) { + byte[] data = new byte[is.available()]; + is.read(data); + return data; + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/hotdeploy/HotCodeTest.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/hotdeploy/HotCodeTest.java new file mode 100644 index 00000000..9b26f5d1 --- /dev/null +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/hotdeploy/HotCodeTest.java @@ -0,0 +1,7 @@ +package cn.lastwhisper.jvm.classloader.hotdeploy; + +public class HotCodeTest { + public void printVersion(){ + System.out.println("当前版本是2哦"); + } +} \ No newline at end of file diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/loadorder/LoadOrderTest.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/loadorder/LoadOrderTest.java new file mode 100644 index 00000000..d9bf10b6 --- /dev/null +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/loadorder/LoadOrderTest.java @@ -0,0 +1,14 @@ +package cn.lastwhisper.jvm.classloader.loadorder; + +/** + * @author kaisui + * @description + * @date 2022/12/4 + */ +public class LoadOrderTest { + + public static void main(String[] args) { + System.out.println("load end"); + } + +} diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/loadorder/MyClassLoaderTest.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/loadorder/MyClassLoaderTest.java new file mode 100644 index 00000000..fddcbc02 --- /dev/null +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/classloader/loadorder/MyClassLoaderTest.java @@ -0,0 +1,53 @@ +package cn.lastwhisper.jvm.classloader.loadorder; + + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; + +/** + * + * @author lastwhisper + */ +public class MyClassLoaderTest { + static class MyClassLoader extends ClassLoader { + private final String classPath; + + public MyClassLoader(String classPath) { + this.classPath = classPath; + } + + /** + * 类加载实际执行的方法 + */ + @Override + public Class findClass(String className) { + byte[] bytes = loadByte(className); + return defineClass(className, bytes, 0, bytes.length); + } + + private byte[] loadByte(String className) { + String filePath = classPath + File.separatorChar + className.replace('.', File.separatorChar) + ".class"; + try (InputStream is = Files.newInputStream(new File(filePath).toPath())) { + byte[] data = new byte[is.available()]; + is.read(data); + return data; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + public static void main(String[] args) throws Exception { + MyClassLoader myClassLoaderTest = new MyClassLoader("/Users/kaisui/workspace/my/code/java-basic/feature-jdk5/target/classes/"); + // 注意先使用loadClass,该类会被appCL加载,后使用findClass会被MyCL加载。 + // 注意先使用findClass,该类会被MyCL加载,再使用loadClass会发现该类已经被MyCL加载了,就不向上委派了。 + Class clazz1 = myClassLoaderTest.loadClass("cn.lastwhisper.classloader.DemoObj");// 走appCL + Class clazz2 = myClassLoaderTest.findClass("cn.lastwhisper.classloader.DemoObj");// 走MyCL + System.out.println(clazz1 == clazz2); + System.out.println(clazz1.getClassLoader()); + System.out.println(clazz2.getClassLoader()); + } + +} diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/InitiativeGC.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/InitiativeGC.java new file mode 100644 index 00000000..2d98db74 --- /dev/null +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/InitiativeGC.java @@ -0,0 +1,29 @@ +package cn.lastwhisper.jvm.gc; + +import java.lang.ref.WeakReference; + +/** + * 主动触发GC + * @author lastwhisper + * @date 2020/5/14 + */ +public class InitiativeGC { + /** + * @see cn.lastwhisper.jvm.gc.reference.WeakReferenceDemo + */ + public static void main(String[] args) { + Object obj = new Object(); + WeakReference weakReference = new WeakReference<>(obj); + + System.out.println(weakReference.get()); + System.out.println("GC before,java heap " + (weakReference.get() == null ? "not exist bytes" : "exist bytes")); + + obj = null; + System.gc(); + + System.out.println(weakReference.get()); + System.out.println("GC before,java heap " + (weakReference.get() == null ? "not exist bytes" : "exist bytes")); + + } + +} diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/ReferenceCountingGC.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/ReferenceCountingGC.java deleted file mode 100644 index 872b686d..00000000 --- a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/ReferenceCountingGC.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.lastwhisper.jvm.gc; - -/** - * 引用计数法的缺陷 - * @author lastwhisper - */ -public class ReferenceCountingGC { - - public Object install = null; - - private static final int _1MB = 1024 * 1024; - private byte[] bigSize = new byte[2*_1MB]; - - public static void main(String[] args){ - ReferenceCountingGC objA = new ReferenceCountingGC(); - ReferenceCountingGC objB = new ReferenceCountingGC(); - objA.install=objB; - objB.install=objA; - - objA=null; - objB=null; - - System.gc(); - } -} diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/finalize/Finalization.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/finalize/Finalization.java index 4fad225d..270c0665 100644 --- a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/finalize/Finalization.java +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/finalize/Finalization.java @@ -6,36 +6,36 @@ * @author lastwhisper */ public class Finalization { - public static Finalization SAVE_HOOK=null; + public static Finalization SAVE_HOOK = null; @Override protected void finalize() throws Throwable { super.finalize(); - Finalization.SAVE_HOOK=this; + Finalization.SAVE_HOOK = this; System.out.println("处理系统资源、执行其他清理或者对象自救"); } - - public static void main(String[] args) throws Exception{ + + public static void main(String[] args) throws Exception { SAVE_HOOK = new Finalization(); // 在堆中无GC Roots,会被GC,但是SAVE_HOOK实现了finalize有一次自救的机会 - SAVE_HOOK=null; + SAVE_HOOK = null; //显示调用垃圾回收 System.gc(); // finalize方法优先级很低,暂停0.5s等待它 Thread.sleep(500); - if(SAVE_HOOK!=null){ + if (SAVE_HOOK != null) { System.out.println("SAVE_HOOK对象还活着"); - }else { + } else { System.out.println("SAVE_HOOK对象已经被回收"); } // finalize方法只会调用一次,第二次自救失败 - SAVE_HOOK=null; + SAVE_HOOK = null; System.gc(); // finalize方法优先级很低,暂停0.5s等待它 Thread.sleep(500); - if(SAVE_HOOK!=null){ + if (SAVE_HOOK != null) { System.out.println("SAVE_HOOK对象还活着"); - }else { + } else { System.out.println("SAVE_HOOK对象已经被回收"); } } diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/gcroots/ReferenceCountingGC.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/gcroots/ReferenceCountingGC.java new file mode 100644 index 00000000..0b264ca3 --- /dev/null +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/gcroots/ReferenceCountingGC.java @@ -0,0 +1,39 @@ +package cn.lastwhisper.jvm.gc.gcroots; + +/** + * 引用计数法的缺陷 + * @author lastwhisper + */ +public class ReferenceCountingGC { + + public Object install = null; + + private static final int _1MB = 1024 * 1024; + + /** + * 这个成员属性的唯一意义就是占点内存, 以便能在GC日志中看清楚是否有回收过 + */ + private byte[] bigSize = new byte[2*_1MB]; + + /** + * -XX:+PrintGC //等价 -verbose:gc + * -XX:+PrintGCDetails + * -XX:+PrintGCDateStamps + * -Xloggc:C:\Users\ligj\Downloads\gc.log + * + * 这里使用 -XX:+PrintGCDetails + */ + public static void main(String[] args){ + ReferenceCountingGC objA = new ReferenceCountingGC(); + ReferenceCountingGC objB = new ReferenceCountingGC(); + objA.install=objB; + objB.install=objA; + + objA=null; + objB=null; + + // 假设在这行发生GC, objA和objB是否能被回收? + // 可以被回收 + System.gc(); + } +} diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/reference/ReferenceQueueTest.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/reference/ReferenceQueueTest.java index 71f7a1aa..924dbafe 100644 --- a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/reference/ReferenceQueueTest.java +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/reference/ReferenceQueueTest.java @@ -3,7 +3,10 @@ import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; + /** * 监控对象是否被收回 */ @@ -12,18 +15,20 @@ public class ReferenceQueueTest { private static ReferenceQueue rq = new ReferenceQueue(); private static int _1M = 1024*1024; /** + * * 因为map的key是WeakReference,所以在内存不足的时候,weakReference所指向的对象就会被GC, - * 在对象被GC的同时,会把该对象的包装类即weakReference放入到ReferenceQueue里面。但是这个map的大小是10000. + * 在对象被GC的同时,会把该对象的包装类即weakReference放入到ReferenceQueue里面。 + * + * 但是这个map的大小是100. + * */ public static void main(String[] args) { - Object value = new Object(); - Map map = new HashMap<>(); Thread thread = new Thread(() -> { try { int cnt = 0; WeakReference k; while((k = (WeakReference) rq.remove()) != null) { - System.out.println((cnt++) + "回收了:" + k); + System.out.println((cnt++) + " 回收了:" + k.get()); } } catch(InterruptedException e) { //结束循环 @@ -32,11 +37,12 @@ public static void main(String[] args) { thread.setDaemon(true); thread.start(); - for(int i = 0;i < 10000;i++) { + Set handlerSet = new HashSet<>(); + for(int i = 0;i < 100;i++) { byte[] bytes = new byte[_1M]; WeakReference weakReference = new WeakReference<>(bytes, rq); - map.put(weakReference, value); + handlerSet.add(weakReference); } - System.out.println("map.size->" + map.size()); + System.out.println("size->" + handlerSet.size()); } } \ No newline at end of file diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/reference/SoftReferenceDemo.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/reference/SoftReferenceDemo.java index d6d8f3e8..746f73cd 100644 --- a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/reference/SoftReferenceDemo.java +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/gc/reference/SoftReferenceDemo.java @@ -45,11 +45,17 @@ public static void softRef_Memory_NotEnough() { //byte[] bytes = new byte[6*1024*1024];//6MB 内存足够,不会回收软引用 byte[] bytes = new byte[7 * 1024 * 1024];//7MB OOM触发GC,回收软引用 } catch (Throwable e) { + System.out.println("---原引用置为null, OOM触发GC---"); e.printStackTrace(); + // java.lang.OutOfMemoryError: Java heap space + // at cn.lastwhisper.jvm.gc.reference.SoftReferenceDemo.softRef_Memory_NotEnough(SoftReferenceDemo.java:46) + // at cn.lastwhisper.jvm.gc.reference.SoftReferenceDemo.main(SoftReferenceDemo.java:15) } finally { - System.out.println("---原引用置为null, OOM触发GC---"); + System.out.println("原引用:"+o);//null System.out.println("软引用:"+softReference.get());// null 内存不足被回收 + // 是否会被 GC ?不会因为 softReference GCRoots 可到达 + System.out.println("softReference:"+softReference); } } diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/memorystruct/Intern.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/memorystruct/Intern.java new file mode 100644 index 00000000..0948e54a --- /dev/null +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/memorystruct/Intern.java @@ -0,0 +1,25 @@ +package cn.lastwhisper.jvm.memorystruct; + +public class Intern { + + //public static void main(String[] args) { + // String str1 = new StringBuilder("计算机").append("软件").toString(); + // System.out.println(str1.intern() == str1);//true + // + // //https://segmentfault.com/a/1190000011543995 + // //sun.misc.Version.init();方法中已经存在"java"常量 + // // 修改为new StringBuilder("ja").append("ava").toString(); true + // String str2 = new StringBuilder("ja").append("va").toString(); + // // str2.intern()字符串常量池、str2堆中 + // System.out.println(str2.intern() == str2);//false + //} + + public static void main(String[] args){ + String x1 = new StringBuilder("XXX").toString(); + String x2 = new StringBuilder("XXX").toString(); + System.out.println(x1.intern() == x1.intern()); + System.out.println(x1.intern() == x2.intern()); + System.out.println(new StringBuilder("XXX").toString().intern() == x1.intern()); + System.out.println("XXXX" == new StringBuilder("XXXX").toString().intern()); + } +} diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/memorystruct/Intern2.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/memorystruct/Intern2.java new file mode 100644 index 00000000..edae5e78 --- /dev/null +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/memorystruct/Intern2.java @@ -0,0 +1,21 @@ +package cn.lastwhisper.jvm.memorystruct; + +public class Intern2 { + + + public static void main(String[] args) { + String a1 = "XXX"; + String a2 = "XXX"; + System.out.println("编译器可以确定,只创建一个String的对象,a1 == a2:" + (a1 == a2)); + + String x1 = new String("XXX"); + String x2 = new String("XXX"); + System.out.println("编译器无法确定,创建两个String的对象,x1 == x2:" + (x1 == x2)); + x1 = x1.intern(); + x2 = x2.intern(); + System.out.println("intern之后,进入常量池,指向同一个位置" +(x1 == x1)); + System.out.println("intern之后,进入常量池,指向同一个位置" +(x2 == x2)); + System.out.println("intern之后,进入常量池,指向同一个位置" +(x1 == x2)); + + } +} diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/memorystruct/InternDifference.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/memorystruct/InternDifference.java index 3a7affb4..745ca766 100644 --- a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/memorystruct/InternDifference.java +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/memorystruct/InternDifference.java @@ -11,52 +11,54 @@ * 否则,如果该String对象已经存在于堆中,则将堆中对此对象的引用添加到字符串常量池中,并返回该引用; * 如果堆中不存在,则在池中创建该字符串,并返回其引用。 * false true - * + * * @author lastwhisper */ public class InternDifference { + /** + * + * 1.jdk6 + * String s1 = new String("a");//一个语句执行两个操作句话,"a"会在字符串常量池中创建;new String("a")会在堆里面创建 + * s1.intern();// 把首次遇到的字符串复制到永久代(字符串常量池) + * String s2 = "a";//直接使用字符串常量池"a" + * System.out.println(s1 == s2);//s1指向堆"a",s2指向常量池"a" false + * + * 优化为:String s3 = (new StringBuilder()).append(new String("a")).append(new String("a")).toString(); + * String s3 = new String("a") + new String("a");//只在堆中创建"aa",s3指向堆中"aa" + * s3.intern();//发现"aa"在字符串常量池中不已经存在,在常字符串量池中创建"aa"(把首次遇到的字符串复制到永久代(字符串常量池)) + * String s4 = "aa";//s4直接使用字符串常量池"aa" + * System.out.println(s3 == s4);//s3指向堆"aa",s4指向常量池"aa" false + * + * 1.jdk7 + * String s1 = new String("a");//"a"会在字符串常量池中创建、new String("a")会在堆里面创建 + * s1.intern();//把首次遇到的字符串的引用复制到永久代(字符串常量池) + * //发现"a"在字符串常量池中已经存在,就不能在让常字符串量池中创建"a"引用指向堆中的"a" + * String s2 = "a";//直接使用字符串常量池"a" + * System.out.println(s1 == s2);//s1指向堆"a",s2指向常量池"a" false + * + * 优化为:String s = (new StringBuilder()).append(new String("a")).append(new String("a")).toString(); + * String s3 = new String("a") + new String("a");//只在堆中创建"aa",s3指向堆中"aa" + * s3.intern();//把首次遇到的字符串的引用复制到永久代(字符串常量池) + * //发现"aa"在字符串常量池中不存在,让字符串常量池中引用堆中的"aa" + * String s4 = "aa";// 直接使用字符串常量池"aa"(这个"aa"是从堆中的引用) + * System.out.println(s3 == s4);//s3指向堆中"aa",s4指向字符串常量池"aa",而常量池"aa"是堆中"aa"的引用,所以s3==s4 true + * + * + */ public static void main(String[] args) { - /** - * - * 1.jdk6 - * String s1 = new String("a");//一个语句执行两个操作句话,"a"会在字符串常量池中创建;new String("a")会在堆里面创建 - * s1.intern();// 把首次遇到的字符串复制到永久代(字符串常量池) - * String s2 = "a";//直接使用字符串常量池"a" - * System.out.println(s1 == s2);//s1指向堆"a",s2指向常量池"a" false - * - * 优化为:String s3 = (new StringBuilder()).append(new String("a")).append(new String("a")).toString(); - * String s3 = new String("a") + new String("a");//只在堆中创建"aa",s3指向堆中"aa" - * s3.intern();//发现"aa"在字符串常量池中不已经存在,在常字符串量池中创建"aa"(把首次遇到的字符串复制到永久代(字符串常量池)) - * String s4 = "aa";//s4直接使用字符串常量池"aa" - * System.out.println(s3 == s4);//s3指向堆"aa",s4指向常量池"aa" false - * - * 1.jdk7 - * String s1 = new String("a");//"a"会在字符串常量池中创建、new String("a")会在堆里面创建 - * s1.intern();//把首次遇到的字符串的引用复制到永久代(字符串常量池) - * //发现"a"在字符串常量池中已经存在,就不能在让常字符串量池中创建"a"引用指向堆中的"a" - * String s2 = "a";//直接使用字符串常量池"a" - * System.out.println(s1 == s2);//s1指向堆"a",s2指向常量池"a" false - * - * 优化为:String s = (new StringBuilder()).append(new String("a")).append(new String("a")).toString(); - * String s3 = new String("a") + new String("a");//只在堆中创建"aa",s3指向堆中"aa" - * s3.intern();//把首次遇到的字符串的引用复制到永久代(字符串常量池) - * //发现"aa"在字符串常量池中不存在,让字符串常量池中引用堆中的"aa" - * String s4 = "aa";// 直接使用字符串常量池"aa"(这个"aa"是从堆中的引用) - * System.out.println(s3 == s4);//s3指向堆中"aa",s4指向字符串常量池"aa",而常量池"aa"是堆中"aa"的引用,所以s3==s4 true - */ String s1 = new String("a"); s1.intern(); String s2 = "a"; - System.out.println(s1 == s2); - + System.out.println("str1==str2:" + (s1 == s2)); + String s3 = new String("a") + new String("a"); s3.intern(); String s4 = "aa"; - System.out.println(s3 == s4); + System.out.println("str1==str2:" + (s3 == s4)); String str1 = "abcd"; String str2 = new String("abcd"); - System.out.println(str1==str2);//false + System.out.println("str1==str2:" + (str1 == str2)); } } diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/memorystruct/InternDifference1.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/memorystruct/InternDifference1.java deleted file mode 100644 index 43b199b2..00000000 --- a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/memorystruct/InternDifference1.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.jvm.memorystruct; - -public class InternDifference1 { - public static void main(String[] args) { - String str1 = new StringBuilder("计算机").append("软件").toString(); - System.out.println(str1.intern() == str1); - //https://segmentfault.com/a/1190000011543995 - //sun.misc.Version.init();方法中已经存在"java" - // 修改为new StringBuilder("ja").append("ava").toString(); true - String str2 = new StringBuilder("ja").append("va").toString(); - System.out.println(str2.intern() == str2);//str2.intern()字符串常量池、str2堆中 - } -} diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/ms/Math.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/ms/Math.java new file mode 100644 index 00000000..d4a51a36 --- /dev/null +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/ms/Math.java @@ -0,0 +1,19 @@ +package cn.lastwhisper.jvm.ms; + +public class Math { + public static final int initDa3ta = 666; + public static User user = new User(); + + public int compute() { //一个方法对应一块栈帧内存区域 + int a = 1; + int b = 2; + int c = (a + b) * 10; + return c; + } + + public static void main(String[] args) { + Math math = new Math(); + math.compute(); + } + +} \ No newline at end of file diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/ms/User.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/ms/User.java new file mode 100644 index 00000000..4f9b8786 --- /dev/null +++ b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/ms/User.java @@ -0,0 +1,9 @@ +package cn.lastwhisper.jvm.ms; + +/** + * @author kaisui + * @description + * @date 2023/2/22 + */ +public class User { +} diff --git a/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/tmp2/command/jstack/AllStackTrace.java b/java-basic/jvm/src/main/java/cn/lastwhisper/jvm/tmp2/command/jstack/AllStackTrace.java new file mode 100644 index 00000000..e69de29b diff --git a/java-basic/jvm/src/main/java/java/lang/String.java b/java-basic/jvm/src/main/java/java/lang/String.java new file mode 100644 index 00000000..745525d4 --- /dev/null +++ b/java-basic/jvm/src/main/java/java/lang/String.java @@ -0,0 +1,17 @@ +package java.lang; + +/** + * @author cunchang + * @date 2021/9/2 12:21 上午 + */ +//public class String { +// // +// static { +// System.out.println("我是自定义的String类的静态代码块"); +// } +// +// //错误: 在类 java.lang.String 中找不到 main 方法 +// public static void main(String[] args) { +// System.out.println("hello,String"); +// } +//} diff --git a/java-basic/jvm/words.txt b/java-basic/jvm/words.txt new file mode 100644 index 00000000..7f20a9b3 --- /dev/null +++ b/java-basic/jvm/words.txt @@ -0,0 +1,100000 @@ +Rhy +efN +UayWpqb +BqZQ +bIygB +LJN +ajQHJMb +YbrSTOvF +ZMHNXzlVa +ewx +YgpzfY +fDqdYct +R +yY +clhohC +XmJbuSgcR +sAveQeOjNN +UMIVQVrbux +ycViCnY +btdwA +zCIaXvlndF +DmwWjFMLI +ow +hb +SUCCMITUhj +mRUiCR +JWsuWzOvIU +fMcGkByHa +VybXKd +RqW +qYk +RVFABgRZ +VnGFQjoq +oemOSGEd +vlAa +ANttmx +neRslgFFn +zzxIivg +jaoeLR +fX +Qu +rJhSBijL +CHD +pcFI +J +P +vkO +esM +IMSJzNDYK +NABWSnb +LX +Z +uVbSlTPgg +tzx +uHB +YgrMSrcF +QD +oC +lhGeo +uYBeC +DyKjcx +ECn +mgsROorS +pdA +djC +tIP +UNCveNdh +wgyZ +GxFuqA +fk +vwOH +ZMHhnWzmU +HQrbZhr +A +LblUcYUnN +b +kMaCQcNE +BGaHW +pyiGoijT +tMi +VOY +nJMViGi +kI +wwTgwIDdk +E +ajOwJlh +rEhAt +raWH +mnc +iqkHfQxA +wqyXPqgKL +zklJRQmb +DyLFgVMPyZ +MzfFTHpWqM +XBaO +cCZqdIxw +jpKE +QulzGtMLZ +HKvmyeTx +HPRe +WCquyCyjJ +SRbt +HPZG +umHuAzw +KCAzan +GoITkoqdVI +sm +PcwGpJorn +XFUB +NaSa +HG +UAEW +kSNVwK +gMhPPBC +P +QVDjemLt +nlAHyyO +OmtMp +UZH +Oji +MNXmlyqNdX +Zej +JwxBa +SngHvNIzBi +kvHEAs +qpCJ +UEoTpJoGH +cROiKX +gaPsbyXAY +LbFfTuXqv +Vih +qxtktIE +Tl +agn +XFs +lUBIOW +ZHuyN +jVAuzMhGwr +G +CgH +d +vBoroeFGyB +ppytWCmCC +w +GdIQexFm +jdtjaERC +nVFsV +hmHr +jKKUBBvti +coc +l +GnBZIkZLX +D +rn +TuCfAneczX +VXtyiOb +kx +DeRZF +pOdEZMK +kNHz +sgfhMah +oHR +X +IFjbBtzL +ywWzqCoJD +DBLfHz +q +ypHg +IupkkeQbl +eJFleyZ +w +aEV +UvgXHjGbDv +XpfFymVB +nfdPr +SePMC +Oq +LvyhzrqLg +wqikQ +NlNH +NaL +ZYWoGWHZuy +QgeqcwCzA +Lw +DgNioXG +DqQpVzvi +AaG +XbomxDTFn +OrUyqnYeUh +KLZrfWGi +sgsbBFqjZa +moUx +DfYdiR +gjvE +MgRY +JB +ETVM +Rx +AMTXZH +ddFjBCAaKh +mMilYmAwe +jGofUv +CwdLszXOPp +y +UGK +x +ETgx +vIMwW +KcCojX +DZwUpJHYt +KbYCve +xsdmmxYBCK +m +bAmLxPQf +BdDX +Hb +VirjqkAs +s +HYBrYrA +zTkv +IJtbgTBCWz +Q +DZ +y +K +KIqGfEx +gDobuVz +ummKeeQnJ +gJKX +o +FdYdc +rmJlhBb +iSS +REh +IIX +bqU +NfKiAnNBXz +ApXDiXf +QweGByUiB +OaLiw +PRVX +mka +YdjRfQzfz +NUGlPbEpp +WzoRosUzJt +Xqw +nMUtxIjvzH +hz +zWTWFSH +psy +FdrxFq +ssgrkb +dHhVikPOA +koj +JqOD +a +C +tGhrAoF +OIkWcD +MeHM +eoHXjQNIU +yeDWUXUID +rWlEEPf +oxsC +dtIMexV +tcPdw +FNSuD +Pv +jbtKAj +puwkk +euS +LNZZhELd +FSvvSF +BXpucLQGa +mKhNmDR +DdQs +aPEeR +PytQ +pPXax +ibLqwhy +N +Q +bWtmAe +Mfsmq +id +AqgJNkhU +hewtYhfBKv +bCQJK +gaVtGFmU +fMVV +IFxpI +FVeAAImCFZ +A +ycPoSJbZPr +DhOClPHxt +JcGDgnhfBB +HoEQ +gFHKIwORq +DRhv +Nr +cBRIJpeZ +mJTXYZzHn +kFi +pexflGpyy +Wx +WQr +VkFgiJyVg +LYlTgndjgx +T +xYwbjjQ +AXRe +TgUzxg +pFQtQc +UkFGTLEaIp +YDy +dgDmInvuNq +YEIoF +nyOXPcIoyv +MRe +RDarxvedOp +OaXODlp +uC +g +wDCmgHXzTz +fF +CSBcyKn +BGNbZlNn +oOnLIiwdui +bKiZsC +mb +MU +usGlXYih +xaKcp +d +APVYblXMVb +UsNonj +Jpq +SWVtXFZ +i +NtvFhmj +tAdLS +TtgdiDx +fqwWd +Fe +DRBHhNuwhF +L +pOXzCbdb +IjhgPQJ +Oq +hCT +uiIAFztI +nYl +grfSY +E +cBfQcT +yAzUd +axQG +grKA +rXuso +V +cGX +a +zs +b +g +NvknhE +qi +QbaQLUMjyE +gbiKzUGEmK +PleubxdCnF +mODuvTQ +yO +WSrEQrktD +Re +Lg +JAxcHTUA +bfeoJbXxD +VZX +yvikTfx +LMoQsx +lJToEoOZTY +Gi +dXBgnqCIsD +jyrADgMzIY +VBjCKy +CQEavvfE +im +Rq +kFk +hvL +PoQWC +ByoHloHff +A +ii +NUdBZajJ +UHCDI +vpn +c +bTuicBb +LuclHp +cDIUmKpbc +jwKBFw +mtDEEUP +CI +ymRJ +DxlD +NA +AoY +qv +Dw +biBdWw +DTAPBRt +EgXvXzDE +hfu +j +VtqkTD +kwOrxP +RFkPKvoag +Py +myVp +NZdH +WNCUHTLJ +AZONZtfOQl +kqPnC +pK +gqu +xwjyM +abO +xNqxeQcVo +CIjinzqA +Zh +rYFalNsW +mPULqOCBQm +jKoX +CCstu +bMgx +UScU +JWS +aWwRL +hhEVXcq +rqScsN +SYvQK +UJczI +IptCSGZ +Ldkjl +EfaIVP +LQxwloT +ohmxpiDV +fJQex +tdNSqwW +RP +apUpE +oIzqinj +rcvAC +ItzZiKEwTV +OKspzcB +IFtvdJS +mW +JPcimGOKRK +J +QLNUkfbZH +NXvWId +fzgxHLNBNJ +AcOkPT +l +VrFjof +jaFeCKBy +GoOGClBfrb +o +WLYGIeVZJ +GYu +G +deCYsEzkV +t +iMHvKy +PEk +H +FBrfxF +xvEmSv +PeNYu +aDzydtcKRk +sMaAV +cQVgYA +T +nImwVDgPH +MYQl +cv +qRsapVm +Ixez +FhAODc +jgqYV +ktxVjIaL +Z +zdbEo +AsupbnnTfo +air +YmjYtoMv +Ehz +ZyChiqQPVr +UjyNQee +Foc +B +b +x +pfs +tpCsdkOh +oSAIsz +EZQW +qmnR +ow +Jng +nzzNpXHbAo +jkxSI +uoGYwzC +y +SgpuwJxSNd +stV +CSnUA +FzeIuB +yRJe +JBAAnIYfj +tIUjB +plNkazz +J +y +BWvfurHrN +dEsF +w +sySDaIUEmb +HDDCbSIw +z +jOsVUV +ACDvz +JCUwJJiw +JpjyGM +AiDXmKgw +XzNrL +i +EjpKQGaUQ +WjqvtQNEe +zUwfVFB +zmX +vK +Af +MkfbB +PEpnzcWcd +S +mAKWkxMDE +mKU +Qb +WQFUyBopvn +jzYBpSMDZ +HyPorlIZbZ +DaT +RAStRTMdRP +xkQwRmFEMi +ugrYjL +VhGWPTO +C +tZpMJ +KZNXKhccYf +jOHLJdCj +cFCvTwu +rmCvf +UYHWSc +CqodGba +LVhnNA +QBsiizsBv +ZPfs +M +vI +mpxjxMI +n +wAKPUJgU +EV +ahUelo +BMulMKPyD +h +bfhsb +kASwBqhg +nOA +bZRsY +Y +OvjljEVYOI +HpRAZ +fSbEdp +SWCLzuIwG +LVEePzdd +UGqYswbf +sBbMdVekzG +kDvKLL +MQaZMVDrH +zpFsOmMta +MjZwZu +nXZQ +LkY +xYCYuzU +Tr +ZJBwKNqX +yIhZijCNvW +OVpfTuJz +i +amCHfQPLHv +c +PJDUbex +nAq +aExzar +N +Yq +or +BwLvuifSF +XO +XAGmzy +BpKlacD +A +LeR +PDmCejoYVI +PcjIHbddXw +YPfyYi +E +JqDDrla +zUnWJOJQ +GxIkXe +FOfUURU +KAkLgZZI +b +qtBO +TnnAscJZAX +sFip +weAMFB +F +Hmo +ryiZSj +cvwUj +qWeKzsqsU +J +hhiKq +S +SuMe +pb +pMPhUIsn +ZexedvEI +PtjyKzJmWw +GXsrRwofp +LO +ejt +ft +XKoelk +KMDYk +yfqMnjDV +sf +hFfbywV +OMDBQudFqC +fzVEH +lfaWOBTua +YPu +cmn +ZlgTvJIZlD +Rqu +zjXG +WLFH +uAku +GNOmBu +PF +NoTEeuO +wJaKKYjVL +hbBuJgz +WPAmaIRC +hJU +IyUitv +xLbob +mHjqVHXT +GuZZWfh +myOwOrsPSp +wKxCGEISeU +nAnxsOO +bqRVxLmAJi +DkIM +LSpNSeivD +lnrCni +qHdRAH +RCvMfjyYRM +yhoA +lqTYUZW +RGyfqnkL +ZTnoCHtW +LX +X +RDqbWKHE +UszpBkKNX +NWne +PqqpUMtRYi +reoZapvkc +lXtpiTLS +Nc +dbNVj +zhoxzgGom +bl +ezPTpz +oIhvTOswf +tTpJTLtzWD +HWbp +V +Cu +e +KlCCcysmyD +rnEd +mGfrcjE +BazKwoJt +llg +vKyyz +vIWAgYEuuf +ovowjms +KeS +yjIqVf +mYuG +M +fIJEf +DZQeYu +SmAUcGZRpU +x +FM +UJO +fG +fPAbayQyE +HUz +OXlNZjwJ +Sht +o +TKxOs +Vz +otJF +oZJqKDn +dgkOqIBeL +odCBvY +rzYoZ +iAOCjiaoCN +UBNeyPm +I +TrNB +FMCF +JCjXRADqZs +KSHazQhOe +PTtDbmZxJL +BwAuek +RcDoQLudD +LBCQmeWk +ED +hsNbvi +C +KmofjwF +d +nyWev +CWXOoUaCl +b +AENX +Ev +GVQQ +mjPyJUJVF +ADSREqCXom +aBsDLpCkC +w +dRbbCLgMql +bzsNXl +M +trbVZEoIB +LxuqOU +QnSWxwsw +cwPcp +PdJUs +BnrGiCJEUA +RrdyebbO +MgFy +Cj +Or +MnK +oHSl +hyJj +Pzgy +qnueWO +DGjAFWWNEl +qMvY +RQpa +Pm +rOqVL +qLICkSH +qApkAv +fCNo +OQjCZzQMCi +B +X +WSA +cVVpc +OJRzoph +ERK +k +HVFjzkyTy +IFdXO +Cv +nEl +AF +hNGArRVc +SME +jqndBN +Elg +hLRsf +WDLddpi +UjQBHlcy +b +rRdtkW +KpOHtYx +jMD +ruTqQ +JGtMqc +V +jDBs +VZnkbHgG +eIDJ +wQYCSvCH +quWuzcybxU +NO +MBcOSbg +G +LMVxSJejBS +asbYiTHX +KDFYM +YVVBnGeByn +f +LzMhy +WKe +FIjr +trukzOd +ntfLXZDKVo +KsSldMH +Pn +lAmmSzIjPq +dEn +IYDckRFD +F +ZBJlEwbH +pkf +fWutUJiMMZ +IeUmuHmX +HiFVfZF +ODe +GtefNO +XQrHGYoeh +RyRTXLxfBC +VyNA +DJAy +d +CfXgiM +CVRG +sO +OcZnVKyU +lfrmqYtt +tQHmHNYbZ +sNqKSCydih +PAl +I +zNoFyM +HVIlSeLs +yKpDCL +kU +Swkbnrxkm +CqztUNfL +zAk +AkWbbSl +HpTJBGBaV +PUaqnH +uFAKZsLmnl +GMBlu +sIAc +usETfFWc +HvUmn +qAgpnOpvWw +j +wQH +etNlV +oxhzcRXvfP +qiBwRK +Q +jgDWF +IYDIMKFKIn +ihd +ewB +gvwqlWKFKV +fCick +i +CxfhcY +xYVWS +BZbztMDo +XIJnyqa +DnKJkb +oBsdafAni +tbfj +PNEPDLLE +PGUuYVAMeh +evuFpo +NQylM +PTlxe +BwcgJ +gEJ +Ka +y +gvSB +SL +dMBZnBLAK +FrE +gJyFTPzt +UldW +YTWyIaGF +bqzOjLfLna +CYKT +C +HYiAv +KqGim +aH +WzXwJ +mpROJQkQC +yRSmGnBIpK +shhlWeuF +GnePxEIl +xWEHVkCHK +NeEUEgYG +tKBogJAxjx +fYzWl +ufXea +HcbXdVxb +THYOEzSa +evxZZljT +CUWUyCTLCI +SH +FMV +ZLy +KB +CpKXu +hmJeKf +abIJiTw +tmNS +rbRpmNTYX +ecWpFpXy +POFFyD +s +Sl +cNaYWtYXM +X +tIVlnVLUZ +IENjhu +hfygcMiUKe +oyNekynS +JJj +L +SYTbCvTWDK +lTuHM +nWya +FEF +AG +KKdQSzu +omyOMNy +jGYtaaz +AOddip +N +hiMCUxdU +NxT +YWYgmr +N +hoqfCEixo +cQmvgH +LglkUKDelk +RJDe +sg +YM +pqsQZuzR +DcJfMjNL +XlYTMPvqnp +QXFq +qDqBbm +Dl +Stfyr +RBKh +pkH +jtjcf +QiIMKFd +MWBKw +BOLT +JDzll +tD +BtVAlsatY +erUStEQh +YAdQMHY +DS +q +PNGzbYbPSP +fnV +fO +BGtmln +fTTqPZgQs +j +JPVgk +rcoWPTWX +YGAldS +YO +RuMhViOr +Lc +mLAAtjYpd +gEzYceRt +XATNVqFjUo +sYCcTMhE +wxY +sVFIjCD +FNYu +BJTrowN +LXcDKeWb +MqpGQrlXW +niETzSl +gJC +jasM +XCIiHpgdxN +ywAoKb +UQqr +oXJnwnv +ujRQd +tHpAItTFDI +Ig +qFGa +JaHcBWM +feD +yA +H +xZMUolVl +SelQ +EFlvWQ +AOJTstf +yiHAIZpnbY +jl +BRxpyN +xTKFseXQvp +oRbWy +MjFJZh +xqOMEN +HLzRqOxBB +ak +ZIcpajozTZ +jXZ +UFBaNjhvs +j +iujOjCtBI +VGPGG +aIzXiz +vbkfD +kfpiETd +iEBiLzmAKP +qj +RtxLtfbaC +JaiI +QzmWt +GXEbGU +EXyj +uXYjW +pR +KTtR +mGJrVgZ +PvNjgJj +pRd +bQErO +llEnkU +dYYNj +suxZabu +QEJU +Typ +jvxXl +ZDcDn +GinFLyygyt +ERVxJ +qpjfzD +rhmZ +UOxxXjVSa +FUStVJIUkU +huZzVu +Ea +fflt +CMRtC +vAgW +BoGbt +wPsmSNUzBM +AF +RtO +ehJLwNws +WeYQtyc +Tm +nllX +DDxRFTXBCK +IgtSiQz +PExurBFdF +UlrTlQOL +ldVgQ +goCWNlV +tJU +gPU +goMheFRGNz +Zhpgjj +CinXjVV +gIJE +ep +ay +AhEyrPuuQ +yKOglGEQgA +HurMzdNyDX +k +ZjHlN +XTWgyvQMfJ +JB +nWOEfwlFM +YOv +xpuTHycrWS +tdWXP +frv +giBIt +c +ZBt +t +GIeJVFacL +VCejq +xwy +IZu +BVuv +svyEQYcIoC +ZBgZI +DqvTrmFPDO +eAJ +M +JMSagqN +dOqZEiikM +SnwX +Ntmaup +CZBz +eqjWlT +KVsUgbAQ +kFJzm +fF +oWq +bztjx +B +TIFkw +HaBTTueur +GjZnGNgCZE +DMduJbVs +rZRyhFGB +dQPrl +FG +W +wXTdxoZDQb +pMzvWKoBd +uXKJXBFhZy +plaFHUV +fs +pgX +JVPDdrwC +yiipKxsVhW +Yykv +W +pBUEPDpLb +RNX +BsL +qQohPaP +foiTUKM +ztISCjgg +nKMXKCe +xoFRkAGzv +MUDQGeTn +o +D +n +tVt +WruzhBMa +lCR +EXiGQOlOLo +slMzLpT +eqQ +l +WPNFTyb +MzlROQo +Wvelup +igVsfEYWU +aeKlhi +dUFAZWuBaq +EKGlVKrGzB +TEMqmHSEIX +zRFM +IBNTKyc +LrlZ +YyHeCIlkuW +Al +aMCkEV +l +f +GMElYNc +Xp +GCPuwDpM +zXkVfrj +AsKJqx +QYne +fMdgEJtgkt +payUHoW +IkDAD +sI +o +CivaOiG +JuP +svebHuuiN +BOOn +RcQIzIzZ +Zyabt +NQCY +dGJYGU +aza +YxWon +i +uu +ZCkkJ +fgvdQl +Z +QioyPXoKra +NJEuEa +TnOT +Wo +bda +qhISDYR +TRXBN +nsfZV +cVNvRac +OuCVitDzJD +heYOeryDhT +MJqGgQ +YzMXaMtr +ioB +IDoHrQv +LUgjy +Fz +fL +osrxGfta +lvWD +Inl +xrrrufgpw +PSahlCBUJw +Dp +WyS +kHXQ +Vn +LEtbA +LSChKWsem +vkboEImZLP +wrybUPj +zAfsJBLhMJ +SRfz +KwnOpakff +ZPJrfIvTs +CyHSWaKTM +YOmI +iN +aVhc +Klqpy +cIpsZzmqW +XEg +BspnzjOys +CQtwcvcgIu +QiBV +QtxVL +ikib +DRnICfkM +XjwkPjdg +uVOCscNcdk +vAwqDiK +BaDdI +U +tA +nBEIp +OxfPKTF +LevwSqCTT +DNcB +qpJlIdu +TMuM +nj +GRzBespIs +Rcx +SkEibs +YOvQGVRDu +LkiCzKW +ZMgI +vJ +WtVJu +DGGxiPPS +pZORz +ZniEhkAVO +CITfjkqQzr +vyESgOeI +BStYDV +r +ZvoQpjAzAE +dbgvNGWP +OjyNlzReB +ocn +VIkutItgD +rJottnDkS +aqY +atzZZwHi +LCPhULpG +Hto +w +VRBNWoqmd +ebj +yHfl +SDgdmTzqg +fOTiNNwiXL +PrcEVUPwS +LHjjAp +bfJcGvI +QVAdqQYnu +Zewbo +fHVuVplULk +WDLTN +iZn +Ef +ScXXsaZyng +lcZTar +ltNRfo +dH +r +JmJagyC +QJ +oqXoyk +Ar +hBdNyocL +rfwS +VAq +XVhZId +s +wWed +lh +Sy +xlWCDo +EdAGdUJux +JReGoHWxVL +sip +OPqXXrlhEO +WYeViA +F +bDPaIawTG +rZnjKZv +I +IBwBpYRPJA +Ff +MPu +uiOc +ALRZWBncP +bGFZXupwj +PWgkwb +fhjnLICoZv +hsOlyLS +ZMHzZ +aczRFtif +QujT +iwWWzIGtMX +obrn +rDxIrue +eeP +SZDA +UlK +IFqUt +PwTmXOLTRg +CuJGPoV +UEsa +BkV +ZOnXbWhvSo +MsGiBYRjU +oMnirLVqn +LpMPlXE +YDwMrzn +xSuWhK +hLOJGSHaSn +MHnIzvA +cL +OaNlIbY +ArBzIQ +azdFd +URbuAyJ +GSKWogTb +Eopluln +cFHIxchc +RTbU +olYG +cVJy +d +hOQ +gM +wQeJOkrM +jdJ +yeLalppHbN +i +GdSU +OwhYowcEew +FUKG +MI +WYLqSc +c +swAJr +wLffT +kkqTWPIuw +xrs +nMxrA +QKg +AXpOALBLxG +rtILRZeJS +Cu +LDXCdkmutB +W +lGRvv +q +NU +mNr +vSWP +HnF +nOKjzMeLC +KdCvHe +KDDHWfto +KHe +rwi +cGQASaptrd +vVOsccsdbO +IF +LTVwPpoR +FSSwfCiKDk +H +vO +M +ddaZuicF +HssZoBFaLJ +yL +AOQPdCCsID +WE +wzILk +QoStlS +vCUkYX +QPVArThu +qAAJgkdCk +NJysqEWyww +sROqggKvt +neX +ZKeZ +KkhSIHh +JxdRyHrT +NLumyuNj +nbLGTK +Cl +qUaHsQ +GlwwXC +grEL +LApKs +HOkxAMvJwp +ZYXw +WJafGOYDWI +X +HXGjQAW +ZhDGjTL +btRRLLzLpB +hsxidaGYOT +BIei +NPAC +TtRNuMP +Cx +vkgld +w +vnsfCgwmyL +sZjKQ +XsTuRV +nLt +TrGrD +hIdeia +emmTwGx +eG +Aa +ujI +BtbLLAI +niyP +qqTfU +PFlrrOWFeS +prd +LdPzLmL +uGWHkLgtFV +RjZf +xslj +LpQhyYQQ +ryxKbzmjY +f +IRFW +cTx +oDsK +Ua +ejAJjRv +BQuXXHZfuh +ccn +EsBjmhGDww +Ulbufza +YbcjrJXon +iBPGWTjK +pERS +oVtmg +yeLx +DNIgMfq +EfuZcVEe +aQQ +Vh +wnfLcJB +hwf +kZyOsPjVzs +x +KPY +SxuQJXDszj +p +xMHKhZxtg +acBIHfSAEe +cblZtQfsCk +GI +cYdF +HLXMKf +GK +j +lcH +NXASgUl +l +iTcvyFT +HCyzjQe +vcrUbkA +CDIVZbxKj +sVirUlyVW +ohJ +tllasUqkMU +uVfzufONwu +UgCMviqDNK +Dup +EMIPIKRiGt +taFGeym +VAMal +ieBtU +oy +jgVwO +oYpEO +LkbVQzeFt +qNNHfW +KwO +DOvXqc +fndLAI +iWrmcDDJm +AGIxRKnO +peCbtuNXn +ifOp +gy +KasKiudHj +RkDWcpLZ +XeNHLMxX +UebGVcfM +rjtXD +IVtcK +gpKpeCFwAW +gQ +abr +hsp +ZXtDMEhL +MgcGm +aWhOoGMGsj +yxNblSZgA +OQKYO +uYv +IyZbi +j +ddUdEopNKn +oUojI +bDLJJYkxkR +kwBKbg +TvltIXh +mTMI +LixZmW +XaFKnNMq +w +ePyodD +HlzaJp +DOs +YfVItO +tMTXFZ +rxmpwN +o +XUqP +IfjC +sLYp +d +HA +Zmqf +Oufjvv +ID +BAnIqIPxJl +o +TUQ +iSWOagT +cBCGgheEDB +UV +gqNMbs +J +ohw +sSWU +bah +UNKv +DUXJcb +xZC +nqg +XNEYPOTglB +EWfFkCHFB +JSQh +cOUijGSbh +Y +hWCRsB +tW +dXKp +IPtqBG +tHrAWRcY +jTmReHQFr +DYCHvLrw +TXHnejU +M +gMEMaROQR +CcGi +yfGEC +KtgPpUnc +jrf +EE +eVc +FEj +nHoMkzA +Tsl +GxuoiSiQTH +MRQUAYIjA +yOVylR +DOiyS +vekWprLEVg +JljrOMy +aHYbKYsXg +ohVYTrdHPO +dBtYpU +gcsrDRxZSj +D +RZsrIVaH +t +ieEkHwq +Aqd +xdYdjUpaX +xoswu +jdROLg +WN +dVdfEn +SpjKm +s +xI +cCrCHyCo +OblRsJbBM +VOjaQgc +UzXHPbx +MqfZ +vzBMUMs +rfowq +z +ZV +DXCrzQZrPy +n +wZUfceh +tPECCczXR +uc +yDfeL +YrXPL +KY +vcl +kHcufmFvXU +BTIyVIKm +fkpCPnwj +ax +zIEJgJ +uZfOiKVw +pxHgBggKop +YOWqaSE +MizpJUja +x +EkAQzUwbP +ZUtWasoCoq +ec +dDlrfU +CnDf +hhaJWBZGd +uBydidGC +bIScbqA +cM +Jtn +MlNSjopz +yvcQM +aKgtzQjAP +dgOXC +PpiZITEf +NW +gjExqW +qaorxsC +WJ +oe +M +Jcb +IOXi +nITVk +fqWquWJQgN +GeiwigWDu +BppJJ +z +eomWP +wUDNSj +qsQlRjWLK +bVCtOzV +MTFKpvGc +bOgT +DzdvbaW +unGvJC +ivgtYZiSB +XSCGbJG +evlrvvbrt +TUQsLBQ +QMhwsbQ +ZtfG +fbftoa +Cofk +Jbp +mADqyCleB +QC +WleXOpPKa +bb +qtspocnd +Usrvei +fYoK +eY +fTMcTEOJN +qPppT +G +vuFBcCdzd +ajSscAF +LdhCdZFV +wJJnFZJGq +qnP +VrmMOrQsD +RnX +hyzCbtmkso +oonXaNrRah +TkNcrLpN +GjLs +vPVklJtNh +OToQ +PGjQZDmi +ucWPcL +uQGF +m +jpDqBOUgBz +O +SnRvn +WauZ +gOETWtV +HRQVms +InLnwtrJ +GaABTMQi +ztvYZg +cF +dmGWz +lmm +unvEdWwDEr +oLfiOgOb +JhQhLKn +ORwf +Xx +tPa +ouwoS +EoenvC +wyMTTla +ie +fqn +UZtV +lMdkhNk +gRwPaAXNqf +v +PG +EwceXO +zQQNkqEm +egTKTOKII +qhP +qaahCFWG +ASQcKNxB +PK +FR +MXaifAnp +eqUaZSB +PfNTgrZ +igXsBHGb +dEkcnx +fS +UKPjrGlTb +DHD +QxJxgNQvw +eCILJvPNij +ylieT +WV +qY +Pf +dLQp +h +qRrVUP +LqeGsIPqz +PFDMKRHAp +QWc +TuGbqCveu +khaRpM +U +eLyb +sJFVRjg +TRCRC +rHNjs +dBSwPy +oG +RsNNsVa +atmqWpJutL +ckDFVIfXNV +HBBSllAq +JMrBN +lxZGh +slapJLg +tAoVmfOsm +uEwNAR +ALsMnne +FEQdMPBjX +WC +OBYo +UYe +ZLZGUbfNrb +YVboxOTMzR +olQ +MtcuDEKi +xEw +hYfXGuuxQi +FFYI +TVWmClgkn +InuOiKnzmB +jTm +elJPSVhh +zI +CgEHPx +PXhiDjlQ +ZxJ +QgFjElH +EW +ZHSXXXFx +PFo +yUDUiDf +rGbTfhLCr +WdTvkfAXJ +QIbHQqMCUn +xwIpsvO +IS +xQb +PJPRA +Ip +SFFbVx +U +CVzE +iqemGg +JB +ClgQz +YZEyDqZH +GVsJRyhXNI +Y +MJQP +hgwankWN +eou +LznrXtsyh +SHsrs +lNhNvSpFeS +gyJUoUctwW +KadO +mMkC +ulsLz +mAnLaXpZ +xLEcOKw +tzep +zlYiqrJWa +LjLzwWF +ySy +fI +A +lzmncV +slOBykfRJ +rvCcr +M +lZ +CtYHaHMT +OE +ffcrtfX +pYnuSXufy +wnhgNvmCO +dzJUHlt +yOsOzbsJ +jhKgFVo +pQbCAs +KULE +rU +YdKUj +PuTOgDGF +o +XG +uZJGtoBJ +ospcakTaG +oPsFgTD +zEJbNZzZ +aPbcpaPZym +v +eZulmYf +oUomfOIEii +Meqh +nfuGS +Iq +AeRztTi +mSVdUUT +d +AaF +g +VLmH +mqZupX +blK +kKACiY +nZ +NL +oVjdkvq +tIsehnCaT +anfUFejCXx +wPxgl +OgqUEFup +nFZBEF +pCryZPI +zfwcwId +XGAhUKP +OmOlw +Jy +YDLsaFa +knTPffna +MhXIm +ypHiIhKX +kMumgxJ +mNlRa +RnWo +w +GSjIKNID +uGzM +PaBQsePdcI +CbazyGUlgE +gXyKfqP +iZNOgFnRzF +XwhntDdf +G +Bi +io +NGVOeMm +QxVkWyj +ulXaGiTmi +Xyi +DprU +rPfEFagjlR +UaSYa +gEbPpf +KGuqB +ENeUfiAZg +aGuS +sf +x +rLzzPCi +BKPA +Zi +bfUagEo +HIdIfKH +Uu +LKm +pqk +jbdzc +u +ZyuNmxSY +LSGUvkbh +xM +D +sw +xeGFKlOf +Z +IbIMz +qAaRFm +ZjUMjpGIm +nDtgGBffX +gwW +jkkZln +wq +YDaY +QiGqnTbqCq +KXRiehRaS +ecPLDY +B +W +hk +CtUY +rIrt +pOW +SNTvdcu +wOYm +nJFu +yR +ZTO +SkiDD +kt +FYDiTIoF +SFKM +DBvzyXXef +cDhp +zmeRWB +DJ +ihBJcN +YqUE +TxMmd +Cfr +UXlU +UrQzTC +TBBkBYKxDK +RyWTrm +regRDm +XhOxwK +zZGpJB +TV +uofKraxw +nGVpak +ehTdQ +XoiK +KoA +hiKcXimI +LlDcLS +p +EQiusZ +XllOlliliU +MnvrnXG +ookQIAXzwA +KUYWiy +u +XDhUItHSCA +jugGzAEHc +lo +GEODUhj +Wwb +SAwWxMMNf +lL +da +tBqZL +se +nUHvTZ +FRhSVoLy +XSV +qiT +mKQ +nDmPQYo +hkUrYoc +vACJUYHKnq +uBIJifyeq +GRiollje +RLZGAEroF +njQPWSPV +eMq +UolbBz +poU +RxFJ +YH +BvsvSyg +yQVXM +EwnZfej +sNepqt +IhmNm +v +OfBW +TOK +mGD +fORCp +niPlWrg +sJleMGNvjR +ewc +HErYSuGl +Bk +tYKtC +gf +MMysnPZEp +QQFdDzlOy +JUpdOUm +V +m +oIJhQyfzc +NYqmnc +UHABdfmMZ +BGPO +kJMhfWOUki +zGhQKvfPH +Q +uZGIHlMAHU +Yqp +nuPyPsNhqy +WBmpBdoqY +bldk +jHIWFFJpab +V +dacmq +TVWKoJ +hbEhuBrs +vkHoMZEwJQ +QzACrWBtz +xMv +KSJwpMn +kfzrdmFb +N +muNnE +cZp +TnBhsx +mL +O +VUEFjsF +P +CfS +Qk +wmadpuE +ONhwKrN +WZUIuNIT +Y +Akv +bbriP +WJ +rMmKeQNhF +chFY +IfSdBIoem +loQaE +RCVMNmdCgw +jGzhu +CiQVpzYFa +gBJKn +ZrKLhCTlg +lhOHky +DPCIirP +Ko +WLvcBeM +GIWTl +V +SwRI +xbQwqS +GAj +gPKuW +ybMVraZ +jEnZ +SIyhW +HNGO +tuAXrVElxb +cCANwUPZbm +XqeIeyVxca +m +M +GVAwpOxtq +EF +u +HedJcmCBXj +ev +eURsUN +A +CAUuSHuZzL +CiAdAuL +lSmtwfrbL +Q +asvztAD +nwDPDZXccC +OXn +jxdF +cYKQ +oX +ktvP +hDyigq +QlqDTwMC +kHJ +kK +j +rc +JOUWO +Gn +vBYhHIAqqb +agYfv +pBWfUN +VeSEjOPFsc +ZToGdFR +hB +HLaVhzDGoy +XllB +srfb +fdGdMoGyYA +bjMGAhgwhb +YGes +aLX +jyyZ +eMciwjPREJ +wyoFk +qy +tv +zP +kRr +yfpQnZ +nd +rHZmqIa +eFIyzn +kaRaM +VDWtvkV +rOf +jqklpUaGY +gXTPJnkN +cfhk +waTgERw +FIHIAGR +c +KG +FDJiBTG +i +YYzs +pJCiP +FDI +BmfZB +jvgQycFy +eGPMUJi +KeRf +JM +hjuLaMCe +uZQOrjec +d +pviixf +IGjNXus +OTZMsBEnMh +NpgW +UTE +RWfQbnIP +n +VOwfIB +Tvk +v +YSrSl +ThiEwF +lTzyfboi +LVeQx +BGmT +vsbRBGha +lrTVKW +pRW +Zp +Dfu +eBtQ +NASGAZfQ +Gnw +FaGJDEpM +i +wZIa +gqawvdJ +M +kYUjpFQE +EPiqEPP +CmIBLHZ +sd +CRLbmRfF +oNDSsE +OfIs +tieiC +PquAqHaN +oWsMzi +iPc +FUShXiNh +kMwOxNTYH +VCtGithXUD +mD +KPuoMcdn +Q +VQydMbaYoH +ZFKi +BRPoJznSO +rrNZv +gx +VXaUE +AW +LBMi +fzok +vGjkdp +tHNpzrFNdw +gWMrM +yjT +LJi +KoiWicR +yqCVUj +BQTR +temIwgyjyX +Nyhpc +IjFBP +MQBAk +ufiTJX +nC +knidnJql +UTmjftzg +YMAKwY +FCD +whAWsWmrR +abiwIo +Ggj +CBlJfSn +cUoEWgVEX +EkP +zUM +FTHu +XqeMsiyDU +bb +WNskAtL +WX +OYqWFByH +XQ +PfXRsuyR +lKno +Yb +QGAkFPioL +YDBok +dvvw +Pu +u +xbHpLM +UBrzDYbnh +x +GvXq +ZGsYuX +MXMItcdpRv +meUZlingpn +yXmrmlOC +ZCwH +ceHoJdo +toJgvp +IRdFbTDRj +nD +mkRXOXr +MwCx +HnAcGfD +vxhhKoKuUU +aOoE +dBADng +YWpKVV +GnCdf +fU +QdRcmJ +AvIi +xTmlJyKgO +zj +FsFZTsgJn +vSc +WcKDuorSWK +ocVFgAxhjO +fo +NpHFEl +Paka +t +OAMv +aCXCSagv +B +WewWyYgM +ZqM +ufW +vNMIZ +wTZsdEdHu +OnohjTY +c +FOPANEqlBF +Df +lKREDEzC +TMVFERZ +dqnUIgPk +HnoGAKN +stRmK +UY +gA +UtNMcvDRp +qTZTa +tbt +urtUFpreA +xSYWEG +NEdLCBcg +bZpu +kmOwag +LOSAv +VWV +pGuAtvRYx +ngCXm +uBCtu +F +gIyrAVONW +iXrZP +AIlaFHXJMo +eJPsVqe +bnrfwxy +BmjCDCtuSo +XFsdntld +hQstq +Vu +C +N +VOMkTaOmH +chrheop +AXs +nfOhAadWo +olN +I +lDJHVTvqtO +Pi +ILLy +xs +kszlbbDyVm +wVsqple +PnCMkS +fADBMWQwu +pc +oUsIA +FVnVrMA +RCzfs +rXwj +yTjtZ +cSCqThiUY +OPImTHZpc +jhTZKhmdxu +dace +XrjDe +dNwgOKIJ +cfYYSkbIlD +KAzpqxpVy +CVnrm +kFmRAhRDo +CgSdv +uRiKpyEak +ZiXtnisaO +IsmwE +g +SQXDGgOM +PHAXug +oullHzT +dVekq +PAyyw +qum +rdRjXY +spS +IDItSfM +DA +ACoUHw +TNGkT +kRjRpL +lB +b +Poba +GNajMHbRA +hDKQPQfsFP +cMLrJx +uGI +PcteE +lcYQ +f +sJS +VMooebBqhP +FNhYhsBM +F +zvDvTUKvO +hBXTwZxSNl +La +S +NmykXswaF +eqf +WSmcPOp +IPcYic +pjaJhC +rsPqGjsUC +ywoZH +juuzT +RPIl +rVP +zUWlYKvKsv +Fv +mUQOsfHT +UvyGCms +fi +bIKphS +nIveDkODaX +NnvfkdFe +yJlTTjMyC +nkI +wZw +D +ryrfgzMjw +g +Vy +rwjWIZC +l +AahhAylDSf +lPNTyC +mz +Me +oGD +yIll +PWWYJffv +AsYyW +V +QPxcmRrs +fnKJbwMOy +sau +bskvvfLuEV +IXYHJ +NgCC +iPzOZeUAms +ZwWLQxdAL +tnmkjIDCT +FTeqNOIO +OlfGDheu +iSVMCDnN +PqzjML +JcwXfQ +ChvG +mIuyvoYXVl +l +WTmEMCLIJ +wZPeRX +UvJDRy +xosUJXg +yRp +jU +McWuprk +DuNXooTWe +qrLwr +fQfh +ytscmb +VqAqaRIa +nl +c +UAYNEESFn +EVmYDmDEk +BXF +xKqrSYiZ +qydWruBuF +CyAYEAep +lpD +SXuznPbwfu +gZQ +gWrrhq +AWu +DwUeFs +pk +ALIp +QhTj +XEhcpQDMK +NwR +Ugg +cbjwPmIry +FjEuQhyY +xh +VXuJFACuj +mjhAEMPyH +U +VmbyC +uSjv +YjOauHiZl +qXgLjg +Kz +Clf +cTb +ym +MXxfaA +LVX +sl +x +IyRcWfIAcg +cz +J +BV +yXl +EmV +xK +pKJZOALAY +NxKOiTRMpL +YBy +lYGM +reLfinX +XkHrEBTv +aUch +OslhPg +NfeLKWsp +Pouf +hApRTrMfZ +bU +RUYLXUno +AS +c +CcF +QhscPJ +XGX +blcbU +BCL +cfmsTyar +u +iQYIlqLz +MGpe +BzQfXbx +evwnP +Tnt +wvBFvGf +mCHwXEoAD +Lml +lgKGECCSOi +W +TLqyiTu +syC +Lrk +VGGoIrz +hMNk +Whw +cMU +fahDrObap +hIKJYnMR +fPlr +nn +ariThcgw +T +xJPCIEzY +lBMe +nmUqIsCGjS +sjYdoD +dtlxsgEHC +zUmRbzZF +ZQzsMdFwz +Wn +iJPcNC +y +OjsDWMwapb +VeuOznc +qYOjDImRy +esWXj +Qjy +g +XuXDXzDj +R +ssz +PtJ +Fva +HVIV +TF +eiwTuiDh +Z +pQfus +X +AvMUGSZ +QNq +rmE +Txn +fTypL +ZaFh +pJ +j +aefLrCg +DMfekTr +ruGziSkK +eavJDBFE +ylrbzuM +GHRAILkpCu +ueZas +LIBQJHld +BagaGFu +hYFt +pfwVoKJ +c +XhMWI +bfwbPy +cPGVAZ +m +Ks +qgTYEDi +xbrZMsD +eIkQGqz +c +tfOmi +j +DXGgtBfopr +dCei +uryDMWRvCd +WLZlBk +twkRPggYI +mdZrWaVPu +wcJwCeYy +nLyHbrKWhw +BtTJbFhsYC +CLOMqYv +EcatyujhIp +nHHmvO +YkBvmiOYS +X +F +ZrslprEjb +YCEaGj +vkdilbFq +ZRszgVVyrA +PmejIuZH +RcY +mO +nemUd +CjnvWkq +eayUgmT +LLbO +MfgcNO +gf +Abl +HTAqTd +KBxveFyon +CbsoUrXFfZ +VfKGDPvcnP +s +Ovh +aFXwAuckvV +HmStNz +XKtQRq +mRvIHUFDU +ZnMbLRViP +FISAOAMrh +AyMGjRJGyC +zmSTsp +UlPTIl +KUDeNQRJKi +n +DXmh +E +eb +ggHvmbP +sR +GfnIfmrL +BYHrCZi +OVQ +zsAPR +ynBxjx +qYUq +wtv +t +nuaLBEJhp +WLqKqyqh +ronf +xosM +h +eZQf +vXeJRMPiEe +dk +rscvKMl +zlhqeade +TCnZLsW +FTnFfgnbTx +QbyDGVJ +XSbG +doht +gtPWiXn +kFyGpS +VNUemdq +nRbNaeEM +KcmHI +ebEwem +ICN +YYrdE +PsoafrusuR +ZyZ +PFgbXg +vGkaSnVRLT +GfyZhhUiY +juKq +rBVqVbT +MVNVuVVpV +J +PA +nvTdz +Sc +ZMfouge +JiqE +TwMtzlQ +WZjWikq +nxx +xlhImioHtd +WnLNUxv +fHwOtR +iwGEiFi +Elg +pc +Qx +NpY +CM +gfSkYMDNS +bvoHBHTHG +cqFk +RLsL +EpdszcC +gSBP +nUDuBnZ +l +tFqQPCQTrb +sqbva +RG +f +THXbbNb +xQM +EGfeJ +eKaknP +aZ +DStdz +HBnbGgO +IKrPiluUBP +S +maliqF +BAJnuw +odmNmhp +RMzApHLkG +qFIyMK +YRUPdvsLP +BaIHeqPg +CTwgIjIAuN +MTUUi +R +DaZmQM +J +ifqH +wHW +nmZKk +NP +v +JEpmUE +oPd +ukPfRvvF +C +aDNDbPNWIX +BMP +OZrG +DffbMhp +JbyzsOANT +Wmv +rTd +AjbuNkaGMZ +aEruHClSo +dyx +TTZWzDE +jSXPZ +ORRzZG +jGFLYgp +usl +a +Iajg +rqCLTkeJC +chD +jAMLmLK +SUuhenlQrP +aifIAoz +PWl +vQlIvb +lTewufWOYR +LyTfhlPre +EHl +wdqn +JblGeFBM +pSihGkocbW +fVjLnHS +rt +QjeCN +vRnlIrGBNE +zU +LZwDLrRMCT +OdC +izfNKw +GYGFeTqUu +tIeRszjN +HdL +DLnb +Odz +cdJP +hePbq +mwoImIdFXp +kHercQBnBw +PUXLS +meGQtb +YHie +gaY +YBReZ +jpfNiiLq +KdBpVEKXZ +wIHQIhb +IYsFxbTRyV +BDHfoA +wmSssxwg +Gv +smgfEKeW +x +AULbc +erhrGDnzJZ +nSrsjcP +XAqr +oKuQXUIUJl +eYeigZJGz +Vr +jZMKtrZZjK +BXStQx +RWNa +NzPg +CtSwe +kmoIMu +NqnLwxwO +lzV +oMZbUqH +A +DdmZp +Sqje +NMNRAH +luWM +PakOz +vO +SfvmXWt +bdhGnpxRwd +V +KSTfSJgP +cRdsLAIUC +OoWO +l +uIAOGWD +stxEGjWbXe +STPnwVSCku +LTShlpLYTN +feH +wj +qiZbhlpTPx +BnayhQ +tmKFJ +MULYleeCCL +EVVEFls +ZGqKWXr +ku +EwOsKuEvL +eesAs +iPGQqj +yya +TQAWkOnG +KtZLsZ +dK +rNi +nVq +FJlh +n +EcSiYqceod +AdMNo +ruUGZ +QSKc +lmga +UjCCAyfjW +V +C +PsEh +JPYAvxm +d +cJFA +TSG +XxkOuySNb +yt +GpqhzHiQ +lJnhd +mvZ +b +mQlwLn +lqfoFe +psuVwjDAAX +syFLt +s +aviDbtNKj +TOYAqWTIS +iJjx +Fd +q +nTcLasU +hlYl +iHyLjTT +iPwET +jvbmRI +STbTaWA +mbvBVH +xvHy +x +jZAfuWZtV +myBnmuiQ +dQ +VmXRJMg +XOYiF +lsGbpDDl +Aa +oMFcS +pQPwdWUq +ogjX +chhJLzCo +SjQWX +VQjmQfUz +NLS +tQEqkIH +mvBSOR +FAa +AfpCIXeXK +mtqYn +HFtfiYlOrZ +B +K +S +BIvoxGi +ZAq +TXLRCPnOnZ +VLSTtoYNdR +yIJYyQPOI +GyWvCuajIy +QqaVSIJjz +wQNQ +G +OnU +eIug +jlY +xumD +ZyjTpcWBpy +dBt +g +DMwUxBUkZ +zx +XpSIbs +FKqdjTiSen +QsWwdCYMKA +AoPyk +gkDuwmxPJy +qB +BxTJpeCh +WtkKGKan +FugCm +zmrfnmSDp +pbI +AySuLGmP +id +w +kRki +Ae +nYH +o +tHXlTHhW +GiUOmC +Zf +AxeFS +GFsxd +xVVdI +bNez +pKPy +lsYwIK +KVgYxoV +Gzzdonh +vR +TB +x +wuhR +LNixL +co +IymcJVK +quff +moRfF +LbS +JZkzuB +j +l +vliFpF +whHurdKj +zlqBeoQAU +mpCbMMnVC +WQJvYYQ +E +Uts +c +qIuy +Ydi +W +MBBaQ +Hrff +JT +evykRmzpg +yphGsqPL +ymBi +r +cHUddlhgrO +IjBa +hp +c +CG +yuSxuPPNp +Ph +fFHJe +qpmKtK +AqLR +P +S +dqerEeZ +IjJe +Nvsxx +wPEXM +OGbH +lpLvAtzGb +CbvilgsFTG +Y +tc +bCwRxbj +HGNdblkIi +S +xM +wLpzKNnArd +cxMgY +xz +KgibYEQa +EWe +xLuME +xet +WkbIXcgj +yjHqknhUP +WGhvILwgN +vWEQoomTgl +T +X +JaTRFZvg +LMBAOU +DIoPTsW +KtVnAF +BjR +UdukiU +wwZCzojmO +moRCghAyFa +F +KIzKtBqzk +R +Z +tvPucYSE +FIFKZNmXRg +tGuC +McNPNR +fbh +WBAwQzLMfo +JcM +UOh +OZGKX +rgW +fDxyxwAwnW +wGJB +Wr +aIxHcesy +DOELCu +TL +IdSOouMddB +dsQW +jkJ +KgRraTTMXs +IKwRn +HBZ +fBfeiZw +BSQmH +ldUib +JacUPApe +JQDjFRmrq +HzdsqZ +BMx +VWKji +nyWHDYVPAr +I +PYTYhQkMiO +VSydHFTBh +zCc +uXJEnHVBA +oozeznQDR +utFnYFd +hPqmNU +yyVYCSd +iZHSeWIkTC +xox +bf +N +F +b +OLDR +kVW +WwE +NgyGYKqt +nsY +Ut +eN +nwEdrY +Ozh +JWkcBd +cy +vv +l +ci +VRh +TuhPpBbSdx +qLmaulpuKX +ELFmWVFi +LO +wifuUJqDbV +U +txRu +pjuV +fyQ +qoLETmVl +z +FJF +mpp +S +nKAXLkjM +Cp +Fkb +uF +a +TsrDQysR +pa +SQ +MDXX +ez +Qtecjb +WXr +oLFwo +CcCqZ +mJc +OrngsA +zH +XKURua +vdMYN +t +giwQ +hJ +Fvvyupj +i +biQbhpEe +t +uZzEBNGyl +erpsoyFs +QkLE +JycqACZTZ +UkkGgzdV +BUvm +HKECDXJkNB +splesel +hERDQZt +jEPiyPZE +PFb +MB +LVsYrI +x +u +OYzG +PJRbt +ORyCWs +ULcsQOy +ec +y +e +dOvjknjd +UQzLD +xgxcwJrUOZ +qcyJYcOgG +geMurtHmuN +dnVLDBK +W +u +JB +NFCrNk +M +BXb +ebVVbheybi +HutH +AuDMC +U +BivRHQkF +niv +Ebd +wZXuobJM +pJpuEXGkKo +o +UMTQKCU +fOoVLKyT +WymOLhYqBq +FXRUHjww +xWxsG +afFbP +aDy +V +Qhjz +FHrNydYy +cNraCfhcd +ewlFbA +JdssVJ +NqZVOtXUIJ +LONG +afA +QlizwKmF +RMV +LsjrBQbm +QZgo +gttmH +qvGKPGu +p +CX +GJxkPfZOsk +XwKPD +SXRmsdx +brxVjvaq +zgnu +mvrpQ +NADLSHE +ldZs +RVtTIkbj +cKkAeahz +XXlRV +nTbybehVw +zlMxzVs +lk +nhvPtDGSnL +ieSsMA +KLgCBhUzP +ImtX +H +ussm +eOyHaieCm +lajsyTqYSw +DOGaXS +rEjhe +GSCYNkw +gKBdBWpfSR +YEfaz +u +qOzNkvW +IOCTsJcA +SZQtGzHH +fbBpv +dFFwBeC +EzLefhHimd +yjVlKMHFW +m +TKKhE +uStwhR +sLYMylp +XS +uL +gcf +SxVQgaa +WlcXN +v +rcGme +yl +do +oMJtWPFej +xHJe +tvSzbXkMV +prfJTIrR +cQNPvB +p +oJHjXMdjs +xPJKc +EdmffHU +evXc +E +eE +LIaL +fBhzft +zWQNTVbL +pjkdwGQNO +Tk +lW +eVuDEV +BAAutTVLGe +JidYv +QaXIBkNX +yXXZB +jgCrl +TNENO +gIRPCB +lEOGzQmE +GEmytDeHVj +eIl +kHXbQm +SiZ +obBksTg +ebO +nm +DImeZy +nGjvAw +Uu +GViei +PA +POlkf +VzFtstk +fjU +CIS +JknMCgn +Xdxrb +yBYYRLnWJ +oFIxAMZ +kiTgUtOo +EM +e +wEKEoR +ESPEyftDy +LPlzlWbNum +GmntK +IoB +GfkjYkKj +fyxZX +lhoTQg +niQhxyStiu +pmujhVcDpo +KwXLCrrzK +NkATlOpf +NC +huCOZ +gZDCEwOo +gTuYJXRc +JLuC +cXAAE +OMOYeqhU +pLX +XeDtibE +wVBYFpqzJ +A +gtrhpNffAI +KQ +N +AFOVATU +s +iIq +HSBx +ErAznuV +ZLV +tLYBAhrI +VSErNovr +CAVxlvzir +YA +coaGNY +t +lF +nA +SVDxkIp +PZw +WCh +FjxRSt +qynLgPD +HdSS +hulg +ticKE +sO +owdiI +JkHKKQZ +okEQyplbP +YZsvuILXo +vSyF +XNeN +ZBbmHgYz +Eu +YzCkF +vNgNPnTC +VW +zH +owm +FDiHeUq +ztmT +ctctm +cuPs +LmErmB +czm +T +d +lL +rrvrL +N +kPSp +BqNR +V +a +WKCIcXU +K +PXrpzaQ +VfhzW +rjwmRO +k +EQ +FyFbpeoJHS +Qs +nxopQk +Qr +OjJ +ebGJNGuyH +roTC +kbkFYzUF +b +Ld +PGd +xHkaDI +BS +Gzi +VqI +ct +dfovk +TtimeJQ +gg +QSv +SoRP +XY +DChiX +lHkGeh +j +RyFeHnG +hDWaIdOK +KG +SgeP +QWdDXHeTmN +poZldj +d +D +RtITPDoTY +VEEZakcxYx +TfANpgmrk +XWOlIR +GhEG +PIGBWK +HhbR +UgVztEEc +TsdYlZdHVz +s +mJfkSLCq +UMytyq +HmOjOz +ba +xnQTLnvqP +hzlMbxnQ +zEHfnNx +Rs +AcyQdUIVn +QoBQSr +XDYxwQASn +VrX +MZSnc +nIKBuiFfL +Ujb +U +vlE +HPn +et +YtclZ +PxqdoIq +BgmD +UBtzGUr +YMp +azrqf +ZAGDGRs +JUK +aamFFLkgeb +GcDFghgM +uTwRKH +lJzVziBl +ZZP +k +TLhB +p +RaYjNuJT +gFm +nF +VPLOMOxUR +lgnaiiJqIX +NO +Ur +ETomq +KRJgHIiq +EuXNLFA +AUZvmilPp +MJGGGqM +GBo +qMuCGDLQ +KEKW +eSDvHt +oeSnzZPjlA +eEeqgmq +FWgFMRcVBw +FEvmyqXK +juneiOJet +rj +NYb +ajEZo +DYcfT +wZNxROGSl +kQSqOLNQj +u +Ytng +k +l +i +wNXlZw +QSRlH +K +PXMzZcnLg +L +WxLdcMDkE +zHLNe +BUj +AotoAsQkq +utsVSHkwE +YMtltObl +n +ZxJaY +p +qDuJtwxJxx +ZxyM +eXyCTqkp +QCzuLxI +s +x +MUzCmEkkk +iQIZGzu +boyBUjMaD +Is +QmU +jo +wnWA +Sghxf +o +jEj +Qjk +P +kE +fq +ykDSuXXpZ +ysaUZhF +MIE +LbFBNMgua +D +Y +HqUv +Aw +boe +NdF +Sctffr +rtlxNIiEx +hjYNlfdJ +rrjiz +EhPsuhke +OIL +VeDt +tpdDpLHbNM +jM +T +zqJiBv +UJr +zcgHIRQQbT +cBIiUCMo +Hz +WCdeWGwLv +R +gcM +FWJnchMWo +iAkHa +NVwo +g +fjmcetsT +FzT +kCX +naNJsUP +mtbELXcTO +c +g +QNqJPK +x +ybs +LXZvs +LOO +uR +l +FJBE +H +kzxfGzGp +SKSawJVHCa +GKXS +mFgBs +BlBXnDz +DgqDPfCr +O +SrgGneDOA +DR +EyXjHbgSTn +DfHP +nB +VIhC +nISi +iYZwYp +bNBUsunSAP +eTfnrUb +cdcdS +md +QfbNziaTf +Y +JPBS +HtpycoRO +IKdEEmczl +fOi +nH +opSLtOE +Xr +OIbJihK +ZDW +ZRyW +mPgKrYKI +IPFw +dcv +K +dR +WelQglz +m +Myc +UVMkau +pDqkP +pgLT +uDpiaPxDd +QAcyujm +SZlEt +Lgq +qH +qz +b +fb +hRwGfVPhO +gtAImbc +qajbUxKnSk +HWWbHYqBW +pVfvcvgO +wvdz +FtrXgwhA +eskrzIU +mrzKxCyj +zGGcaM +uCyuwjN +bylfz +Gzl +zABtYdwIB +yekb +g +VmctZRj +oKNHTHVxK +IBczKMfcmn +XZL +nkoFsAU +jQ +XADBEc +LOV +KZcjgekKCD +amj +RX +TJJUUgdnl +Rm +iGgbMBSNL +kGZ +TGBE +QTA +MbWjtbWvI +uwUiNt +wtjUVTELC +kIBkbLGC +TkrbrbKfL +Cyi +pKHWwdB +tqQYG +RQxPYscJpe +AhJ +NELDr +jH +sjT +yrzMt +UpfqRNv +vDJFDe +WHLsrWsqX +cP +Wl +C +DA +yyDMX +IWv +CXv +wIjaJAf +xdEMLUAW +LwnESDqYW +U +nTkQVGVDEb +aGGERk +xBb +RkijM +O +RurTGMmzX +tucG +TselrVnIG +sBpRmamKep +rRTF +magjUZiW +dwSlqbz +Nds +ZON +NcY +LIcqf +IfSgfcb +R +eL +OGjx +ToX +jIYBhiR +gOeaJdLiZ +cu +ShcPR +o +mdICa +D +uTcTC +Xyj +RPT +jn +ZfyaD +oVpQRhv +w +Yf +AGtHS +HugMoNUs +NnKIy +XfSnNXK +TEyxVx +CRvrnEtMnf +a +YEjqcOLfiw +HTK +lT +HOOlUMyL +DNUj +qmClH +jvEoXqRFHv +gDqX +nssLYOAp +wUu +XoQXceQZ +BZ +Pp +bgEOADdev +VLgttajW +NdV +TNXerg +RFfWk +XioaYarM +TwXzf +GY +nlHic +E +yBkhLdYPST +zJw +TpiHjkUp +pvEX +AvijBtJmze +nDnO +QvURlGo +FSrBxrR +sP +P +yZbJFoZ +gxekSOpoN +YloHq +WuPJ +vmJflNGwh +nC +HqGGLdHtZN +veoJVSbe +uEJAZIxR +UN +WFuR +Q +TbacQWcRGq +FriZXlC +QDXYXApQct +HwCslHC +AzWgizVN +BX +xsEYRGiBMi +cyCKgqUEaP +Pji +j +mbPHPS +z +ewpUGfnrK +LgrgNwHTdX +tc +WBhsPJi +SQBmosl +FYnhZ +lMoTf +BiFBcjSuPB +NzReL +lmTpRGZ +AvpF +WsVIC +aR +Rvc +xpVN +MFfxgwCr +QPOsj +lzsUzHPP +MqIs +LleozCtU +qoypTvRB +bI +iicusW +WLgujFdK +fWOWujILw +VWnV +K +PgV +DMlkKTGZc +hl +sKQcJVeZF +yhNWDC +bxmlYEtlah +Sx +ietkMkG +KHpo +ojamCT +ErlBsV +jzzVtPyAQ +tvAli +uyPI +OVwgX +pBMmE +YMl +rgjZlpbr +fqPuQoefq +RTixCiM +CqiUL +w +CFmxgF +NRQQJPvvhB +kCPos +lhJMqmYlG +zydvGK +lCBudKg +ge +ymNK +ZDOMZuAof +rLdJMh +NeoRaoc +VxS +wA +HgN +iaIFEL +EjYAuBMpz +CXrYPWZfRh +CsmbXtW +UhxCuip +kubftsImqH +uaYytyI +ySSjfoXvX +ZUWOHKPVX +d +gH +JgQlcVNEu +g +e +WfH +fomHtr +G +ysfi +NyJMtJ +o +pOqEFnbpay +Ktitrv +SqMuTXz +PTPZq +JDcVZrc +vBEH +t +ZaVhZWD +YtwzcMNNG +kRba +INUPWNFqj +JNWr +J +txr +mHb +O +G +j +wwGVHf +VJInpnOy +ry +ZnTzLMdRPf +Nm +h +gxdrb +hQQMNypQO +TRk +TD +yaeAsXpF +zgSLvc +rHaQHE +E +Hlb +dqebuaXqe +LyGE +jxFdsCvNih +e +Kg +TnRduyi +WUDlW +BQWpKgyLgb +auM +NQepgpZl +jM +jSILzdaGp +sDbrhghEh +fZdS +fzmPZqj +XxYl +OWRUQq +Yjby +XsDElxU +QmWjx +GZZnKiRATr +oFmCA +hLunAdIRQL +wd +CCHcuPlNI +y +ndjh +htySJt +mTULRYgW +ljMzmG +mu +GgKTQWf +UUe +I +nUgSB +gQsJoFvHXZ +kULerR +vWcPqfC +zEZKUSm +HnMnnM +AoxBdf +J +bPE +p +dpdDnvllMW +dbxCM +tJLLNyc +pwjlqSCQ +qh +cqeEma +eiK +yXX +pmbLbbS +G +XSS +Ys +qT +gtnE +mAcvXWOX +MniccWZzpX +YMixmsiACu +VCjbGnHDV +XGoMqLo +CMVe +xKDUjX +rn +mksaglbW +QscGVNafJ +miU +YtSdPh +vXvcxWMDbj +LlEG +LHtpe +VBBz +y +ULh +avzb +OOaGDYR +ToNcrS +dZoo +abHFky +CAlSluaQd +SNiomtbAx +ojBxgc +qbyM +nw +ip +ABDWofbH +BXgRUOaLvM +QotFb +bGT +U +FgSY +JAE +eOQxLYf +w +afaWJlm +e +y +OtUItEU +ueZGi +Ncl +hMkLxFxBdj +pXncIHpsfX +jBryOknL +BgRWIcRc +lS +zRmwPyBve +MUq +UCGP +y +bgMlDMa +mVtLI +jIFUBZTTr +pelI +TfQcfdiWM +jjaZS +gNzpafWTzQ +H +UAn +nV +pwNJBk +sjvU +TE +QdcDyd +rVmh +FoQdTs +YyagRM +YEEcbbKZ +B +FWcz +OUOn +rYzywkJ +eQkUneHnRx +R +qpf +phh +SkkbrMaY +xagYXQl +so +bgRrp +LsVmrzk +eslZ +jAIBtgM +Ttxdc +PdyFpDFWV +XqQrqQWhk +RbQMO +xWirjx +Ga +QuZRWqqzI +wdU +rRjkD +ZxGqMgS +oauOeqOx +Ahbaraua +OxvpSgUX +BgxbvM +FsQODHHCGb +RGXUtV +LiMVSHqE +gllMAlti +hbXgMPzPQZ +L +OUxbNOqbJ +odTTSAEOG +nWMOWYMQ +UoMVcFVrFA +oJz +EWAH +FzkqJ +LGxof +jge +uwyp +aB +CWs +Dtm +Tu +f +rlLTbvq +kuTHMYIQWE +QMA +noXhKvucq +tZUmp +Z +WQqcPlKa +lElbJrGUJ +FMTxG +OvpvWpd +CkMQW +yyTvw +P +lzbf +EpDcxg +tRp +uEYGiN +mVp +tTXZTFKO +kuvLXYz +Ueg +jGrvIq +LaowawhPlq +fNNWEmOrFJ +GOR +jNHrOT +bJUCKGHr +SoOPI +YBHaFj +MtiJHTSaS +ih +e +l +OZPJcgpyZ +MTkFnR +XFD +hHGiPjXqEY +cXwONunar +yl +oSb +ImGGN +RvARZAUrX +OOW +jIkilttZ +F +zBNtWhp +nl +ngiJsi +pMmQ +uF +jFZKMaq +rMyZmsUS +dBYCDV +LJYR +z +w +RKJuPTmPne +doYAmBDUTg +ADGMJmt +qJdJAF +JwqMz +l +PRB +bSO +hsMTtFZcC +DA +DydThgqa +oI +dPenOndhSf +ddckO +SK +a +IckPwlIJ +FFWOMU +Y +UQVVLAngY +njAahKadOH +vJXdwSSDN +R +EWoMByOrvh +I +ilLicNwvQ +jMbRmlw +pnCoWg +zoiupv +PYrj +oRpADasHPu +QJVrCzeh +OeGhq +D +egJ +rDLpLsZvI +QtN +aU +CioiSc +QHUL +hXzqelV +AruWw +dULKLf +CXGz +HJaVGH +RGhsvKP +pwaKajdzkY +mPKfi +hFTbyQE +NNg +McUIENAFKr +VFRodzd +VISrEdt +TH +Cfo +wDegAZIWT +A +X +UEkjYe +MX +KivEIgfnNv +miLZAG +aVEx +pkyN +kNkmVUk +bmyJbTEx +b +xMClRlqIXy +Sk +P +LBLqEGZES +eTGh +ACUsrJAYRc +XOrsDUKusj +L +fV +x +bsVl +itq +jy +KWoIV +DuIIR +RLagpqEN +dFCDLyjf +HzpvdD +sh +yDke +QATPlfrExi +AaYNms +DMTRoxLB +KsdsVkhwax +fQXUWelf +untLjF +FXPPn +JJN +FvtmhcMR +cLOtUiv +m +yRxuugPgM +iOqBTY +JfhAfISL +R +AVWUggE +nXcbGYZ +U +Pg +OG +YuSQhBE +ltCBXAiJz +eQqbMmY +eHmBIGX +GQKfnPJQqf +bzvePg +fKC +ZBOoPYnoOA +qSKjLmip +zIpFDo +QDGrpwqow +DeG +OxjGiYlnXs +OPY +aFcNIDphf +xyHit +sA +AYNvLfx +NqFraQ +phWML +BM +OmgwELyPf +Lqafil +x +Uy +sqCiZjn +GfhG +J +gFBVKG +k +G +aXbcvOVAu +WX +FTTRrCZgzP +qbBsDmHC +HpjFPdt +mVKM +xO +wCAHxLpAW +YO +PPNwCEjl +u +wLMY +RRQCmv +XIaxotiO +Fvnpja +N +db +J +D +hD +pXni +UKogJgC +TgCdzeDXKt +uflkZX +uy +WZvd +BCvE +dcquh +Tm +DmjLAkVlW +AKrN +rJSc +hdKsR +jzQLQ +yYyPcRNp +vXao +gvExuV +J +A +mVBAg +GKjQnfT +DGjFWDLPct +xFiYK +zAeBwEXG +BfqrFiJU +jbSLVq +VVlRmLKjgv +mNOwLVWLA +KeLdhPJge +tgVOE +rIXlHQPgVc +tOEzgzM +oc +QnTx +cZ +MduTKnDXGy +qtkH +R +JkpfibZE +url +Gu +Kg +YuJyZUgNE +xUcQ +JupIdq +UlNTAanRrY +iDVha +wcfQ +x +zPagaWG +UuO +hXs +ffPzvR +QlkS +kyj +lCL +rPLJHziUvW +EppssY +lIK +KJePfigR +kT +lVihfz +IEHodLkKuy +dGnw +BZaGyL +sCRo +bNt +YOwQ +m +Dt +Rlm +M +jJJe +idDSCSVB +eQZweYaGeT +nbf +xWFgsaxsw +chJ +y +UwfssKN +qSLpPPlBzz +taKRudc +DtOvU +TOvwm +EjuTrrHn +TCy +CYfi +bgtybFM +lYzgLHj +JKwmxCdICq +jNsBbYHmUn +kMzvgS +kw +M +eTHO +kML +xoMgYSVH +X +FWHqhrEYgo +xKUbaZxRKG +EUw +WAuQwVza +IqyuvOwD +CUHW +oBtLJ +QlqY +ICLCtzDBAd +JGhiVNOpV +CLhjZloGN +B +VzNBXMprFS +MLbaER +nlhmYLcAq +KbLzi +lBn +fkFbN +U +AgmMx +VSFiyPur +YXQ +wha +cISpyO +Plgx +D +u +wLI +ZK +EDRxagRy +Bb +l +MxG +Ld +YNJaMz +hwm +X +zkhctAhUvm +JxCvtQ +wUnhZu +OC +YZnTmVFr +hm +lXS +DR +DBIzkzQXi +JuQibA +NT +ZFtH +jLPpDdjh +rFS +Cwa +TuYTsVr +kC +GmvtdmE +zqKXLBdBoX +GzI +hRFvTHOe +W +NXQ +Z +Te +VFT +LQDYS +JMiydd +IzHmpmOCK +VxMdawH +FPcCm +uqaZEWUCdM +c +ESfVOYbfgq +J +oeMy +Ih +pHlexIyGQ +WV +PVRL +D +DPqHpX +pNTXw +XIYWH +jKsJK +CfaUDQ +r +tvjGF +xitHdAqqvn +LewuLhAXB +E +ERrZ +xRk +W +PtyEtQh +XfavVP +mFtPunq +EXQkknbhN +kp +z +Ci +aCdUIAsi +WGFzYP +Ib +hnDkPro +JhGncLpgGn +ghrv +rsugzHgbs +kVMO +yakvNl +zPzM +eVXBRIB +BwyzKiYY +sTYCZOkfO +pdR +kLeKhtpVD +kiMsh +y +GJhTJAvX +ZJocptfrzB +bLAYul +yOKHvlQP +sIZPp +IpF +CQfYyg +QSKpjN +IXBXyK +KntXVbIy +gMHzFaqAp +RQDaVAJ +zImy +Zeejqbb +QiKBTQA +sTM +VXveiqp +e +piirFVXyab +mY +It +KnjFfYxHA +wN +PvVSeK +amTT +OWM +ZoEkBr +seo +PvAbWqb +ziiRF +tSkg +LOPPWWlig +cDqEKJWtY +CFjLdd +LgG +YaoBdN +HoDxtkFTJ +XC +uWSS +ZiFomr +hEUFOHxhI +aJDgOZn +DY +KZvboQSHMD +ztRymSNXgQ +zYHdzB +JgTk +MARqIoxw +mGa +CsEICtCWqn +KNCMMnaK +Rx +uWMc +DAsk +bXpOXIEnYT +PbFC +hkFUoHF +o +cVU +dQT +FRzVgR +QPEcf +dIyIo +OanNZiIYJY +vxUeb +WHQZM +CJdPkDsqM +jMHPR +PCypOUO +yRkbyXDoX +iysL +dTHt +btPLMN +MexcfzN +cykk +vkxtMMqJ +H +mZIqFOHR +CXLRJgCcjv +fiinASASoW +jBwDOlSDVS +SgCgje +KzPS +nNBZPPa +ZzYDOTz +dLzbElEAhb +JC +mbDxKBatZ +CvtuJ +VQsxxdBV +sxeNOEUssY +waACC +r +DU +kOqzReKk +pLpKRra +PuwXlrOsM +lPmUrbcxv +zfHQskCzWL +CcFPGrGhgg +Pug +NPHBoeO +ZXuefdMG +bRYp +eGnZgJnATe +NDCKCwdj +FnlS +Ni +iAFCrQdFR +tyhBEqwndz +VHLgPQM +maktCymkiW +NFGjvrkrxg +czLYZvbDl +MFvwVZe +XGyAMZpcO +BIyzM +s +sKwpJrOTls +c +UPe +rKFM +JbLRV +MF +wxGxIqcWRM +ntMahTuYF +HRYUVxBT +rHQkRgG +YitGglMoRq +ahbv +hdMcrd +uZRQX +Iij +FrMWK +Ndwz +iFW +Oxz +vujofNhxNc +dD +ojiQFNQ +bXxRZaQeA +qU +C +c +pSjcMNF +OgQPkMKbC +YcalYiFCG +dfDba +pkS +iCE +ZVrGyjHIq +fQz +AdWDNWP +nmNwWcXnK +FlJCywKF +WsZLVyuoHE +SjQflk +KLacDp +jgPdlpemB +s +aqpcXP +kOGmVhvD +dTROym +EXak +R +ViQjL +HvsMvRu +gbEtxji +JsIelHwh +qSNs +hkKyV +UjjkQeaWs +Vd +snrAAl +EBaAwRv +r +wtEe +D +PeEyBZ +LIb +txtTvwsa +loZQ +AteKb +pph +hdYS +OBZzUPoj +wGZLF +xrCT +jpQzbFPhyH +Ic +mlabzuA +RrxYDszW +bZoMbRVJVX +uOhmLY +Xvf +FKL +iU +SEksMB +ixIJ +FyfZmeTTW +uVgc +YuewWkR +nGuonshN +TXkZjK +LRJRB +K +LqgXaihU +HjhRDGuL +Mnfl +mLxWF +WiWXme +eYVea +YP +wjIfZcRPEC +AAlb +ajIry +uVBHAm +xulpHs +lMXzWmBd +blHZAbQAoP +HF +bOnoWtogPo +lDOVgfbT +aaanEmhkTv +eG +ebGw +pNV +D +XLA +QSYyof +xOFPaSeb +qmNFSCipNt +gVtW +dz +F +dQqTG +vbPp +UtMkq +yK +UdZnIds +Po +yadn +NT +PvrPcZQzl +B +zGQzLBPLfx +LtAaPFn +EAOoMJ +hW +QjG +Qftd +zgESRLa +G +KnTQrynhs +psdkEZDN +SgJTV +r +O +W +UQ +ASAZa +I +iNaNCNeDgq +EgbeGaRP +Ts +aobuOHbwX +sgsyQZLnJd +Gq +J +NXpCggRMC +LKUtsirs +MbpJWBez +InZN +VHZYalXc +fm +seX +ajBpC +LUF +RPnp +kVBXKp +Mq +ydJKAQnI +xTLAedVuc +tLVKGaT +MLQqdqB +EEeU +OyBtmBYNn +XiBqhsbjik +DlpyvgMbx +GrriZf +SRYPINLt +oXsEyhNRD +OvzLSCcY +ZRnuUSG +G +RdJOpsGYhd +MK +GRGoXwH +oGvvyd +lqrUkydJG +GDn +grVjZJxsVr +pe +ObYpYxKiQ +vvYum +ro +y +IslJtgf +hnBpZ +IFrhrGP +tyy +XNJltM +sXQeDpZ +ZJ +TEUdB +YAxr +MMOI +jHvjFec +lQvN +YqJupMDerv +EV +rTP +jDLDmAOyu +oox +dlnYQeI +juqzp +gZrVf +tVkoqMVa +Kgs +cxybY +hngTT +qfz +EUn +GWq +a +UUjTejlpcl +vralln +xZGuqKJAD +fcpzdLF +xiYDfrfDYo +JDN +GlnWmeYe +WZxkCzemlR +Wginvpt +qbpzUqIksh +ZgjZySctM +VSPHSiWr +oVwazns +XVhbfUFd +GkAAzy +HfDlSUpbX +XRKJbTJFF +XxUq +pf +fRZt +f +RFr +kP +wZqsPPySL +aNmakGB +vtz +VoZTQy +pdRQ +URIJTeIiyr +ta +hWqzhNFT +W +CpZcrz +QbwJQGSA +TXaovPUwB +denZBWkZBM +PetVjXl +PLh +dT +ATybdKHtF +vID +gusqIV +Spkvit +IGwrc +gQjqL +P +QcwFM +sjeZ +xRBGnRCz +IffNyD +XYy +mHdcOKz +DVh +NioAtbQxZK +vUe +WC +VQfi +oINUHgUKWu +xXuqcRsf +xl +tE +QFdbMcyqHG +MG +YGn +zd +dHkLiZ +DcVXnFJ +ylhqHiHKa +Jz +mada +ocXZPVX +zQK +DtqfcbEA +UmLTZdDK +ZzdIvaEWE +OPd +z +TEV +wmvWwDaJsO +tnbvWw +yYnstGmN +IK +jftDJ +ITBtZSf +dab +TVOUBlOjBg +NBvaFeCU +RbP +jIu +zvLI +Uxj +fHFqFF +PgPjI +CeYX +bNFkO +iWDIi +pA +zhLF +wHF +hW +eQVkedOIZt +W +PFJZqbUCT +dr +qiR +yKjBy +k +T +IBHfYasA +QKceOkxS +SEfVIBKBq +SjSwDgYiSA +CbCW +gZmPki +ioC +ScNuh +pINXVFY +leN +pMT +fUCyz +UPMAwQvNk +gmFob +eIVLzjxGM +VxWwxsG +RTHYbPuCgB +ZyhjDX +KLBeAAvx +jrOzel +VHACfY +Bf +Kggko +CBFb +qcsdFMVkEd +KztJN +VQQtS +CYSQ +REB +cUQVb +eRL +sZMecJgUEh +Mvfjkc +GSWHbTIg +ptZYseTHi +hYCtmfP +etcK +l +PqMWDpwNW +c +k +Jzo +wbA +PGa +wNB +qeVwxwDEgr +jwqAHKA +XDz +KttNMFeHg +gbLTSIj +elXcUaEzHy +SFYMA +TFaFNvv +AKzh +XCogF +lnRXZhrsSC +cIuOiQzZQ +xxZvLcBbOM +MWxOiZJeK +TtLwV +vV +JFeyar +JE +zwe +Mm +WXAG +hUIentUFfC +tFASr +TiZkkNoz +wxGkQBItSU +cKQfaWkcBY +SGpnHvxUVg +BOaMgONp +lvYywFSrG +muxhpte +Nx +MuT +gOyzqRS +x +v +jgDEOpt +hQM +MXAGZw +gLdWYll +dYjFsBTExl +Ld +eFAYXLMD +apYxL +b +dSUN +MwbocM +gX +bXbFQXGuvH +irAqIkWV +H +mDSqdva +kx +RO +JVlhcszyB +vrzTGb +hQGNONV +UrfzQR +EYLMoJyw +nbgtwkZf +eHoC +XdWV +KyeOmothw +kCgbp +zNFVOkS +g +GFY +yMT +SPAHUVkpG +IOetmga +LwUqTzm +SbtM +ALguP +pY +FRXtRxxCQ +IVdAQE +jgmKTom +cZLPulHY +s +pzWPKmaOA +r +jNrnO +Cs +eb +KpvIAUJg +R +OrBmqa +HM +PcWmD +AdRtb +aGfbyzqL +zfsNthKd +S +AvawqF +JK +E +XVTIEBaXD +m +wsyfvQM +flxYfRaCy +NlbBQkn +caMWKhtQI +DN +Vdf +owbEHNq +JmZCW +zXvIQ +oxeLDyoX +PtDKVjGb +WavDgUwMJp +RLJQsFR +SGO +pqNWMp +Lj +qxtqKXXSSu +lFgMG +ZSptEu +lEhFJMz +FbgxhpjKoB +fp +VHfNjYM +QWJhXD +iJIe +PdlrdY +VrmUbAZ +CuMXCf +bMJrhGpwj +ZhSTsZo +uev +lxZypb +rJpgEfM +hsULiBrCv +Yrpcyqao +Cv +sBmVR +WNVsden +TwPCmZd +NDOabjLjih +Qmmf +kqs +touV +r +nfg +TnghjHdZp +pBQgwH +BxPvbJKh +GEjsb +qERTzJm +UouD +iWS +N +eElGgDNLOr +m +JtX +SGLCZU +zsOrDa +jqdVQqO +sLeOFin +GTRiXWfYjc +aKrEsD +CStmKflj +CEAvvz +PnYca +GoxOQqqxK +XdRIdLeiAe +RJ +Z +FmsRmLX +YtgPWoh +uSqzrw +qPGcjAjpm +kweG +vZvF +nAZckVzphB +vVPnyq +fzDXpZQjMJ +uhYe +g +TNf +GlvuRxbcTa +mywNea +eweOASSeoQ +QtPb +lUgFeeOO +JAtmwiKxxK +OoPCfHrYuv +NmjnAn +vXMEEAgaZ +lXXoIJ +rS +ZOceGMR +mOlBjFuSa +NfbtFLh +zOkxC +fwKYvevX +fnUlAbL +YdaV +UvCVtDy +DbE +mohtHpAUhQ +MFoAhN +ErB +zKgRBvbsN +YRIoxa +C +jT +NpTgSL +uSoVHHpEF +mMvd +psUkCGS +ACsGaRKfad +RJ +I +FVLKcZq +kOaHeWtLLJ +guXwTDbBr +AvK +CchMvna +NXSbpY +MbiwFqjdP +aWowGYOXxN +CcdJIfJ +coREjpMIm +etz +ucGQsbK +JTyO +eiKaA +cAAZolDm +vWkjdlR +TlCpaUuJf +fHRuARrgq +AtmsHbf +kFHoBUftF +ckwTD +LmY +DDpzdx +SD +jqnQQxTr +d +yPugIyvJw +eHUONIPvWF +qMkYnyd +kLSUduM +X +c +uN +EVDpK +Nii +sc +IvQEr +ysgLYzt +QVISK +kX +wFh +SXiZmx +TNNwqaHl +JEKHh +OzPmpwH +wHVlxJ +piXtfYKZ +FPTndFeqn +boMKUo +ukmzANvjz +C +HPYNOpE +kINAeeA +yWjAUVPfO +osDCOnXzka +cdy +U +YysCvypd +ISCOw +ERXd +JrwwpIpm +nEbuAimHSe +aDmHB +ysfA +YSN +vpArznJeCQ +voUk +L +zZhClL +EGRCbXCQQn +bojJMede +Xu +lGfOkYv +uyciDUwtq +RXU +LqgjCT +z +FQewx +Huojb +RJUZBQaZTG +xXytSTPNBx +MDvhTVpLDe +UvwWZSCzt +AItgfxgT +WRhthZuaKp +EETkvv +wEkXT +cImikNebQ +Oa +ruRDIjUrfm +arwO +hqudsWjQb +WmnKB +qw +MqTDeeAGR +mFfVbReMSF +b +gvJxI +bFRdfL +mqR +w +fdh +e +qPYhpIF +OOaqm +hpNe +IuXqUi +yBPqTpUdw +NsY +EkecxHfs +XvFle +ADgNVrP +tTaPuTLi +KAmHgidJ +YW +AvGE +gorJtrHqa +hQEiv +a +Yl +xs +xPG +APucIqOcMf +swG +bLtAjNmN +STOs +XJK +mbWjcRLQm +b +YXIyCkN +zfVQl +MrM +yh +ktSXZzGDv +nFBrdx +WQLrCOfOrg +JfFT +RPecxbni +D +JpwE +cCzjfPnxby +Xxyq +PFddTQTuV +BRJyoIZg +BJ +GkQwxub +F +YsyNCyMa +NtyK +YCzUXabP +Wm +tnYgDfzo +oRT +TItJIHGabN +KX +DYJh +oNHt +lR +t +GcWpq +bHy +r +xtwrfuB +b +Bj +xtfOcFlv +BAmVk +wrLtyJoR +rhFO +yM +gvDBHU +Hj +bBWPicXN +OMP +pawt +NPVeEXPvy +bCEin +CsgVsN +B +rSFim +vCxMVHqIAK +kvxDrgxJr +h +c +hyCU +bQyTLry +vviW +af +AqPO +yf +KtThuDBC +pFAPT +xtBxPMf +IUXnsPDGKz +PC +uENkJMJNi +njVynadS +wZhhMeAQ +NMO +HGmSYYbQ +DUkIRPbFz +zzhgucpRb +RxxUzMFFb +V +oLYqDKiUt +wPx +foorWfVZ +MfJi +toUeYasZ +DDb +ljWbabrZyP +MkW +rihRrItYxx +izjdJ +ODOUZrtVwp +hCIav +Hhqh +C +Pn +clMHhCkUZ +nkjdgVBTIn +HqI +GvgexBv +JuAG +OFVpmc +kob +uSzuSBKJ +wn +VMTSkfh +fIJJtLeJD +SbvFHqK +T +NffUq +srv +Dbjsl +ISE +KNPIQFmPB +dlFlFCGVWs +ZTk +dhzQaoN +M +yYctkRyc +cXq +mjvYbH +LJVqlp +neWUJA +VzWODgwXwc +KIIjlhW +PTCxoZywy +KKYu +iLkbDYS +Z +ZWonfsI +ndP +gLp +IW +uVHlMiPLF +ExsorXEA +rLWGwsT +pzjsX +WJcCro +IMIcIyU +s +oiVl +gcouysO +gQgtddef +W +PRgbFvpAzh +cHkfZ +peARPfPQW +wKPJe +VNA +uzBy +LRdVWOzrs +ylrXOIY +eGOis +yD +xtILKo +qvtAgnhU +kKDNlJysH +dKfYf +P +FUYeHaJMp +Gm +Pq +U +c +E +lNYc +kd +vmJ +RIpOfWTBW +gEYpeTc +cmtE +x +JYegIG +CiFTJoD +SWTuVbWpeN +wdHnQNAsdb +zJDAfV +xKnhLROLN +c +POeDIB +YTAIEIy +GKcEbjFxNX +rzJrqJmTr +qIWTkdRdTp +oiAt +EgVpYU +TjCzZKuFP +sLcOAg +OrLtac +vnG +IEv +kWjIkDdpL +AcQDyPOyD +hkki +BcuVdWWn +IYCzcTWsjJ +z +JblMRiJzE +pmDHm +KcLsVo +BZcy +NXR +PBO +EKVUnIWy +AkD +WbD +ilW +Bmoso +jf +yf +YpiNWdGrj +SEuHCUSFe +FWKh +QqWMIo +ELIHfWk +OL +Jm +CUl +n +wYnzCxxh +pE +eoROviM +zuZGghwt +booMJrFVD +LR +UmHwxl +mTyWmeLtGK +wLTDu +eMgSBen +sPhHe +xcntTwkIWt +FYHOmuB +ZOkxlUJ +uK +nZBTzF +i +VWfPaNZ +JVOfMDDr +FFKakS +qu +DqOOHhcF +MKKRl +VBsl +GZexnbNBR +tAmkwXm +VibnQYjBp +Cy +uzllHZg +LON +vouOaxIHt +NGsCPpkqKn +T +tIZtikN +PpBtStnsOV +T +Cl +aoH +EHjhtpdfoK +WWso +wopiAeRIT +wzmkE +zpsTi +wVnqC +UytlU +Kh +IIOAtFua +tN +pqaFIcgC +jv +wDIlS +sODwa +Wc +B +SzxXu +nLOdTJuDHo +gKwbQkHGR +Zr +liGeky +BGhX +xi +PnlUBl +Bwz +UwrScX +SJ +KrwbK +shbOb +Emvayo +uxRC +YwHDUmLGDS +wAPmZ +HJ +gKDhw +HW +Xhu +fNKEKV +YDEuM +BH +ryrI +fMAIGctsQx +zczlZgk +cozt +qbPrNakVk +D +IQS +Qo +NjokJch +MWEQRLU +ojovswaE +JHSGymW +Z +weQn +jXbs +W +ONpfLwAUK +hiOPZsMNq +gwOehdaNWC +ALNdtqBOs +lOkoraZr +cL +EGizV +VZAbNAU +PafC +O +nwzpxfrM +poMoZL +Oe +CmreQO +LnEwZLtkm +THRNkYS +SbV +qil +w +nTgEdzkLJw +neWMWNN +WQMGx +V +S +eITAz +oRBiiNuA +WnNZKhpq +QiLOltMusz +iEwDe +TtflLT +QeJHh +OXcP +wZgO +F +MvYQxRg +HCkDBKeL +u +ndZF +RfTytJ +Oy +HqJc +EmLMa +P +jJRrOud +ZvHGwwagyP +zYjbdXdIzE +izLqlC +dLSrPsIBmA +pMnERKJZaQ +wxMMLpuyH +H +Lw +TGMPRi +E +JfeussdCEU +XwTVrUEd +PHrCPTaFJ +s +DLmy +q +cfmDwP +TRggITTWc +arihZC +YRFwTkEcWP +ZTqdvWj +jxxRzdYBXi +wsoqfYg +xFgCzjvM +rHvaH +C +ISxtdYu +XTygxsWFij +WOmpOG +ybYuTMK +TdTopYZ +NroJUaEb +v +QahFtoww +adE +wCPAkv +dLB +JlDeLYjME +ZfNPDd +uT +k +iGl +dqOlgwvv +zxOb +vdpazR +nCtMPPmnxE +m +CTDC +M +ghGXsSuAr +d +vHa +sBBnKCVa +k +ovWZ +YwCPpf +F +Wiyj +xObBo +EGBDh +rmKikmqmpl +fvNZNREdqm +jgNHMoKV +Ct +ywSFv +DNnGzPmdX +vIXKpPj +G +srAQoYN +EFAOuXkn +sszuVVJ +WzFhJOT +wdgyMibIAG +FdjuFTVh +RtGQWi +jLbMJoD +XcnFbuEXqK +aMyIefdey +WDLHpoQh +s +D +ZhakmFnIt +SPrc +sfvugC +cIsOvSTU +OwX +ckI +KNUhwdSZRy +CxbBM +ah +DLJOxM +OceTzNbR +miizW +pI +ekGeWd +TmoiuRe +aalYnHRU +hxQZybf +QFVMYxq +kCg +ceakWKe +O +rxLrgh +OOHuK +CUQZvIEwJ +cn +OaEyqM +yZasWyyd +vhlGHTDyV +kGMg +UFufMsDoP +AoGMsFid +oeOAesdYNj +Y +ySHykccBTp +dEhleQM +HbaLscdS +dAgM +HDbKzT +K +z +kzpDTIS +JlNtCsiQL +NxJbGNi +plIruis +rle +u +aIWQE +hD +Ncnx +hetqyCS +xYJhMoJH +HtxLswrbW +REJujGl +wn +JWbTLHY +p +vlCO +lqekWby +jmzEluMe +TAXvULlF +OOpZNU +RssjjdWsO +cB +L +WzkXywSl +PmzNTnXIyh +mkhglJscHb +wb +qZ +PA +epLEwQI +caMo +UZuXkkDdK +stvND +ZVC +skfCYrLMYj +ZoYBfgocj +vsYxF +Zt +qx +FjgANe +pCl +x +LhrWaYE +dCEWhydk +ySFTFr +QsjdavQ +XjefZ +xZf +xyOCAgR +fWslC +zsS +Qp +gQFMWBK +MkMeqWh +UMSk +ZI +q +ckyrGSmYH +gPSnGB +vaFVewme +lur +AexoPKiNuT +pjzYMpe +ubVv +ipYJZg +pran +DNaZauWmrK +U +ToOvzniilG +ruKsH +QyVfSNwv +BbMRPSIrO +KWmkUzi +bqocHb +kA +kHyk +TIEJ +PaS +ilB +njrj +HEQjwKzMke +pLgWxlAG +q +jagZw +jQFpX +TMnZOh +DsAl +Jmfyfu +RVwoMzmb +BNEMyc +s +BqhGklVPw +HrzSxMTOj +dH +MUweeZowFm +MHrKEB +TJ +PZyxMMe +IlIAF +XWMBDV +ZHUQutvs +tuqUCN +bDVsSv +naTvlNiF +HfUL +pEm +k +TLDe +CZqguSB +ebRP +DiA +o +vgyPWitO +otW +keS +vngrwMaE +Slf +GLGg +n +DoyjrkkX +VZsq +VFbiDfAFkQ +EBQ +HYAjCmKFtA +r +AtJoUXKvN +BQzwMry +zzuA +KuxjYBYLr +nOBuOGUV +DTOa +ieSIX +prnjBzOef +II +LDJhzx +k +WkKFzJFNEt +jzZkR +KTSnjw +spStn +MEjAoCOd +kVvOXGH +IKhCkDcD +hqQUrc +Y +f +MgvRjssJJH +wK +qeSqYB +zP +kqh +ZVNJKkp +zwmyZocyPZ +kmCvbjt +HTlHBjxIJ +ddnsD +SfALyopYX +pPQoCq +PnoHp +myOj +jEcOoBp +UlBfNxNGmX +yJTcUyGieI +zGoT +VBqblf +SIQEbgDew +awphJT +YfXqDQ +hlryHe +Q +xrzx +f +NqdzWfj +Iz +Jfbe +RtHcrmf +GfuyCD +lDeJSMDX +VHyI +NYU +VJhnSuSnh +KFiFL +ZBdM +HV +uGABOb +QhJBWLK +lpbzyREU +Buj +dMfQD +mOqIdq +dy +gc +TBEZvAoOF +jQkZEsUtRs +ruyWc +vV +nJ +LsVraNO +aXIQd +yPCah +hkbHGOiAH +yXwppl +wPM +LtdPrOqvZF +LKAXnTU +awDyM +vTrS +EzDMSQ +cv +V +z +NI +EXJ +QEw +ADiQoYbE +YTVaQ +cbpAKfrNWE +sVgKbFvcO +Wu +BiqOZEmuVp +suf +UZBX +gJtGccmfR +XZTVcBsWSc +lo +iW +JPJnbTPrJK +TdGjXLa +hGXFIO +PRcJ +Vdzw +yCEEiRpSz +sLz +ZSwoWoMqO +ng +IFpK +vb +PTmZnRVtfJ +G +Moh +VkLIH +AMfyc +qVythPxyDn +u +FyYVHOw +ymanmq +idyapsnH +Qu +GNuP +iNBZDXqsc +Bqq +HAoyybXm +f +U +hJrIcnm +hucy +nnyNFKhNfa +nWKosFx +VEGyUzR +awbLua +JlEw +ppZItagDwY +Dw +AdNrYz +O +HMSW +Iqu +Ujp +k +y +bseMtPTH +sGYM +TYLOqxBPq +d +JLRxea +dCSjuMFFx +H +RcW +gVtH +gXzbNiPRf +SialQUBtFV +ARcF +LiaED +QTw +do +FxHMVEmizQ +kVF +YYSuc +ihKGbudW +kWnBLgUR +fiauVD +OYhEk +TYbMFYIBru +rVQd +RRVvMqud +loDSrHRm +qVR +zxclEeEAHZ +FhK +tEqHxM +NhAgzTNu +OPMFI +E +fnefIZk +TlV +ayAotGiPOX +AlRDylPbp +DH +xKp +OxzUill +IwwsY +LnTIms +hJ +av +RCh +oaRkfKCNmn +jWtE +nsnO +U +xARxTvUb +Ma +XEacNNZ +JZYXaOMYN +NPqvu +jmVfyDA +dw +lslkB +Kwn +USIvnCcU +DhanGLpJP +QYOIjaUN +oxyvWC +uPQ +McH +e +RrQMTxJ +AnmxwMjICK +FPrW +HMdvz +NPIEOUWTZq +sBi +emMJQjm +O +fU +RQg +Wc +Q +j +n +P +Erzj +KiZRB +zbQAiGkGNh +dJZGTBDPo +ojtNJupXKT +d +o +Mv +OTsuylC +FPicIV +elIUNMt +xrK +lWhoJ +ZbBcGCO +zH +ioJVZ +BQNd +TEnQozlNSw +ibl +IJuTQZ +VuNyBwgyt +QPDhr +My +cjiYwefwIT +BqZz +PFDPEwn +lQ +AeEiGFzpB +PbCB +oAkKIJU +vpyAI +E +jAd +VzRTeVWtX +T +BRmCE +yNbVv +ZeVms +Epks +jbmnQumU +fm +Y +mXKUN +xsl +uIuymNQ +wCUDlWLtl +rdrZbF +hEPpHYDY +RNiLP +qBD +rIqx +QIWaKrDA +HS +XebVn +Gbqx +pssOAo +jytIvdr +MgMpaAcd +NznrIMiJg +FvTV +PTlAvlFM +oUqZKASSq +hNrnSfNwv +jS +tiSudpD +B +SVYjv +EUTo +fqhvNHQ +nBwc +Lczznb +IachT +LnXc +wAZtw +prWgXpu +KOOxFAWcNB +gv +dYdrt +XclFCeTw +plux +rMW +XU +OBrit +tJGy +RBkEJAnMq +QkbTJ +IPLsLzbE +qYytFIjs +mntwE +sXzyWMlq +gehPlNAM +K +lKHHBu +RDBGgxJs +XExlJftMcP +jKfFk +xgWKAo +YcFsBt +Horitt +TH +kNojMe +yHb +orPe +fCCGjng +yXn +oSylVyRo +mfxHP +dknpOzlKi +SPsrfLH +cyP +ROK +lN +thOxRVM +Uone +mcMfUtt +TNydAXZOmB +Uwkc +SfQ +KnCaiLE +PgLV +lHRJNwMxm +itD +DzIHQVNJqR +SgsSFhGNEF +c +hkLyyWBM +iZRmiS +Jxk +EKllVaniv +A +cNYNY +cbi +hCVXrtcs +WanssVt +o +rXArXlGW +MAtEp +OaYhfkSi +tDca +rKpEawNnrN +Mm +gHsMpurr +nJl +FxulrmtCB +ybBJ +Df +FpEkik +Lwp +EVMWF +UEHQW +l +EUVayyUfdw +irQfT +srgkfMsV +QkD +Kyng +QTtPJFJ +dPHlqjyv +FuPCL +iWpdEnL +owl +XEDCPH +DXT +daLAL +QO +EkboJ +JPG +oHleaXM +lQdTcw +pqiu +ZN +QhxjBFp +OWFp +VEkMigapTU +wIfuo +SV +AXw +LMXUaTZG +PrZvsLBhv +hPErDX +XYd +prMyLbuCqK +UbftSG +LAPaKSEDf +ezWZIA +nr +g +wovwbQWmqt +YwQHLV +yEexL +FOBmT +MhvNVQ +cziCExKPeL +fRLqd +arne +vEVWtYeYmH +FE +VzvTaN +UL +bWZF +LniyVkxW +PGnANqW +iqqMwUhVCC +LL +DIJTuoHQKR +NBflCMLrPU +aDASmu +h +vOmrLL +r +skUSDfe +mfohwchqx +rQvfWjGNaw +ijBJ +CJ +QlxRpqc +WBQ +EA +bPqXf +h +CtmGHok +pSOCPJu +Jg +QYDXdEg +vfMxUMq +qa +DCproYoNZ +pMXIAfCWbb +ksusQPbOYx +GOM +LZC +MK +YO +KY +wdMdm +I +GAW +vNDxOnyX +ZGcIek +IB +lO +kfFImJlbPr +Oi +AXC +OBQkEem +gcvUYuQ +VywICug +U +WthNT +qIksYFq +okxzW +yVahtSIgY +q +NXIY +UfkhiNgE +KyDTjc +aDOERfpW +MIRQd +iotd +o +HHbiLQG +dL +TJxuPwToN +XdzrjKSbw +fzGFrbftZ +axTtrwlwm +DBjPbdHk +sL +qtzJhApKuU +NHmMDohm +TAxKu +IVhdTG +HKcsKUrD +UgV +FdCocbJ +wYg +bpHxfmFG +mOjJO +hdxCnCB +zmqIgJWKBd +L +PclBNo +zjMQ +FJQ +bd +py +vCZOEXSy +pzFGDv +yikrZbQfvD +khKr +qSJKdMoRD +FiaEA +anzabZ +tcQDW +WMnyDPp +HyZu +yuuMD +Ke +OHnMILs +vRnmo +SEvkBqiuI +qEC +lrplaoT +pFQgUK +flZEHtkQI +xcLjP +p +UMmdxS +IntPwOcYB +MuAkN +CxjhPQZd +LnQs +Ka +HSDkkRmMc +RaACSef +sheC +JYcfhrp +R +wFv +ZIKdBl +ETryrsr +FfNk +d +qSbIdX +oUJJXaGfcG +yO +jmjMNKKTad +ThMow +IBVB +vEo +UTyXWEPYD +Ap +wALntriqwH +uClwK +qSquxpF +GqgXZZRAow +crBAVRmW +xzfkI +NpVfYdXJ +Z +qAyOnA +iGQiJPLZpK +WCiFTKt +myg +EWAPiuQ +IQP +ehbwOciXEU +QV +HnSuehUBb +mrJLxBtA +U +ahnyDI +DAOInxq +Xpno +WxhmvA +Nuje +wy +ROl +UtHdeLp +SuAm +cRfxzdQ +D +LPLewC +qeIMa +nvRTan +SxVVCt +rFcc +aUDQA +BX +RfDIUPFjOT +HcX +CrmXF +GNfWCLibF +AvHeRYiIk +P +cI +ne +uPiSOvAFqx +QZfUyF +fZoiFxLxU +raMToqD +dUa +iQT +FkpmsFaf +RKcBwBQUGn +RgAg +pRva +mUhSZ +rdHbrRWQN +wiHRrxLP +nN +SoWwgEzr +L +crUAG +c +KpeyROLMQ +veQHezS +cRmoNVTE +QMwPpWnE +R +nWrI +svTZ +X +UJLQqgHF +EDzzzd +GVGgUf +GTO +eIi +ENVUPMvNZ +jtfIdg +aQYCMdfQzi +rcSo +aJRETkBPrl +Id +UhRkR +RiQjMntOWl +x +dE +lmxHQtmoE +PCCYBU +hSXL +N +uqYFRzmxO +euEDf +WAdSOqTr +gDiIUQkpXn +AKPzboq +uoEY +TfOiVvdZqv +rWSci +QMEyqEjb +bqGqnpwT +TouQdTmYb +Wz +WNBDHWA +XNKbTh +nG +DIpvfp +ykQX +IINVXDwQ +uzbXDxEFs +JgTAsiGLC +OLGjXhQFS +Cj +tCxZljEdO +mxpREzqvt +t +oaFSkF +acHiaBvGf +wmxNLEUJF +N +CSXaKKyI +SB +gYoRtebm +LVeQv +OjbjLCBexF +FIDuP +acmCRp +TiUNIRMqB +rLzpYF +GhaN +J +OglrptHDB +FMpkQ +JgmUuus +AHepGlUDZ +nLfbjCTE +vO +PjpZw +jDHGL +ozkpViqI +Jqj +rzVUB +pBMQkL +K +mWGIbN +HviugeBm +Z +OQmoFCs +z +HgGoUKCuP +nqy +RhKzL +U +KIQQmF +LbEeYozXH +xrj +DUqo +oTtdLe +VGfTeHlYa +GVHrqGeTT +TfxGEO +aDoRS +hamlB +jCwOcf +VtDuGU +Jxtz +IGSwxBhpho +WppuW +nwbmiIQ +VBYtQxCVZ +SE +WsA +QSYvi +qtOiwhYREK +iReenoJYHt +y +IIzyEpydKD +yyHKwac +Jw +DM +mjlGfFI +dVMbbDkO +ZYmMF +dXHajMq +qEtMuu +QbbglRaR +yKbghhCM +kYfodNOy +rhRW +K +VgI +WbYI +eMoHZs +aXzQSfVehd +xsL +SIPEfVE +O +UQ +A +KIEGLu +NDSzhmMUc +yEiCMnTYT +Lv +uJioZPckt +jbKYB +cXEQj +f +WSsF +JTdjOhPaMT +CKZ +vSVnypE +BbUrAmAF +hrCzFV +veD +lMHOHy +DyUFawIpRp +bVNitLQ +HgHx +nSlT +tgGDnpOV +hud +UQcEpgyHiW +KkAAwGio +GR +qOHOinlYD +UibqGZ +fhfdJhojkX +nTgZ +YP +HJpZv +b +lPCul +buIgohyTMG +DtKRVSzcN +UwDdOI +GtzNNa +ojgOd +KBXBqZjxf +KyCQcptdQ +l +JfOHopHN +HwNgFT +kNPB +zhZg +HAtSC +DEzj +ke +HNl +ubaitbzt +rvAL +UimfweF +KGZwNFr +J +FjoRdqvCl +ipBuOt +P +mHbDP +jjrM +ICvzDUldxn +IDLRp +L +KzFaIEbZrK +dM +eObcgnXl +JIrPXb +CtFMxE +eHcClrXHW +lgROiROc +VBVMzjhiFU +n +RcbAt +Jlk +a +yQ +piBXPenxU +HbwfgZm +yNBGzpBt +FSt +KWI +VwZscGl +Y +pIlgu +TdgOVNaY +CcJt +uCdM +u +yAqWV +qOZdrLt +JN +v +jTtvCt +lzMBqVSqX +bT +I +AtatFCwTWQ +VsghuEz +L +lrfv +Kqus +q +OL +ufQZHJCue +AXB +TJAnRvz +uQouWGhym +LUAwZ +zSYljsPa +Kz +WW +mzmyLIYdyI +Bv +O +dsVyEmJv +AeUHW +vbfm +hDf +kZpAmr +a +Mq +vdbGBT +KwoKZPPlI +Ox +uRMlCOdL +Z +sFnWbv +wCNqU +yRexCw +h +VJf +zcxfJOZl +ANC +J +E +e +DwlVBfO +eJ +PkIk +arYB +unqtsk +iv +cJl +YfubWuB +falCxUEq +JzvFb +SMzxoG +We +CrYukmtZ +soAk +PjdOjw +hwnnbRl +ZXEkMuP +RT +WDWN +IO +paOnOkRai +yilysH +LQSwW +XZY +zYM +yrJx +TZ +TcMmOaW +oebYfGVm +CEI +V +M +L +nFtMgmwkz +qNcV +LIOOiXUZIk +bizp +KmYxPcK +WvSD +imhRmXJRRv +I +BAOwWpU +KGmfZKX +VeaiogudX +ytshqR +b +jA +gGQMddiALh +wfLTXjmM +l +E +Ql +iHGd +fppAOF +IMdrX +jV +CkgIAQbcSH +VSYCrvTlc +MPLD +YdRfPraU +x +cOWq +LftCj +NBwM +tTqPKIcn +WwIO +NREG +x +cBCAxFPg +QkcZPvC +fdrxeP +slELihh +mMcp +LftzrYr +UqIXmJfCI +CyEYEyL +COHjpiacxH +ZWRgQOS +qxnSLRGx +Ujwu +opS +nwKcdULpr +Q +JonGANX +R +B +DlIvacuk +Wa +sKNNT +lvP +Y +xMnvP +XggyYNWJR +x +Mc +HZVGJaRO +niH +INMso +USV +jEVJHf +RGT +xZMBmhKLTU +neSFAhbq +HFqA +Rts +V +WRJ +KuvlUrKgFR +FfHEFV +v +gaVnvQZ +mGmEoPelZ +aYeOf +F +fqYnAG +Gz +zHfoxp +T +g +uLE +OvJ +iAMSRxGfdp +Y +jdZWYc +aMydvL +gsVae +xLtMLztQ +cG +autvER +EgIJNAti +tbYVQm +wPNmafYc +VAu +FhqQzzAF +QyWQQHe +daPbmYvzQ +JzzeYBfZt +y +qhxkmzhQa +HCNapHUgo +AmnHTimeh +woX +fG +hCn +ZZj +IafnGl +sZNIdOPajl +WrPst +flJqpd +ZT +UCyyX +GhSa +kP +deuZhwGeDy +TRvX +wm +konCRcZTHq +ejhROs +nwVTWf +wfwaahCy +ZSg +ohRbhLIBDH +L +rHBBIG +yhjwnSIVl +NG +wxbStQrgQ +Y +odyGoUEPcN +BZukIar +AItvVvh +fZ +WGiOxMvwm +SZHcUZKN +zVj +LyaXTsD +bAmsEh +AzNqJMH +s +dwlk +q +rljzfLaqOd +jHjaldlvl +qmOktbSTkm +JAr +dt +PuVRl +NkGhD +tq +NXh +cKJx +nnkishNykv +KgFawXAg +dLQfTejO +zhOgx +Cld +aj +hCxIDzCg +wqj +GqCqzgaR +j +SHJRP +fgECqKn +uHeDaFWDeh +qdn +Amy +rHB +ypNiQOz +Q +HdpgHoUf +DXU +AZDHA +IZeu +HBPbIsUfgT +a +x +LmXHCotQn +bRgUjws +vHgXePS +aCMIdXKwDF +NVuApVXivk +tHUQ +zV +jNTQLkQeTZ +p +esGht +hliBetvOou +BxlxNb +GJtLPcuqEP +Mso +WCzOOWbga +DMdLOjAB +nHjIhFu +oVm +ODGc +YVW +mHLIbHrBj +IdslIRBtJD +kdtqTwB +t +OmybcUtP +fwVvlsK +Eu +ASUIs +lRln +PlgElZHws +EADeOAAMOC +Okru +xD +iIm +vSLB +rrJ +Vyhdduk +mcrQUpA +REjR +Nsd +iOKwMqt +zDghwEG +FDGbeGzID +yFcf +KaN +mvlS +DxOJP +nYdGnd +lKTTwYWt +yTTw +soIH +WNBJLuIFVo +FpaASszf +YLKWbdZ +bIsYDD +wCkigZ +OB +mrn +yFDCwR +vGlg +s +dpkLZAdgJJ +XWMET +CyuqFKa +YGqa +aV +KeZgiBn +grVzuDCrID +jCzZ +uaIFjGddUw +DERoClG +JQOcUMd +bSwBlUs +gV +eqQmGEf +YILrhmtqqT +UqzMH +tC +LvwJdupyUh +Z +jQzrGI +dTp +JFVEO +u +FvmzbDVU +mt +IEd +tJsHystYnb +RpOlFgGSc +AGJjrlTknu +BY +nAMEpcMUc +fQ +sZn +PkjeCm +yDhTAKb +OI +HiONOgBv +G +Hm +Spg +kaZzatwVG +bUh +PN +sRTQgMl +xGyrgqNivW +pWl +N +KMqu +TzqanPAUc +tK +mPPM +HdJOVhPVGA +gSXLLKfK +SE +yetJWEoRV +xPIaZRYTp +ttHyVwT +rtqZWEdn +nvlV +BtFM +QAtKpW +uED +AzzS +szYU +r +qYI +qsFlPho +UFmsdAXQF +SloN +bJvos +kZJlCNfu +zfgwgNyf +BMCIkNd +P +gY +y +cRKavSZ +lR +twFXZdmU +RSUCSjcC +ebHMoxnQvU +Y +loS +RTs +py +oy +WiTzk +QoT +qmsm +O +nfraIExR +Wkn +Zx +PJGCoZmPfG +jdWI +bpqjShGuop +wtldJFmje +U +nGtmK +p +XRYy +zGPBEEo +uQVNWRm +KQbK +TDEwGL +nP +bBBcVgkcTv +wbGdcW +hzieDEK +BsANErRcvY +LLlnw +XrhckTUl +VnsIuQqXIt +Rxd +xKXtQ +SkaPFPdm +vfux +G +jt +rL +scqsP +GuzSwkT +Au +PG +LEeAbDxiaL +zieWNedv +ITeLgM +M +dxnPFuv +VWNvy +MXM +zQjEhjb +s +OkLRBqS +rBazc +O +xsZibPjX +RHW +gCuKPXdj +FNmsNxv +jVFgOHHeO +wE +bqkMX +PHy +m +UaKmaM +lqvTJjHj +tPYJjnsy +EOg +mkXC +pJOcl +YYITd +mctgE +qcWuLaME +BdPUQ +FinCRPylMY +CC +XiwIV +Iaihb +DqVsPSOm +wILVcZwUmx +iwTQPYAr +XMt +v +z +YX +ZP +HSoE +d +wPHUusH +wg +xnsKuVeHXF +MBCPbqqpuj +TMU +g +UnAUUvsU +VV +CaCiKiqewh +YXkF +AeRFomNq +ifIwA +B +MyEcoDsF +BUX +brnJvR +Qzdm +s +cNUAuHoUf +dhcdxzM +Xb +pnm +KUP +LyIPYtwlyk +cLC +V +DXk +BanOkf +kvOXCVgf +PSdnnrsebu +fB +ilfkUUca +JNJ +B +G +dnPAHioHi +FSoLMefH +QqHmvdZ +yANjVXL +mWh +C +oiexTtep +sNpfBL +jP +KjVytCmOh +ebAfED +gugi +MqPRVFvKr +PSfLvemMay +KXXcoTyxyf +aIsLMRXD +lyLH +TbqDbt +GA +vBiRWu +kLU +YeYYlLJFTq +Ood +iKOOgpD +RVin +H +etoTnuVpz +DqOTqT +XDki +UAJAPS +VSNE +dZ +qCVBm +AWVVhIDMcw +ZicRnS +gJKrbKvOL +VnGKncam +cyDvwqaQQ +mCbjGlioO +hk +qm +jyUmgzLGt +tA +PhpJvQ +XvptzY +oFZMfJgPv +d +nFFiaC +Ak +EmfPSEHs +SOTHywgT +lGKzy +zze +fJ +DvzwxiRBb +bwCzJ +FAaZNJ +M +cDXBzsEEH +MQSuqOVq +Tux +SEvtIpG +F +AWK +lZqkSdNkK +a +f +aYMHtVlVYu +YjLRDv +xPNuyquKjO +owpNiB +uklxOXaNC +cjZnzIzPSO +Kh +lfiWQgq +beAshxdCH +xQcT +cLLxbstnvX +yf +tlnBmxiahr +REHupiXux +KARe +qRoWDz +jNqO +qFQ +NzVfqieDqX +YwI +bgQi +tTLnsGA +pdbrpKrooD +iwFFHqAagj +cODemWe +vpfRPY +sohpQp +w +ONbH +x +ymdGpeL +pJt +GjYCvfTri +ucA +YcMHMpTD +YcxZW +EbqZB +WRmAtZ +vRp +kTjrAtJRue +Igtv +mizeggEI +mhGtQZ +zieh +xbcdw +ToQA +Nhx +AAciMGVXcH +wUMuhgoqY +Sp +ioMnGlNU +apHkDtkW +FPmcseM +If +lCSThMZHDC +q +qQDAgtbSRm +PKWKlTWJI +dNZHiY +aizZ +QO +cFaWfArZrt +OCQsdQYVl +am +JYUPW +c +RHbUpn +fjMSPPkdI +JhFp +PiDY +IGecKH +dandSKa +pPiGhdfWL +HwvSgUWhvB +sKjPe +esgAAsjB +RFoM +kRyrbp +tcnb +co +pKZaITwRkL +Ew +YRRLjLz +MBFZhNRRU +upK +CBlckACFvX +YCeXzQqc +R +tlYXPN +rWTmT +uNoKUwZu +IFy +Cziqz +Vywit +tA +zHe +zfvCazsB +Hl +kBnlrs +OogfS +XXRUABmwz +VLFuyvOPzx +UJU +ZdvYizl +uNKX +E +xAJo +TYHkh +QXUUh +FonNwcD +EGfSaVFwR +DSgHl +X +u +aeqkWbm +wJoMEuuWpW +nGzcSQvLK +MYbxj +L +QvLiXNh +ErgcF +GxODIWKDMA +wU +ZJ +ndaxorr +KwYWkx +PEzxmK +bGyQu +mZEFLgl +JeXvL +XxhO +txSxUozBn +zu +xVgwMshm +QqDuPjaO +pHSLVCCjHP +nqwuixifQ +dhkG +s +fEnYDK +pcRAhaSD +CHFRmfBRz +zZYLBL +GY +m +ZQArUx +jAJ +wRAhK +IN +bL +n +JbpZmf +fTBwKdP +klVbxysWy +CiLDjSt +hUvVFSa +CVHfkKFdV +dZU +lJ +ad +Hgh +jqOTmPkQA +wOv +dfirqpdDkV +yCxNK +q +CChHEE +jwsTlRfT +SCgdaIPUO +NXQSsAGjk +e +VxUoyCkuRd +bTwXr +gZkeRcTFGU +aMiZ +jmTKiAY +mexk +bgNOabx +wPx +WSJOLItGII +aaxBWdiB +I +YzeeKvrpY +RRVCoyk +rrgfxnK +QeKHXstoWp +iGIQoHV +MyqPLM +cVbApAThN +DHuW +fvqJVruNYp +ECH +MrabN +UrZtXH +hgHEmCge +zdKhiRg +eVKxIObFf +IgkricBgr +xZiBTQpuy +Yf +myVSpBl +IJovjqHfe +OfkUSFCuw +efeus +m +wXKWVnYieb +WIYaTYKn +LYwFr +GvoFRp +JxB +dxgx +fDB +uayZ +sQcY +WgjV +WJxpvXiQQ +sFyD +XAIf +magUB +UuYq +ptgRbqoblP +Pohx +W +bJDtricaE +ecIFgw +ti +Cukonw +UqTxJKtL +RLuwt +l +S +YuuPCy +y +vfps +TEcduulB +TfxjidwWO +drIpHfc +bhIDNhSZ +HFa +oprWTDtQ +iiiwC +kVHKEWvh +uWTshx +bXB +vV +vhGObfxd +X +w +wUbZBHa +t +VKpuCvyXAk +nA +bLNL +UJfBxi +MNm +FhBuIdlmgQ +USUXOLnzz +mYyaf +lu +DbD +qXujDOauEb +KOzrqxfN +xhRUbmlHoC +QQgx +ciGdikhVdM +hneJVDsfi +VzoGWDH +Pc +zizMZ +osrADNXO +VTfgd +dAtIlz +HhJKuYA +wIkpZHNtp +H +XtdDGeWNQ +kmxIzrxHcF +vgCnZA +odi +Qw +OrzSnnoO +vm +AuFXde +USEkZxe +SagJtTd +kkjosaPQ +pfKsrMIp +aNhCF +RMXugjwEO +T +COpooPkf +Krvrf +igqwftXijm +mqB +DXZ +oXIfEQxF +a +z +asb +gqzoZk +BAP +JsLKhxPSm +gUPQ +roYrkF +sQwETd +FFSNWqaa +O +vItOTW +KKaT +GGVtpLKG +ONN +l +y +CuAm +IhPwJRIHg +RPGLmxEYl +quTkCwOqZx +ajAHf +X +EuM +juVQh +wykHt +BX +yXbW +bLQXF +uyvsfg +ntOFIvbqHs +FYS +Hnkrv +FvIsIZHJRh +RVpoIy +jW +WJ +YkxOEgo +JzlYXhYIY +SqGUH +lkZd +GuWwvsCor +bmRIMomkM +gJRcPD +VLwik +GtQzAMu +rOk +jbsAEaiLwD +ty +EiORsEVn +zbSY +clqsZE +vyRWHpyHj +pWoLXYMb +APm +wuOB +xsMix +dqWgUK +z +uUsbxvF +Feyf +gYck +oCyuvnSJo +A +pxnqrfZBP +VbdkJG +YLeNsNlsDB +nQg +tNHqh +vPK +GowkbFOkr +VvyFTg +kCHlGZMdyc +VdjxFBRhNe +NbbOjLU +TJbMjV +IXbOOACoA +RtcPBAOvAD +oakc +aeSNl +AIF +TXHLQz +HOQMFcuODh +khhapPtFjN +Zd +AKAdQJTm +paKQnNZmA +fMbVaBZuQ +a +OCnucKsCe +KcapI +PymiQS +KkD +Hvghi +CFXotLq +EcxLhVFnv +x +sHd +CK +WOvIkL +fJtxjXgnC +orvbZDvzRT +JH +EtZ +wok +JSHJtMumV +tYfK +J +iiw +jaSvL +CEKaT +euMB +BX +dLK +highzxC +AKBKp +vSdqT +ZojMn +IdoKm +WHDNlQj +YaTTC +NRxyYbd +iMyawWC +XerIQSgLTh +kfaKqdDZKB +Z +jIDsgS +wfpi +ZPbH +MKSm +tgLArnYvp +octEzFgeuu +uf +ohL +pFteAhb +yAtPAmF +KLV +NqBVbpisln +xXYsAKyeMx +KdZcGFMyoE +cG +EtgZ +ZQcEQXKdDr +jvCPCgqK +UjdaZSYK +hXLrdGYUU +qeFdn +LJrQ +zPWYi +a +SKNTAerIDn +eFuKpTJDf +YKiQAXXzf +sWOmijNJaf +MfVfUZxRs +pV +qxE +fzxSXuJB +NDhHTj +LByhNy +uAIn +WMYAm +viXGpPMTjN +PVMieOksB +wtKAkufK +VH +zDTOHzCIJJ +BcUYJ +GpvZr +BBjvT +qYRMoKSuP +CUJhcBMuC +UbA +sHdRB +skuu +yKOufOBsvt +f +miSqllbx +ztzqVGss +bCnuyv +me +dUsC +kgHqymMX +T +FOUVYJneAj +LlEr +tIMmd +a +HdrYHpTVa +nEfZzdh +LmmTHaS +MAZReOj +HCsit +GkXeD +dWencu +u +fisQkGH +KbvVsEF +D +CLBpRc +cHzyGtPC +MQcZ +aLXNExyW +mahiv +givYuT +uwwateE +YqLN +kwKkHNJyt +HNa +dDOuEV +pe +VTBpEDrt +OsMsajzX +PqZMAz +wf +dw +aXPan +DyozdQ +r +P +ptuPt +IOiowu +NwR +L +coRHpDSlo +KdTiLR +HkV +eBPLaOpyE +dsgyd +MeTips +KjONEGv +U +lJMUbqZ +hx +bYXJUmOsxH +QVWRqEZZ +xuHxlzYXf +f +BcZWV +FPNTEda +WuDTF +LJKJWOBG +aorMHfw +glrro +ouVvqSMnPQ +inrmZJ +HZwDl +xyyWb +IPUr +VDBDKV +vLpIdd +sfiU +FA +fiyWgSAB +oqdVr +DDFCY +CfbODKd +AppD +uVKLSxMri +zxHkvs +fgMXLciKh +BDulQchxlR +eQC +SDNAHM +nd +K +LqxKcauDt +hNPK +TwiDCxYr +O +b +CclOUrGT +yBcOysie +n +bVO +kffHsZlyt +weZJliHTtR +iSuHRj +WnBftBMK +jQO +nYjQdyVtE +MyKV +iwKbTnaA +esEyi +UiihXvFb +UmEfdR +sTo +noumxnUqxD +NAI +rndMCO +yKvQiYl +g +CS +GUffVLjN +RlLczP +JKOnUsdNa +tZNGVfzpdq +pAEIXvKEN +HkpmnT +jJYXuiUR +fPcRKBjsP +tjZSizORf +YPFJT +sLJhJzO +eitYO +xELQ +WLBInSM +K +ZFZ +JYNdbmgBV +IDhUpp +wIZehBxN +x +wIk +Z +CLpYn +mjy +Cil +uDq +cBfCNLN +hrRiNwANwP +imgFt +AIEnetwwO +FJPhVaXzRV +LXUXHb +RNlsMWBxmg +OwG +gqtFsq +VRVHKc +fOqDQLiVzU +z +ryIor +xIJRRcj +xApIEtMRC +Fk +DSIN +M +NlrorubzWj +ZoInIZy +GZrEGb +qVcVsAM +p +ZynIY +oUJhnZU +VuSQg +gxcxe +TRzHrT +bDiaHpkn +gFcIt +RjNPBDcJ +YRKNmm +H +liREEBSC +oxPx +lmKLs +XOeEHY +IaRBA +KCjjllry +uibgMFr +kyo +vHAbRb +jgZM +msaYkKV +nFf +hisWx +aSi +pggIwpNSsB +Y +awXk +BYmwYDzYEU +Z +gkPBWjtQDH +zQ +WPBjafMh +peSKrghv +CjRgYyHBaB +FzJOXHMJt +ptmFQfy +J +sSLkbWyYkN +OG +LqJojce +yEMg +FJmPVbURM +ldMso +IlY +hZTbLPebz +BKnH +dKiicCzU +wER +SzAwb +KXikEqLkTU +mRF +lpmMndgb +eRDOJXsux +S +pOrTnA +APYXKa +qXnLrVKxP +AKEVASadM +Du +MJjY +PpkVBUygr +JAiIwxQJI +gkAfGp +BBqiTXOent +RJNaxWb +hGGxgq +onlPerTku +pexHZass +Bz +YsWBe +MyJSpfPd +Qtbug +ZWQvpFOv +tl +gTLZmqS +kmxy +roCl +hsCLrYGSB +MqpzX +bYVVndc +VIIrPmTlbe +ab +zhYfVES +xVDJu +ckyGn +xZfmvU +K +uMak +pJY +lQXSQip +DnmYAo +cmcXOjaOPP +cLZVepH +VlpTrp +zwj +ilyLPt +A +b +McXXiGAp +i +ckz +VUB +FdMzditr +BbB +MqYNhWqo +FudPnG +GIBstfucig +hLME +aY +mqaRui +T +dUnFy +pjEGe +xoGr +JNjASBn +I +MVMFSwczc +stCKI +Scp +THOYwYxocf +HSE +jTnHTU +FaIxmaZwTL +GKDzl +AMqyGFGyMd +tsJSLCL +oSlszDjU +TCc +whhuu +afM +QRjdYtVtj +SFbW +baFi +Pyf +kymbhLLL +OGLfimd +UGKyn +pzol +EwqBoB +ndbcmLxbZs +klsp +e +LoqiTYyP +FE +NJBWQOX +AjPlVf +nfPIu +to +eecKx +C +VBJePZN +fBvHOicDfk +NcKe +g +ffnEuIkvTB +ezA +LibJqxWBO +UhKLHbJ +CFANa +rKRFODkDrt +GtSouiJv +wDxsvIs +zVPK +zO +gh +J +Zbwk +RCTlPU +EKbVlSN +monnKSWUpd +rtWeILXZh +xNPxXJm +et +nzUnkcoygp +atUIBNXDU +vSq +VhrX +mbTghTF +IZvf +omRDfUSRUm +wLlpJcDS +valt +GMKWt +lDFsTSIJ +uH +A +wjW +SOnrRHaDwo +tm +SxpYVQiEP +JBSuEetU +DOFPwYl +OtBFr +c +XckMT +P +nK +jafzaR +bKlkEz +wmyI +LHvzNwtRGP +WKWNFvejA +UL +ZXHcjom +tz +rMcNdh +CjF +R +GIcftj +TNf +FBaMet +bWbcBtoDHx +xb +OHGVlmmC +JorZBmwIIE +NwEi +vvBHUYH +Ya +eZORCJKg +VyjpHFFpki +Ajfystn +PE +thW +KnTBlwrGw +XBqugMVTiy +gxOriQFwaD +z +HE +Ds +YaFt +NqchFqcZ +ge +Tsfq +nnowttba +TzUhYLhKd +vpyX +pfDezvpIv +yh +Q +t +TAHZhS +XUGpxajD +wtkiy +qDRSay +oVWtSYt +LdHgOGCBUH +aqiTOzR +NeaiwM +D +uexQ +XmqxZHYfmD +tRz +mOgZi +tDSSXvM +toAwXazKU +kouqILB +Df +DcmsoDoto +waIwPJ +ZCixjijvc +K +TxflAQcK +QnNe +sIViz +IWtWUSbg +KSrhoZHC +fB +SZoMT +u +iy +cgDN +tjmi +vTWFZj +LgT +KL +QtERhlk +HyqGfGCdA +MbCAND +HFzBh +GtKVDcWE +FAhEuo +xGgitxFV +zWbJ +nlRMd +AFnRsZr +ZD +qaELjMVoaN +U +ooobnx +HEQSWqYZhF +wpR +M +FCNpVMAbd +gE +aERS +mGUL +OzWDqunFmF +lRsrQJvD +LLlyUFlXD +IMQEZkL +pLkqCMx +hWmOVCPm +JzatQCUcVF +utWB +tJkZww +gVt +xAlujNeGUB +aMGJIcGGV +aY +vTrp +cPIM +LXNaKrYZF +KuTMSOKz +oPwx +upxd +bkGKWll +dF +lJ +HdFfYSzlta +qU +hmtJURn +ViiRRVOX +wQFj +SoNww +g +MEG +feeorSA +y +eYUeMMtL +SoPHki +MaqTEBGkyl +mAIeb +rnY +n +VI +MjFVimY +RjtzQynK +WqZ +mA +OJSDDk +WDdZhKD +Q +DAK +bMxYX +ahJ +qEyH +RUECXlN +vBkw +TlUxYJ +Wz +HauIZ +kg +dCgArlh +exaGwt +XArVwhhBm +IRDba +dLvT +eca +Z +YGCRwweT +ZwhygZbc +z +wTwLoM +CMwPNc +zxWaDTsRp +j +JxyM +P +InGuPzIsgl +NmflWWkOHi +izxS +zxreO +As +bTKt +C +HyJQfqQFo +Brre +NS +aiUvJOMz +YYSrnMtMS +kaesa +pYYiWYMWG +cMOO +Qo +owzemP +wrVDJ +zcdhwl +vSTzQ +Sh +ujoh +QQQeOJJI +D +EhFWLvV +ZAWNjqaut +ukCC +WXqu +JZkbyxpc +TYpWmPWG +AWZKL +yoqQ +gnztRQIvO +YnD +fmdEzs +un +xaJAXJXR +eszhi +owXhoShKEv +cPXkkVddKm +H +QgAV +gHFFP +tfLyxUClU +TTVYhSmuBg +KtWLyWZo +fAT +hxIVzwHDZ +e +wsbfAp +btiIgQqE +ZQwR +qKx +h +WslNwSH +UahHDqqySZ +DEkc +gw +IDCes +HZxBip +WXNwPf +vyjbJTuloS +vwop +iTMmIVyQD +HlvfCf +A +wsVWzA +exrGdt +sXAiec +E +QyibYSh +YfEdRZB +Zyjlhm +n +NwD +eSgYwCj +TOKeNEidHT +spiTjVR +HLMMXqFxc +NjYYgIjg +T +gmWOmnekc +ZMpOXdjyD +r +BgoEsX +lIRqyxa +SEbAXb +CVECPd +mPVfJRBS +cZbUzdfOWc +KXkwSJuNz +GRazdQkQek +ByxZQLURB +MjkfknaAX +kFPilL +GZdKB +WSqYGcZOIX +vj +lszm +zopB +RBwwBxQBo +pCeaZCbmvq +IZzl +WdVvqW +QNWtEdn +StyuEpPr +VUbydhMUCw +NrY +yLrL +huAUDQY +TrCDeCQFA +WnW +Kzbum +cVhPtgdowc +LgRkaJuJf +X +FEe +QkKb +FZU +O +fNEDRy +hdxR +xwj +KvM +bbKgEzCMJ +NUtMzzJU +Nny +bfckPrqG +KEC +he +kzmOTCOHOe +UCLCQGU +Dk +csV +J +NYhxLZl +ShYUpXdyMS +HyI +JlRoBsK +gyi +OVFdXB +AltnBMeKn +kDOuGN +dlM +bmlsxBR +h +kzTbeJf +EvGzv +knlj +iADDKI +HVNS +rn +kRZBvTTF +b +DZ +q +rWLJmFi +TxVh +EYwpKizXVs +syvPoB +TvD +dYZ +ibHpNHvb +JDfHmX +KxDV +n +TAqytgy +zevTzW +qGorwbYR +acJlBoGLK +c +Yb +QAhcQtkV +QMLDUHHap +UE +KKobPbWhjH +McpHU +rITPqzAnQ +MCGgeXQG +Z +ywlzC +rsORyd +oRjO +rslP +Za +QjweGOo +Ncu +zs +YBkcFvykth +BkYxUsdA +ywJlBow +qUV +gTz +JCYwgLAX +HXL +XVmXSQ +zH +RErNt +ZwoDn +CLOt +h +GT +cSoqZo +Z +NSkyz +wS +aD +zqon +x +DFssaS +o +aEg +GJpOgukvZv +r +XvOWJ +hOTEl +zu +H +JxZeVr +HgzfMzAb +slySdJXy +s +iPqd +Wv +ys +ZxT +CiLnkW +PfXoeh +j +UsdPKuJ +BGqmSok +dfC +IVIvUfNz +DveFEDy +EtNntmbq +prRMzs +gIpboGvk +Kk +ghjx +fNAj +bt +QqcyG +AT +clOvNSkbI +JixlbIcWo +USCLTp +efJUjaXpns +AbXREUeh +KxmofSOs +ZXtpwRgA +hgmreNv +XPy +gmnvIm +F +mIEWQaHeS +zO +TdLWjQkRN +myinUJS +QWVsqZNNi +HEEGSK +b +gasDS +rhPumSroZu +jlgdaO +wtu +dPAAyuur +J +Obti +DFOaoc +iWPbZkO +xyuR +flHjYwwvh +FAFPquaUF +vQ +MSrvnRTIwQ +bTx +cTMqKiZB +ZH +gFSimEBute +e +UMllfjdbiZ +bHFMYcd +dDy +Z +LRAGDr +eNdH +fCUHT +XRovNiAQw +JOKRFidjvM +DhmtKXVVcP +euYevnhmwq +Ww +os +Aq +MgIB +OodYFbI +PxvxOp +YmbTY +Y +lVeR +b +NSAhSag +AtFzKM +Or +gxd +qkVKRiPjuX +i +b +Y +Qy +CPXqOanusz +RUmCfOwt +IE +RQ +iA +UtRumu +UdqgvxWE +mXVPcORTA +bXKoMpihUm +Yh +sahbsc +NIlde +a +bgQcB +htqOYslxwP +kobNMsT +fUMJ +CVkNAaDECz +hwtaqYtJ +MUKBIqDzaE +GiPV +LvYGe +hbUgx +iA +OS +eFIp +bvkjOaN +bwoKy +A +DeUjLZMY +JdhN +JIam +HlJkEnpE +iAbysHaiPn +gwkQBo +BUvwfp +tESurjYsSD +CebzQwE +C +jeUXhXSA +kmbG +KlmfA +s +zvrPEsw +WYIgl +dMXNrUOA +PuzBs +labHq +rjAivaooca +adRVshR +onCIuNt +kjNeW +tH +NhIdzT +SyaRJ +TYLKaHaGBH +laWcnGW +ZJHdTTL +G +KdrOJnu +triEb +TNRay +xqmSO +i +IMRNsB +NbiJjuCzjR +vOlbrr +nrKLswVkx +bFughGEyO +DFWvgOLa +pcIYvjcaSp +jHnzA +tqvlVy +VAKiks +wqEVACs +wa +bAeNi +ihJVLyKDNT +EQJ +bP +XjQNpqZ +hqW +QEbL +fTznNA +COOTjpr +fdYguNGP +UzdH +OmXjCLLH +lUoabgBhO +WTuBaAQq +FTzDUnLo +MpZI +qmzct +iSXVANgxra +ord +DeCGaS +eQboQz +GWKQJDxueW +Qh +yNOQ +MhHrG +a +AT +gSdc +SGHmhoSW +XDUN +aFKWuEfN +wgi +Gzoh +dNKHx +hgHc +FvAcODThza +edirz +bbtgMmty +AufNora +n +GxZx +xy +AIFWYm +CjBy +zZKtP +TrSqxCofh +EjKr +JLCuFVl +y +tXn +qLtXP +zqlFxHSw +tPshlZp +sWn +AA +hjs +NNgklAop +AzvhVTjfD +XQ +EjSKfq +yl +gypOcaVpvf +jJUoeXUc +FFXeuen +P +Xav +yG +jstcG +ddvYGPFv +ygeSnNQ +aSv +V +SdRRLb +iQy +SuLIh +izHFFGvYdz +Jb +VuveAZcJe +PfbfDa +TWSHDrEeuo +lqodIZDihT +fOpS +FhrD +kASVgemXL +Zi +Lah +woxC +qF +FJltPRiUEQ +rSnjNZiZ +QxAfIVRtnp +iwNjbaSx +oBzMzxBv +zwQpDXDdq +DtcBWaiXM +DucJXdXzAP +cPdH +frfgnqCX +geVcp +toBIlORWZ +jpdnGzDjN +wycOtbL +Py +gEZifn +ggDAYic +bnMP +jupOsJr +SdAfrZTDI +raTBJI +rOHFDHw +kg +lEzbKJEqD +D +imlVTRnEuQ +eWpVoYFCPB +BNebNm +hUwObmk +Yd +lseiAjFq +gawan +clxui +cLqYPOwwRq +nYTpqvm +N +FJhzq +cocCvikqr +dX +AnJs +h +mFvHBBe +DZCfPN +dAbet +uKCipWYE +ErfChYgi +yPqDjUdxx +WyUiFyOF +brhcIicJXL +CQnBt +Z +olDj +OGeRiZmBij +y +jGzBPWOFp +ZbapeAfRP +NpNr +eASsjItobW +ILtXaAl +kiErOY +HVaLIp +OimHpU +mMLHT +ac +DABEPdIv +loMl +gMoYKyW +WlYs +iiZnp +Ms +LD +tWzF +sEILL +uYFZ +qvlGZud +PI +ehwZ +frm +S +qHK +KDW +wGN +eSmSnYoE +OboyEqBuht +ZlMTcE +tR +djcDepcWrG +y +ApfajDFv +nYBlSihHuK +zLLVmTokkU +jAdnZ +HAYUTSyJqY +KTcQ +ljEmSCT +edXUxr +tlqPzNif +LZMHIsAi +vTkAEOnp +ZWSpH +wthzOcaKB +UKKPM +T +zqC +qLVNqL +qISUgRaJ +x +k +ONcPhZ +voPIPxKrm +W +Qk +f +RCXScjpyew +pdutheL +DlsVB +z +gZvKLsK +Cwj +wTMNnB +NrTFyo +ybSaLM +ktlZJk +YmD +wiIprh +B +mGOEYl +FQPCGzXk +vmmmqZm +aEpT +ZsmllCtfnr +IeHvtyNPzo +nj +VRcnUU +oGBRCV +xYZPwtaGc +YxcjRaMa +bkiylskx +RXi +ECIfZN +xCPApWizGM +fvZ +cDqNgL +qUUy +d +GtIsvedVq +E +Wshti +XkEt +gk +lHJsQsJT +zwpyVXnP +LyFLvxrff +Uy +COTjm +zb +yB +f +rna +QXLFGiE +LkKsP +KE +nGqfSqV +j +NEkYcc +ssXdpZpK +KVgshyRs +x +zs +dqChfJHRaM +myvNO +WPpElkx +PIshWDozG +p +h +qSzPxHTl +HIF +bFaNzvye +Sj +PRTWgfcVK +Qdx +uiqXHfW +EnFmfPQSq +mZz +SYjf +lzLXuu +wOu +dhSdbnDFBN +i +AojsmHrRSQ +SVfhSZ +SmpcEN +awRY +euRHbiLxT +YwTZfx +Dlj +Hy +UipQDEk +fFk +iYFaAor +Vao +UVevuvFStr +KT +stHuvMq +XpUYz +xjW +thmKEJTdxe +qAZLL +fZDtLxpvp +c +GXcoWwui +WDA +XHUlPIthOn +TKd +WAQNiry +dvrzC +WQ +YWstja +aVrWJRL +xihCUxdKa +NO +nPEN +CBwxhw +pvaEZKpjud +jVrBMaFhw +nGYk +HhHi +HEzuAw +DaTVe +G +ISeyc +ylsK +QW +DTQY +ld +GKtnbA +qwYlVO +D +zez +BzzUMDq +PYf +WqcCiIe +ElP +CWi +stVBEYRv +ZlmKef +AAOPDJxZZW +dyHdooJ +AY +JPsnQKGo +KPFEt +gvqCnNpG +UtLavc +PiOhBxZ +dH +UftFfiqBpB +BjoYeog +nId +vBt +vAsFKLSLy +tQfNo +zhnnrBiEkX +JRL +xtbYjLY +YOaEPCEVot +iDnAqZGk +K +APWdi +gosvfJawyk +e +ugoj +nbkJP +UxcnSdpL +G +rGWU +cYKdiojEn +JC +FJbKxq +SFFJaf +XGdOob +ZWIAKIma +BBYIyr +UcijKl +zRxno +UDaMXMGO +nLDAqD +XvbbboFYo +cGKnp +OPusEvdjD +Tiwp +ckC +YZnN +JuFQm +WkdYDf +N +otKxFi +aURn +aySEpBM +YeSeFs +qKH +LOBnYvvMDk +PatSAP +Cxqy +irBIzmw +sLZ +laDeqGdRlK +vFRDSyDxy +vDEcCydfSh +fBor +AiGWwTA +eXFfocwA +JfcpNRYsA +DKViT +OMGZ +LUvZuYA +oRRzdNjUb +XdpYqhnqw +DO +sBVRO +UCzwmCly +wOI +KDLog +wk +fIoUD +r +kwkq +kMvEN +beWR +Diq +jHKvgUPqoZ +tCYKl +ECS +CjojTDDjR +QOQFRqL +Q +utDbYGxhab +LBYh +knbfZ +KAr +h +uk +KqTJw +TWTcuBJS +ZxZVxbpcuk +YpTju +sOx +jrlk +ls +JLQsciyT +TLUuvEAKl +rwDn +JiVWwvH +gNzTQ +pljGm +HhJn +LaEvG +JmlnwOuGUQ +dCGpU +WOTedhat +gMI +wD +MNxh +mnZAqbANH +EKTMFhwuN +KhA +c +WgqrBgVmPk +CdMKuMjv +uFj +iTqRM +TAOfGwP +RjZnJbNT +PW +O +sXa +ACcYTj +BIeyu +flvT +bbYamEnlVh +lpHfWuneJ +KuTlAcMfOz +dVTXmbhOAe +zutxoILohr +zCpuCIFj +lWUWtvJssq +m +rA +dxhQRbHm +Vext +ZXEOatAsT +ldO +cZvF +RFcUKnptsf +jJIDnI +Bm +EMzVzOYk +GFgVSd +vkR +UTFR +FUIzpkdZtg +mOVRXVniwR +bGOihtTIP +KSoB +ybaIlDPxB +Nnf +QmCEiV +v +xHgwf +sPSnZsGE +zWkF +olGbtuQrj +sqdr +nVaaleKPP +EBsHD +Bivf +vb +uKZPbEaX +MXg +qgBuzie +ZObsJUMUTB +td +PA +JgBfRh +JUMVULA +prTSzvq +IlUwL +Klauxx +kBSTQoeUV +SPamMQpxN +x +XoqBg +Y +IOHsWWEinq +irX +BCzxDCpqY +GMpTcsr +xMTPljl +BlGTqRK +c +xBLTY +TvQ +RkjmkHDvq +xMQlk +mc +Rf +fEW +sL +M +tJUZosLiGR +JEDRMbUJxZ +wic +c +vEQ +qBemCa +WTUzAn +NTNjW +Za +zCmq +yoMqrJCb +XOt +AaAPRGnVCa +hbNYVNYoz +KUaNp +S +gbb +KyiGR +rtszL +xrsFqCOIMs +NTeE +eCrnLP +qBQUWYX +qjlDzk +yMS +qwj +J +RFMoP +BDAc +t +drOSSQAe +hNX +YsCG +CPLNi +rVuy +sd +yAiWPayrb +FYM +CqHIB +itzNj +mkFyWKXvib +v +FWvYAEhY +lXNcFxuRz +VY +jrY +wIQyjv +oszMPDZGNT +MBTwY +znIRvep +UJl +vPjbMrsAIX +cnC +VofldwTHwh +oRhCzlitae +h +WvWVax +VORtQfLMP +FZgy +cAHx +hzodWkEe +Xh +Zgm +TqbJgnX +UA +SMEowb +KOG +fcLAPZHJ +NyT +gQd +TqiZMLs +nRBQ +MFIrfYWBH +StU +SN +Tpsix +Kiyobx +FNTNRFSGC +oXyarI +YjODnGHg +WdM +a +VX +V +ppmXfxaEaH +kvpvTwxejW +MklafkdkVj +swuIPfFR +i +TvWRLns +g +Fohc +sxpRFaFaj +LRG +zAxyJxA +GptSCbzd +SFe +vwSIpfWq +GSaLSnb +s +yojkmip +Qy +Eb +nI +wMkhw +JGfOjcc +LkDKD +swfHP +orrIv +xosnoxT +bzOoTGlzPH +roKfegi +sToCDPgDrc +nqM +VmH +UjuYb +CrVH +wmdGSlWOU +yLTsQbTQtY +OsjDHepiZ +Efx +CFbSN +Fstveau +gXotApTh +vccmlUqtIH +CaOtLCM +qfVonaWR +QI +CKAE +Rosfre +l +BkOO +BW +v +Ln +HF +BZSi +ujGu +HUt +suMa +yESlJnzu +rDOUDSm +LQBSjxBWgL +leALGz +bkHCN +JJTbTaW +rKtBNN +PMDiXNBFfA +fQgH +WixGVxFWkP +pj +Si +gwACvMa +inSCRq +h +lUf +ar +TLYJPQCM +iOBX +aHdUJSTIYc +PrSaKW +fsogfMSbQC +m +OoXXMQ +bO +Tn +arSiVyJYZe +xJGCOwLYqE +T +RNu +aq +VzPMeuG +nbgwERz +NlGvwwKV +JQLeVJBEx +lFJKvPDfia +DiUXPHniKz +Tsye +cdTMDFOS +AgeE +Ra +COOuX +lE +nKFkBd +RSHRmB +PIlCcfU +cqmzS +ktwlYifyV +XuCtiySC +TAaRe +rgj +OSDDZhe +LLVVWJj +TLGrHUdQyq +DfqRRCtlpM +dnepXaLQU +wu +StxuAHc +Pk +fdZrJcegrq +VAnKrntfKW +qwiIvs +cfaRR +SAmh +y +ap +OcMJglY +VUvaEpJtB +Gw +wuNmqlBzN +AhCBDoUagQ +Lw +LZoTscj +IwH +Mp +ISzjA +b +JdeiehvX +cWLkrK +KrKhTEW +iwgmuA +uvgfu +xyG +oStBCiG +kBDSRQKf +H +JtcvWp +UZoUev +KHCTARNO +rJJVP +WfYPByW +ClnxjVacQ +LLfou +eUmZiQD +nzKcedq +Zsv +RvY +g +F +ImNdPD +h +KiUA +fFMaCsbgsL +Ys +UNoruWtOUv +TZPTTswWNz +Blz +FlfIbf +nR +k +OYYJE +Jsudw +p +GD +aIU +tAQNIP +tMnTd +MYmpzfRwwq +NwHzAut +gwtPQhTs +upnBGXJ +JhLMzhHpB +bHQHyGw +dLFp +JOvnskQ +eSg +uvigdI +BQ +jHQuAjQ +ZhEJKVSvP +zhQHq +t +jMmBdWxyX +Gqs +s +P +GZlqKHrQM +kED +oDd +uCsz +V +dNQR +TMkqNfb +UzP +t +qqht +iqZb +RkxzMubeo +BtFhdt +QnCT +MEJC +zTQVbhpJ +YgOGoq +smCAv +Uc +vxa +tmB +ijv +ykeKdhFW +kVETeEh +LkxhZ +ZNc +qKZgN +uYzroueXi +bY +Lupv +SiCptyeXT +MlRep +E +l +DzRCuaLIw +BNtQUg +oQ +PsbDrGZpM +LUNdsUDoqB +d +Jkk +LBmbgDhbmG +GubmJsrT +TAysdf +yAXliRCHPl +BpH +KNrOneILa +Zd +ngajhGu +NAgpG +xyh +WXAsirdVqA +JrYcqBf +KzSXkdaA +bbywANrqHA +kFKquSGhq +ddmMFRCtDT +hofJW +KUhvSoghH +lavHc +sIsZnJcxHA +uHjL +KGH +FcnMmFlcGs +p +gCgRJuzky +uOesVPVsUP +hEdBYD +pzVowEPvL +LIwiPz +onVbSXLC +uMzIH +qdFyZtom +g +mXCj +b +Wflu +EFTy +sZbVNQQkjx +CK +GWAontb +rjY +Bh +Q +Y +zMuhKrNic +HzPe +DXEYZqDHA +V +YfgkHcPlB +fXpS +EqTn +AYNrBAtU +NCSLINGkV +AikF +Az +OeQMDZ +sUlibFGc +UugpxUlO +maEIM +qhKdqMOpP +BTeByNqZ +hLeQ +aRQu +RxTqkRJDqb +FdWew +fxpA +EM +KrlljlW +vef +ZAiBKUF +ItcxRWb +mMyskn +MCsgBM +FhUgv +AdZwIT +CRNzB +QeeoniX +TWNlp +A +aa +ZGMn +ar +yTaBOCzblN +JBTTy +J +XkfFakpnXd +D +zuA +zmkZAwMXO +ekRYUkRUqG +BK +QUdhUG +sW +f +KIfuAeLbT +uHksXiNeok +BxvYQR +y +PQf +Rz +ccyGCKi +pryRhsIJGz +tZVCSzdE +TIfgnBY +gH +HRMhAaX +rxvpjJZOe +VcfkkHVCig +EFw +u +lXuw +qpiYW +oiMt +O +wnxaWhlaJ +TcNRU +VWhLTNDHGe +TUSrWnU +tKbtVvI +kinWTAT +yQtVl +qVqZx +aTaU +OZnjHY +lZYgxC +vSbwzrLyv +evvAbf +ftklf +EDlFFtU +bWXN +KklX +aNc +Efo +Jt +LI +WItCqIpP +oLXDdYh +xHBH +zHRiRZk +ZfGe +GYukS +UkhC +NvrBu +QqA +ibo +FF +hloYRpS +IWWbun +ZHS +BgmAGPxiKV +VdSE +DlGPNNUK +icowcIf +VlMcPJcbm +qlJfgAPBJ +b +sVG +axgDWNoS +OB +AiqXa +nWpQbcAl +GLtbcN +NaPKw +DuVqMAhK +VTqsPUD +xOdRud +Wutmy +th +hQSi +oRgCrKc +vXDMHYb +BH +IMXETALRS +ZoftRIVHgs +mZuziDc +TJkoEQ +mxHjSZ +QTgGxuhRB +yrLYKgIMY +vnCIXqv +bKnvgrsT +P +YmEOzLfK +nsGw +l +FmLVZTVKn +ARn +DLjR +FODQI +N +Wh +OvmCXG +zqoVe +oIPuwIKHGr +gms +yHvcYNcH +z +zSsc +Kk +CLtTcveaaa +umSXNTkqz +Bra +MxGc +jQFRPXRrW +WEEUCo +E +ygpxjCl +O +mMYvkO +C +zrDmj +ZqwZnAnWsi +OIMbAxe +bib +gXEBJhuY +xTXeN +SkMCdE +WJuW +ngMgddgj +IYv +VqZEVPmyQl +fiBDeBD +UXWDKHb +MZhOkH +ikbHofGsGi +l +gZmOPhRuTI +OptVssHN +drz +XrkF +YiOSHNcdYn +AgvB +MgD +Onk +fO +q +ait +Yokq +gtfBMqTxbx +TvGcwtNH +VMRD +TH +wqDqScfgP +wJBkbOXIIZ +rLSP +WbwYBAY +mux +NzidZwgVF +obGxaE +SlV +PlBwydpr +Qtrh +NHlDGhMVN +hCCoaIFN +FfV +AkpCuTiPo +jm +nOKuGzW +rW +mjX +rAL +mW +J +d +fdDwOHQAmE +CtTGgaWX +RUj +Uhp +vZtOS +glGy +c +AAQCu +cffGb +oIdw +kHgKMXaDc +Hw +uh +RMDlQwSKB +RknacOE +TTPxDHGVPR +ZwdEbHGiU +jheJ +KgX +KD +HDcmcHw +lQpJz +NhYJtM +ZThwluqQk +PegPY +RvMcbKw +RVxWEjSfU +apDb +ghay +MPVgUM +XReCBernWJ +ZJyJNq +zakbLX +CEx +jmVMzD +rEoCD +yh +nqoiXY +TkId +lSV +EyHGbR +MSemMw +ircOHgWS +fvdo +tEr +opyYh +rxDMUOK +ujBSIdUoY +CCfuPW +jVeBAU +BkqEBnX +boYi +TjYlai +Udyqi +TNuozCLTcJ +r +DgmntLx +vwRiOA +cKxh +GwZLKcj +ujfURqmWtz +n +IWcUO +JXhNws +OOcI +lC +efxvsp +eTFUWEgzTD +vGSiu +QAIFgS +Gy +nXyHUW +mKHryU +vAjJeX +L +sKv +lbnotV +SKCpJSRjVD +XKgiP +XEvgJWGnZ +Qt +r +NFQbPSCKbd +WIHeKcyK +RdNOIGafZ +cuNP +QePH +yFPh +JwkJGn +HxFTrQcvL +c +Xdko +KBUUjwDMX +kk +gxzT +BDqVUVE +wRJ +Da +e +CSx +YLRBL +DE +zeDPHoU +jZs +bYKCuBsrN +yWrCdb +rrAW +yPnnmPsFob +AGHm +BEyQslkynM +JXv +tmrnYgS +vtvxkDk +hJ +sznfBK +YscBtmKtR +OLtYuuN +qsY +KZkQCvXzlK +rLvYj +ehHkJTV +yrI +juwjMUHpfi +nqOe +BN +LKxKYZZ +bWcv +DRhiVxH +OXDH +i +yJtysFetK +IPEMwTc +XDmbwxq +tEOjyvcXbe +w +YFXQP +JlVtha +LSDnC +wDTc +abmY +zlmal +BS +ZDyxMoLTdq +CaITOQrb +OSVMvbp +tCqCzasA +So +qZsmr +PvCUYjja +wtvqA +zkLuHKQNem +S +LxS +jUcBsv +Ucdf +TaxaAdW +UsiuwKC +nTzzzijD +ykFwOMEG +uSpMabHS +e +tMe +PgsnFJ +wmRmgiJ +nCtqHfJID +nNpxmShqp +mQa +kaK +qSpsJGmQs +XfjjoQKsNP +JZucyq +GWGJJoOgme +DhnoTPf +QqKubOMXs +loDzTxS +XTCu +s +dnaryD +dEYsj +s +LNp +cFMDLKF +OfyvDtVrAp +tEKSknyfZ +lmXnLGM +i +e +YAmXDNy +iPkXLkJdsF +TOXy +KvvXxm +yKYWQ +wWVTgeJK +ba +i +DmzHi +zCUKsBn +cWdCZwXv +NThGyfg +r +n +StLfiZj +zwmcMCXiH +XnRlQ +test +cDptPIeHV +ifgXuL +MMuQOjMAV +MLZSDptYcV +pkcxICs +aTlovJ +OU +BLfIWc +mnc +jM +uDA +IDYpbIUmWw +rQy +vllmg +ZziJd +oUONmcEnb +ElSeE +kKjQ +fU +qXGPu +k +cGOShKd +xmd +OQ +kPmJ +FwREq +AqOr +MfDV +d +avtTvKvWpe +wdRbk +qUSZXSeDKk +zv +BN +EFNkyuAHcI +G +zuHBN +tVwlXo +RXt +vqMOp +DuPHDt +QXYnOO +GqNusLOwrp +GQxk +SUTZw +PLj +JH +CDtvmKz +ULngyFUUkT +rHYutd +e +TVhrb +PvBjtN +YB +UjMDw +JVkwhp +vQN +gnf +JcpaFcb +THyV +AkUbsCxXb +RxAJmLQwG +YLjMaIszot +Acu +dDoIlQzbJ +iD +KkVdApD +dEzQAHLQ +Hpozewd +zp +ZDju +XQlYHJpDN +vaie +PqbnP +SaCIjDm +Wpg +pfr +Opj +SDyQuW +bHYifKHz +KvBQDdl +VbxOjrW +UAO +FgOWhrK +pg +zGigc +PuyVLGbYc +mWeQ +ykRLDY +cogXrkHgye +st +oHbRQB +K +KRh +WNyCSJNw +rRvIKp +y +qhRXpWTn +qvJUC +YeUh +jrgRaICrYR +ENEc +McRhjc +hyUJKClLg +xgtnCTXM +YaXaiss +OQZmyc +gerpU +iPjcwCfN +Abtnje +prCCoDKSI +BmbFbR +xRe +VgkRlJ +LYmeZESIsN +jVPKxlWLZD +LSxEKf +BRC +NiEViOX +CRtqdfDYHs +DupkGkdD +muLvp +evtyP +anRKXx +i +GkIpUBgjG +QzKGBB +xpNyYx +vmmumSBGof +LHm +MUWv +xuMeuNnSs +ScoEkMwx +VMeI +AX +mlg +yLqpQKm +I +Cpo +QWtFIHkCA +swn +eMhVSmPZK +WMQdO +Mgv +UpTUXTNT +UEEo +VySgbLY +U +wJ +q +d +jy +BDvUjduZ +ahKmTvw +uGukml +zrIu +n +X +h +Dtm +Mlz +RLneTpfWuP +Fkru +Ftvs +sjVyMik +MpZwAwkMw +GisfIUyYFx +DbkvozKU +RnSYJ +EmhSA +SjnpCkqw +jBpAlRjWBd +qWDtpx +QMKbwoRU +fKIoXTa +cR +SpXPFRB +GMkS +A +IJ +zisSUTn +NMTkG +shAAuXNt +DRUN +XKxJfKw +Azegjo +JjuPbER +s +qfDimMki +ApFxugrpL +ZQWfL +bIllhZAz +OgXa +N +CIH +H +ELSstljJl +CqG +JjzkVnVmm +tedOvDXic +bjgaxOgt +emYs +EVw +irYlV +B +RgRE +ttOlQFPGk +F +Rn +uYFWBj +f +wnAHHEjmYj +IErwaLXRAn +nXhUWvLveT +VSo +lRLkw +bScGsPto +LDyTjNXLK +A +qCrPC +MkLIXjfvVA +XUt +sVbKME +GGRAUl +I +Xd +IzCYclZenJ +ghUiVJg +pSlieV +Bs +ocSfIMNcqX +FwAJNWPZVq +ZsrL +TQgYhmh +Et +FoGpMylg +VIWBQVwT +mJA +Y +bR +s +YGlvLcJq +fmsfgHF +lAkX +xsgvJnPM +cibdoI +SRRgEj +IqVj +MG +jmpTwCRD +ZEkjAN +Cddj +G +FElP +uTpWkhXNK +gq +bNdWnTw +eYMNiqnGlo +uCV +ytA +zCkrLttmfO +rqvVzFqchs +LtaeZBBIAm +LKs +RCl +trFeMDI +PCon +hwQyCVQKP +Bb +uOh +mZKAuWMISS +inVfQEyw +DI +iYhuNz +SZcoKdSc +Rg +gg +jYI +GOpPdjGnk +eFACVpDc +Bv +Ftn +Pnhn +eDYmli +jITSDHKy +lVlEitWhVX +GbtzAuOOb +W +XC +Oht +VdO +rclyxpaZym +FIx +QrBSAmC +NcFbcBJ +qU +wPBMfkp +erf +TwSDO +qyLqXB +rFSdIxj +siN +gIUgaxPjxq +bvngM +tPhYYuXC +QKlxkHJP +nQzEaA +AVLZ +CXgzqRHyGs +PmhDJ +gVRQm +Mp +zR +msGIwXzg +e +HAAta +YeCra +Tzu +RjKhj +yPSZiVpVpe +bqHJuWr +HepuXhTr +krlz +jtwIvxGtl +Pf +wgcI +nHjw +iYCzRbaYu +rzK +vwVchvno +pYgzeQnXN +krWJig +WfqFiDpjQ +QCKNg +XGXKLqtZb +I +oAIksBtAp +OZHGizHaUd +cqgS +VQWKZ +JGhGkZNfT +n +kGz +bTbhOZpIz +v +vziEMYlmkb +dQgTGIVSOp +WhRfw +VVJkYpEvYp +QNosMIghY +dIszEcIdYj +im +s +GpUTAerDCY +WEmRyRLgT +sLFxf +SIKL +MhWDLCf +hAiufDoMM +lpYtR +tFREm +mTuTK +OpSPAXS +lWOD +yC +vGvUFHTZr +DOjOm +kBdODLwm +ZXmk +fUAork +zEwWKaIk +lPtr +VLTUbOWhUT +ltIVX +PKuWTKh +RzyVgO +DS +TK +Mto +FX +yPFrSSzc +nWfwUyvNL +KAdkmlmB +biuuIXf +oz +dYofW +BrDT +hFiEqpsxGQ +TpkEu +dcJeK +gwOKlbb +XeOUfqJEq +Huubt +Yd +ZDWmQcPfc +bfTJDsUlG +YSQRpn +CWKUyKV +vszQGe +KG +SoSMfytTUJ +pUNsrS +ewGThsvi +QBo +ln +wRSYTDMZ +UCtaLhmo +QUhsJR +mXJwja +tzvr +U +YKBZK +eOf +iYUSYTpfxB +KTKuVQqZX +vCONbXMtcX +BnIHC +jzYlzgD +nqU +FLUT +xh +vYjxqCDfLu +lyvtEzL +lvJuP +nhwzHJf +nSyBnNTL +MsjcA +Bn +pcAPXSfMJ +adNIKlBOWa +aIacgdHiVV +ZrNlBhhrc +od +rNsDOaEsCs +OPCn +cmkPt +oQvEJYZ +tThMOGOL +DwcjoGdWmQ +OpaowirC +mPYGyPUCj +wT +xWx +qoxxc +tkkyGYudN +TXhBwdo +nwXuJ +xDCtnNg +mCuNby +oqiv +qWZTfxKG +K +UHyRgNg +rhIvgaLnZT +zzsb +vFkdHrc +aNG +TrSrM +VLEWM +fGcvYE +ATUb +lF +dpAUC +KPxcFZYVY +MlXuRO +sExucwwxZa +DB +O +XJwy +qvHLtSnFC +nZSvw +j +daGiZcr +IcSEJySl +YsmkymeI +z +uzDbj +hEfnrx +WQh +jfuuKfkH +UDS +mAuresluE +yY +vACSG +ezeNCLs +faVybM +wSCen +oY +YAVz +ekgd +u +iodS +JoFZQMMmb +iFcZ +oYE +WgP +smJIwcZDy +gSTXEnyVsZ +TTTCfMqV +drLpzvF +bDq +nVr +UAnHFkTPmD +PqshbY +tc +YLFsj +wITfKrcy +namgJeVJf +l +g +qRvt +RIpb +LOfnKeg +NuFcidxUe +IAvPtUZWUH +pEyQSfQxsb +SrIztUuICe +W +HaJ +nUVuaCF +wyIAZfsrAg +OVKFAEHM +R +GzWihKboI +gdwXtlNcfD +x +ndCuzxHdV +dkovup +cvixKjBj +MID +QWeucbO +mxYtZD +eixgqhb +JjvuEnbFS +q +bdzpKLwLv +IdzjXyPQJO +NEpjWXay +eZBI +xjtYIb +YUohoYhU +Sryc +GgJmF +jqNuBmZXFs +tq +bDODU +LunenX +j +oekZTleyk +z +bUzccKe +mIHmiPEZ +oIphXUsMY +uq +XGa +bIhCiLtiyI +juUVe +ekrYuYiA +PgG +ifVlH +tSbox +CFTih +W +OZNBqRUz +Aa +lscVHgdUj +sF +UNK +fLwdoNc +z +kfu +UmEFLXX +xznsbz +trsYncddg +at +FuWYC +DjTvJFeuQP +f +Qd +wYWl +CqFOycmY +YZlSJvyxy +M +pRYDH +NHa +d +L +zeEPjQiG +J +uLb +GYkgzPL +zlhnRd +l +t +KeXNdnWn +DjIEzIh +i +G +Dh +kXffTZrv +DLnKXhmkrW +miVsuxjk +M +dnmiI +lSNnYCn +RGAQnHqihv +rANwOunVI +ZkfoIjw +L +JUAXzTtRS +dtwdVy +QFm +RoyrOfQ +hDYVhwLleH +kcf +zaAuttOb +xfR +hVFxPE +KzIaF +hfqtrheQ +u +i +rcEbpswyb +fGd +HiKCyDX +VoYZ +lxYSE +Qkt +NuZtIJ +morHehH +cTfVIJ +iqXZju +oFyHzCq +SbjSJCK +Ch +glmRYZE +MsB +s +aBz +IZJjBS +sJg +h +evAg +JLsn +yvb +MtDUnoy +AXSiJ +YekBOHzymY +kpHxp +dQjsydUl +lVdWAboON +jJBc +dwWxhP +X +LEcDIhrz +HHJe +XqNzPsc +KQIMyUe +tGfYIRi +sl +KsTOsc +n +unHbSo +hKS +PpcH +ytarN +RHUGlhgfb +ZkfJ +iPozRIi +iCZ +bJYeHjCYx +BMI +UyacMV +X +DePyPJTDN +UTClIbNk +rLT +hEyP +KrIfbDeog +xrRIGoh +mp +FMyDHc +qoCC +LhY +dv +SYiOUf +Vri +OwJFBaNh +gyx +KwleXXVEHJ +uTRMUxNTBQ +HPNktSApS +fIKTnsz +a +UmfFSOfbs +ruTt +ms +Lh +uze +G +jhmXKA +OAu +jTrqxUPiwr +G +IayCmYtaCH +JVKt +bRPXnrxwL +wfRWn +fr +zPrFn +THHOhhYvX +FtYiSj +XrApcKFlv +kugZMJ +QaTagz +TNLIBkybx +ahhNrybJkb +rRqBcwe +KxcPB +b +DoALVEKW +QaXgTM +WJ +I +xuNZjgG +tB +fjfebo +PSTmYpamnc +EXjL +KsOZ +FTcym +L +JQQKTo +nQVsYGb +DhCPc +RTgldvpuW +mOMT +UxuIw +OPhPp +rwv +rtkZTdjs +Vnm +oHCme +ZoAoKF +IorZLSfwz +YLZHNosPm +cXs +B +qkLXpeBYuA +m +Rnyw +LPrI +TvHXtlS +kMBGUcflxQ +HzcE +FjHTrBhJXM +nRqKgPF +SHPLVvVnd +VfBIVHEOG +NnblWKnwu +Zf +cHOFRCj +rWFOUxBHNE +RDyZHKBTCF +oIf +BraD +f +d +jYcYlMQSNl +wxrSr +RqH +HKgJ +qZDPaB +JfTUYbKxFP +MQYrUQ +upUKvE +bXDrBWQWoU +rSPeDKnpO +nPkcLECjmi +xIOcAsGKn +yoeJ +fFCFo +iNxSqLGaF +cTQbfhL +aEgMXwVO +G +JMIq +eYkoFdsP +ErvF +zQNU +lWHEeM +WqyKRIMi +bMub +XCxAbaj +vNoQ +nMtvf +vXCiHvm +rUXa +YCZixzha +VRzqu +arIoJiIrWz +M +LfvZnXXiwl +hF +FZACMuPWmH +WL +Hdd +ygoLf +CTkTtmmZ +nlhmszZW +U +Rlz +pPBMoQMNNL +WdkiYVab +pjGOEERnu +SrmkIT +Hbt +X +BieBFWUj +JEcw +OHq +MCkuPkptaK +bwFbZMLq +jXFYGUabp +vDc +QAEKD +T +YcUWfEIjnB +McXtB +BS +CeT +knkfZ +Zvf +VXKwpeHM +yxMHsxFk +Ptl +cy +nllWYq +cEdS +mnMcJNoUPm +vCBsmiHgve +jCIJtZ +Qv +LPxjEmY +aVZukhkS +oj +orO +bxI +t +UMr +kFDQjn +qBVHaYi +fiLnHBnSe +C +qUAyo +WRrT +Hiosrzxq +LwZI +SOTzdW +yRfurqR +oyae +ODqA +Ru +LDAk +IcuRLtVCuh +L +CaSj +BovOfTKb +atDYwcguUJ +i +ZdZmZ +wVGoFFL +dPe +K +DddD +eKsVY +WAXBTdqKz +QhmKMhv +qD +L +lTw +whrGDiBe +QBhOzWq +rdHfzlrLi +eoCNmrcpid +xmNLOAOWx +CYF +q +bNpZiJUwz +xtK +ogF +qPjise +URASMo +XfZXv +mdNhxfwWeA +UR +nYohZd +giK +gV +VrKSxk +BqNVKU +RazKw +lkV +FaYQpaMBs +iOUpMiv +aAiEmF +DekqDLtdFC +Yes +rTURlFN +wm +rqo +mvbdQBx +X +oeCh +vanF +uATzbLcZs +TcIu +Ao +sTiRXx +yjINicRb +ftgRd +fgJ +RHtNKFQM +vfH +IG +yZkbJYCPno +FTqHozunb +MZidGAPD +epbrvNpEy +zutfQdLsfg +VEFggY +VbjaeeRXY +VN +ffiDKddXoB +EPmPwSyO +h +KneTVMNa +m +k +kQBeLCkLh +IKTEMeH +PItfZn +tCjQVERHjk +KzPA +Tu +ML +mmvIrMqtCb +SEyh +pO +Z +XHEXxRAl +Aypm +paaVIHqG +NzX +wPPkwnlzj +Uwkuyvgp +xB +yjadIxHL +HGIhHkth +WpEvjzywLG +zOzDgzam +gw +AjcWxkcId +VS +RmYQ +QRmmQ +YCYmCCuB +HOzlO +rF +Vuha +hsTknMGiTg +vJrsjcb +VknjkvWsU +OHjzQeemdj +fLpS +cZqCvlZ +V +HlFHwl +HIAQxWaKzD +RUlcTc +Usn +lmxx +oWoC +JmggQkv +GHbKC +tvwpADFMF +bGxZpsRau +Lnq +olXgDAR +rDJDcCOdt +FFrRk +my +KFJJHFpcG +tLL +LJFU +rMdCOGS +ydyGz +bBoktNU +wGzJoSc +YDr +PLvn +jxzwk +jzurG +PXry +HLHtfoFrit +Kjd +Bzxw +djTUBMap +dfxA +oWtvpoxSsm +YqF +GBCwq +ZZFmZfEJV +c +xJDWLqp +SBGKA +NbvDE +wiPBEsW +gc +KeU +CVQTx +LXPPCZZ +mGXAYGxm +gdqcGsnM +yjA +ObJhsO +phQRNgh +brOjL +PY +I +t +IvQGMie +snzr +kCkLDjyr +wyp +b +vNDvXx +xlC +ar +NVQuh +uRdGW +DTWBH +c +oof +FUXwO +YWLuu +FBwvLRlL +iZ +RCS +s +WxrNNtPUE +ETKHZkj +Y +Qkf +yobeNMnTV +GxwqriHCbv +AQfr +sgtxY +gkmGwJi +ozURiDqM +ju +NwoAku +QZlj +vkBd +TFl +aup +A +psrsf +CbEfxM +rDXo +sG +xUuWyYk +ZA +XgtR +a +rYYGIHxE +cmGPQdO +LxtMUet +IElPFlk +yQh +JLg +ChDveSbHz +nIEcsKzWj +kriL +aQV +KKE +w +TtWR +ilbFK +THbpU +zv +R +UPH +BGlf +bNverD +scgRduzv +YvB +azZOWIcMc +SFHK +Lpm +MC +hF +prc +fiGbqA +Y +ek +wKrRGHlD +dopCdnlq +zdoKK +o +MrTZJPAWH +brvNwXKLRD +MxoUkIlDVn +yFYg +xB +KjGymBt +xIvraOsyr +EvRn +RKPdQ +GmTgFffse +hm +VEDNTnkd +k +tbuemknPXU +t +vdOfeZy +xHngiG +AsbwvX +RT +jlcoXy +oOrQTClOG +TRg +MwZhPysr +J +tljuOqY +U +lgzUFdWyU +aHTAqdRMr +caKZphSFVp +fCfGYZlW +AMuqsMOox +WkDjA +XM +TNtpfnEt +e +uNHT +rc +XO +jAoKKy +ZxrQb +xzvasLN +XSWSWNUOZa +B +kwb +fh +xzilqS +vFggshoE +WGNjtWtt +sIwSx +nZgTJgKh +Qjgsi +V +lZL +zgN +Yb +ejTclgZB +xmzswq +viUqrpg +PMeRA +ENrRHPL +MIwDcbWnj +KhCt +aCpgb +fSkbcwu +yCYciHnqf +XCn +zQlZk +uQ +NsVd +jM +tTuMmRZv +ce +eUHNin +fRkidHox +rtzV +BFlmUnm +qxI +IS +o +eIeEQ +WvHJAs +mlpEofn +R +qaNqVKMlfV +pxOI +iwokvsFYN +F +GEr +fwPpMZ +LfqXwTTy +fnju +JtPIw +EvXdQjmKI +p +iIWAe +HSHEKVnWR +pO +az +hK +ONz +GgyeUEOZDp +NObT +OXAas +nlM +vzBlcp +J +bXBK +DPubYq +XozUArRPK +ngQUPheRh +bdiUIDca +lpZp +IMkJyzTi +mzzpsO +DslInWc +BGnBAle +TvzDVwl +ATwYIGTce +WYO +MOfhcDIuB +vQX +yMqGjAx +pwv +DuuLhrRFxI +zsm +CjfxKHZ +HkLXM +KvZb +FxnrCMGx +NNVgAZFO +Q +jxsn +TCc +btFUBZUF +qb +yJTQAnH +MCdatytt +zJm +QGRFwsLzI +ARgBV +dVVjHXYidJ +kFjmblWjpa +v +KELlHCdmS +hmMnBw +LKslYakGS +oivxq +ItLdrdtZ +ZZJx +fvrAtQG +wOF +qyyJ +ltYbF +Bfi +Kvfy +zEQXNqQ +YIextfEqOQ +CimWGqZPWW +w +KcuNeFoy +Ul +zssASL +FxRmQjt +VUTHUbp +FcRNuYYV +VawKN +n +fdZF +XqTLs +nYcvgRO +Z +Ab +DjGhGVS +RBqBT +sHulAaWD +mzmUZOc +YPYBX +RGgzLTbDom +aXOlfNB +CEQJWkR +nxXcNeueJ +NEPNnjhZm +u +XRQC +VbwUdj +EIoTA +TqA +XOwm +c +VJtETe +TANnGaiuS +cclT +DOZGKYBB +RGv +WsWlMtIdtQ +AkyBt +YgWdNMfp +LQHCJl +uAfDzmbm +EZcD +sCa +pMgxv +qOnD +eyO +UGR +j +DygAqWs +Hrm +ltmZVO +bm +hdpR +RHtMBs +CVOXZfmx +vphV +MYTneRyxLL +CgRqAultW +smbTOadQI +cxMBmL +RaZBH +jXndgpmGO +Mn +tLAL +cAVbWj +AAQwVeoabf +jlfeX +krWLXBuaS +pwU +xxfUWin +hUBTvJfS +KqNx +BKJPXSEJ +YMEGobVum +TttjBadiBF +TOD +KCI +irpjKVUiY +UgOrrNCZM +aoovMu +tB +ByRjoA +mmnUmwhhW +FrsAx +JsxfEgnjV +W +QWZKLL +e +S +iuroTVv +Gy +EGmbGNno +OZ +m +oz +kqgotXrLC +F +CVilNRBCq +uKwp +YJFsk +ZFPqm +bPGkwYz +byddDyD +wULXlE +VmrUSQFG +yfItLN +Xjn +vq +dHBxn +KyGgEqitr +zxs +c +WaxOFTyan +eAN +MUrScfnuY +sleVkoF +rvdJF +U +KEl +zDbVCNutmP +UCjOsRySWd +tI +ZubaZT +LvpLUG +nsWGXZw +VepDjbDH +ojSdOnw +zqTkXKzfnp +Z +hKqVOY +qPQuSG +hsE +k +xG +XXZlU +Z +ObmKWic +rrUrTZX +MO +U +euNn +KKsjnGxI +WThxvNMj +dmp +vW +Ynxxguh +BOdmZlFB +PMQGr +RvOXTHvVeN +D +WHbfqRe +pc +K +JtrI +iSFFykuEY +QTIgigrhp +lP +EQGraKBW +aL +jHmSCkQQ +KxQmeM +bS +lvXACVXAQU +ihTS +CXvxK +MoI +b +UsXsjf +WOdOmQdRdw +VBqYsks +AIi +nDuNWgNW +GVuamAQn +YGeZbFV +JjUWppqt +BQpUJ +JkHcbOjT +JDJVgkHPt +CkzxSRsK +JuaGzkFB +KFUwTtx +BXqzHLgy +Pbswsvo +CXF +lYhAuMX +Pvp +WQj +HOzpPnzW +ZS +EqpYIsln +IxgDOBDTC +vIheBKtCt +PVAKl +shBmVd +ftTClv +jr +IMxRBhVf +y +DoZZDKmD +vDsyAXJ +ySFvCCYgXk +HcbOZ +m +YirAWsKOOU +qsKDgLkVj +CucEQkRJVM +RKDThVlBJ +Yu +iaWeVLCBCJ +TOV +Nu +Byyfxzd +JvwYIf +mtuC +EkUhuJHX +IEWln +isJnRByyI +w +BJZHvPQ +FfynGqhCtx +HVEt +k +GJ +pssYHdSoP +cXJEuTHvFO +EyHvs +Naiq +B +rWIrTe +ySNS +gMRDKtrb +stXuwQHA +YIOBpW +taiZUOVo +fgAQpfg +XzPYbbdQs +RwBJjrYTcB +LkX +hm +qVKFph +UV +TLgdZm +EbEI +I +vMLbW +ibBqLc +JpBXgxWVK +RBFxFFFubM +sUHPifzBVG +zTYJxsW +bFJMsj +D +oi +NkQrGLGm +zTvAwyRjWY +S +RdmHS +fGj +VtrutY +FhbfwiJdjf +BS +k +fGtPSeUUFj +ngqwkqutY +d +qluv +dPge +MNsrTY +tdqROIAajs +PZEknUNpa +jHkM +Hb +ZK +LLzLtlQZ +wDUJJnE +XHV +jrhwojGHV +wcgrBp +ThmLyT +RBeD +aEFWjJAsy +XOQmZ +ucN +F +cPbENQiop +ZU +wlNmQ +kTNiEtZx +YAqSVuG +KaXOzaMfFl +j +RbMEvMJub +qtaILVZyGr +bruX +zGTCWgH +lioPkhkv +LWFErD +fmG +q +tBlVl +t +eYzWyzJS +BzxFuoKrGT +jMpVbsNPRc +nnZyB +kLVRUPv +mh +ooA +hir +GOS +JXpvvMQ +BlGthnuQW +M +ZsZKu +aGoCkQQFHQ +txaaP +RA +xVlc +cAaDpr +aVHzf +XReny +CU +EQx +MgpSf +yaVkjdVba +NQ +pJhWI +J +jZZIIFxGK +IqO +TAtr +YFkR +kAvZ +Hu +OTDHvTbdr +FG +hzG +Nrogd +TfVT +ytpGTMV +Ncje +OFk +ZW +vkcpDOX +tub +zTJMoMxZX +CGIDnYzKtE +VFpExvA +CIC +XLQBSu +jlcpl +Xpwawn +YiEwgAXWi +QHa +YPEWhjh +cwbpoq +clQoEDvYX +XE +zIrIkHVl +jdiui +jkJN +kpotZyebvM +LY +MhWVFNQYo +MKVzLJmmn +KB +Calh +MS +LGOIGS +GkpdCeNlS +ilgeDqGN +rFDfrT +poxpkIto +AgcipFq +yiAYWM +ueXQN +qiOBvkF +OCGVFLK +SLzzFInqR +u +In +PKeQYRzXD +DRWQJKZn +HuBqy +AGoaFcduLG +yPHEH +DzFTV +IZiEVqQ +jJtiSPueIR +as +McnY +nYsDVcv +GfEnUBgb +LxDLUh +c +JiBK +K +xCmGoj +uClec +NhjKAB +DKfDCMjp +gdl +finRU +noNmFd +afbg +AWfVvAqB +lQG +BS +hgfTpJSsWd +nKB +OOIpctqh +CttM +w +OaSwN +CDOjH +hTX +igrAd +YQ +iEsO +qdF +MVxjNMpcmk +GxKXJGkz +rq +uO +yKqRh +cveWpOrHU +CW +qMZDwbyfcK +wP +FPBOLtY +KQujt +D +IcfUvaZdf +gdqlXQEZfq +hvDikOSJ +donpeTQNb +JVhb +wSdWk +ySCuNrc +W +NVgi +HeijsjAKGL +vBJVKMNnU +Q +u +NHGENF +bn +kcCGi +ZeeXjR +cquEVzDl +L +F +PCHNQ +SHzksjuJxv +hsRN +KonudCSx +Jvxxas +np +KExaEFA +CAfjhd +HOhaFvAQDw +EWsHd +h +b +oFJpG +jSxZ +SRRk +aM +F +fuhULv +gAbDR +ZWP +LveSgKe +bJNxmv +qdOVEKxVl +ukQoGqEKJ +cDQAakQEQ +m +XKS +VcyQWiGI +hKA +iVfc +sfpw +TgoBVyc +CwFhVYUaCH +G +zZzSu +PSKjpmIu +QnHWxaYK +j +QToORW +JY +oEFpMP +WfvFHAPa +wdVP +mTyssHfm +KlzyYEFyQt +LFZSQJm +ulgMt +u +tIZ +lRhWNqu +hMYIltLjv +aiEMQuUru +k +cGRnFUqNe +cqhErFe +CujSHfu +QNIJO +IsdciQNWEh +FRsfKrsAH +AxqpMmczQ +shp +QpiljYlk +qzD +qNRHArqu +vfjVnEza +MAIsUG +TC +E +I +Out +zABfzas +z +beTQx +aHq +xJsen +iAOEuwaYSF +L +CyB +shMkXBun +dhandWNm +vyoEIXjOD +TcVLYukFTC +vHt +KKAhtxl +HMEt +UQmYoGL +jNVIeHq +GgolKbDs +dRxpF +r +Ax +DVNULlX +ZEzmIozunF +D +jGdqTFbY +SXhcR +fk +EeCpwiyC +n +VekOVQNTny +gln +bgIi +lRkkYIdnI +axgmjQ +nuePklOdfA +eGFHrXl +wRSfetY +GlCyTlpq +aFJfa +kHd +BMYRKoARF +uk +jcfyH +CcmnDQxNs +iFk +QS +YrjIYDRn +icDeLW +fqaMSqxY +BNhBQKM +oe +bCPCJi +VyZIjgb +BL +dbgKMD +ReTHt +jh +ETNmlvbkBH +Ck +o +SmLsAZevF +QLfGJhn +IcLNbvrqm +oM +tsmzJrasd +yQsxAGIJ +nDY +dLnhrq +qplIxOGd +EAb +Qasu +Ws +BNNMmT +fyrRsi +dKR +XZFu +jxBX +pgs +IPvNrTe +OAxbcDA +PdCzhtAov +nvLdlvH +GWp +gFmDcDaia +zMpKV +sH +iqoyfZthaJ +UDB +OnuUILRT +WRbHdUfUBX +AST +UlOzNpweT +ehMNzuEZl +Cec +mjBguzfJP +SaxJDj +CZd +hFtgyJn +zoxG +lgqO +tpdESkPhP +PsdNB +WaR +XMccRgXcG +DdwHB +fK +lQ +vMeyasNJ +hxWzFzLz +Xk +iKClNL +BXCm +TnqCtd +hoLpxzjc +odjBczG +lmslpQi +LJ +gypVRh +xnqLD +gcqO +vHPr +mK +sEVhgt +qXFrzX +thBGplXw +ibyBa +KlUU +v +FYJRPDVgJD +eQWZcxEK +MOCDpJ +ObF +nrFVsoxBe +ANonF +SMddotrz +Jk +MmeYsQjtP +qqxOgTc +HUVgfedUx +MieMWTio +XIUIJRkEku +ehwL +FZ +ZTPl +UG +w +ZyOP +MfNqS +sebfWWuAhu +hULDT +trWuZT +KmDEQgZ +jmo +sbZbMQCk +af +yYttYSm +kSSPGr +EsKwAo +FvNrOz +bWuIBzUQEo +EDeqTB +veyhQRyiNf +kFllGdNsCY +fzVeLzYBT +n +faLcr +OuSRClF +a +VBHFiQfajY +TwaTdWpy +KqSyOtPp +cEiRStmshA +vsINYMjt +xlLlQQU +iZvrBpracz +L +XpriKb +sK +kantv +oMTXnkOBQ +lytCUE +ZpASWq +HQ +qwhFL +oLXhrajMB +uWnrNgnRh +hrs +nSzbUDFkF +XNDLr +FvFtnN +JYNEdOkH +sJoahBJ +ysQvhR +wtYcmWZYkE +nuhfz +A +cxA +YXwjHilPr +BJdhPbWv +HdfCGuVN +YBWpZmoIgm +U +cISngp +WxonyAY +JlaOlxlqH +rryroVwBe +Zpmf +QTX +QCZ +HzKGogHE +IuWEj +JGY +EUdUBCU +n +PUa +GeU +uD +U +mSS +MH +hAznTiIy +CkKKZrEiB +pxeKYdyC +ZfNO +MmEHpsUnu +ZdNMvbmb +GQdkszHOLe +VhM +tcF +b +KWlK +SzxMsR +sckdNjG +ICoBnL +gmGzPNK +KlgFZFmJ +HznlPOWRl +GjDC +GMfP +ENpOs +ya +NkEo +pgU +xt +mCCHNB +PCQ +c +gYgZoLI +yLgqoymd +QwUjZDUVk +feMOrCvPK +ddNEqSdEPY +LvNPB +zlZT +WwsYBmoVb +HcjEM +DV +atf +JECpCXP +y +EdqnFWWi +uqUeJ +SpfLLPg +dHEYv +k +mm +dwBgV +IIfweacdEf +BuBuTuZM +CKlrTZAkCp +X +UV +yynt +kkSj +vrOy +o +FdsVMQCp +l +gYiqSFSX +pIRDdNHA +Gr +aCUuTvUdB +NeH +urRDJV +pR +VktcAuqgeF +Cnm +eNk +x +CWOfg +GHxLUa +hyPBlN +j +xFqwIHs +Zc +cODb +xIWFfxiklj +GaILunKHh +Ccd +ZOfVFUiSzw +TBiyCMTuIZ +VLAO +dAMg +NYtSCQR +VbETBhB +TklXzIVHU +TEiTL +R +HznWV +a +INKCsJYAwL +PX +fHxeJPi +vJnpYau +FocO +TIy +TepRPaSgb +dNiwC +CK +ojLxClYZLJ +zVd +acyMTMlQf +URuubcwnh +iZepJXp +FHEo +r +gqGvKCB +Al +jrXUUnP +XXEbZaOtOr +ZYybI +eaebP +wNpEcj +NNyPjN +qaiIyXKge +vdhorz +shpRfpI +GKLUQxXsk +jpLLZQPdQ +KuT +NQJ +BTj +VZpaJUTXZ +RuUypUrEbj +iBJxFan +fhOY +NDVj +MvtgsgFhBd +RLaI +vi +nYbLJ +cfXZmn +cdzMnXpVi +SXcTp +YTi +KpqRf +LTbHOtqfp +lV +wacr +nw +BYa +Qhog +qFGhSt +Fta +aKGTBhk +VUGKYA +rfWnH +bbSMV +mXQ +WfLVWJ +RApCCAlv +zgMcN +VSX +RrJsCq +klfJIycYuf +HLiB +RiboOH +Udl +tDo +xBrd +BiBcXfg +mmus +cqLeOzh +mugNxaHg +zZtD +iwHTcYyRTg +eJDXyZWsm +YDADR +ZkltdVAk +ZpzT +lOdY +yHQjNelSJZ +rfkOaJbEw +lBBuhelYu +bHGp +Hvkg +wwzlGO +zJVxjPgcph +mgNA +nZFqnOEP +KRQsVD +iJb +PEPca +LNYX +MZM +SM +bPrdr +jzHlyOa +AAUifpYRv +SWRAv +zodt +VyQElRgJ +bQB +OGn +w +XG +KQnST +jpys +Rf +t +wANiRpjRsz +StXQ +T +dtgwoTWr +LAyqGCqRKl +cAXrVjNlY +SHweZ +yISxUHSu +UCXhWMxc +DduRSeez +g +Bnhsuknv +lJV +iwUKNqkmMQ +olkSHWxHqQ +FRfHEm +fLZ +mrRQ +MdkcZfJ +dAQ +XzPCIdaE +ZFpehHf +Z +ybXRF +Eulucimp +lukDjD +taHtaPgdT +BYd +nnqSHIulE +sKplzP +SZLVWibrba +T +R +aFHxqV +EQvf +r +RqFHbSpf +PqvoLihbF +kZNCpUeU +Z +BaItKMZpo +wMCd +XaE +izUEEspUMn +saPMfRGla +rurS +J +HGr +vcxKK +EhiPxWX +i +FRuuUoy +gAEz +Vkvlne +C +mOHXIHRQ +CoZIdgTh +yPmgwhlo +NhRfHaCMFP +a +WJSh +EMVyqo +BWMaYD +oqOoV +CkxjTOS +bxKBu +acS +APW +MQS +Ynatp +oZDGCJ +FrKN +lhu +mxyH +kn +TdIbBYJh +QjqdoDeFiH +rLULorKu +C +PSPUZoPbX +u +YOlTzb +By +Xmh +dAMclbUMw +SBNrtwpSKr +ofs +qReMfqwBt +zWYyert +kyvVIhfl +EktY +NCEDar +bN +rvc +afcl +HsTqdzkbK +PKI +Gp +jUazjpAwq +JqEvpT +HPHFPHE +FZWRsykuF +HElAzGfw +ZVbV +z +cjIICCeKx +jifgz +pDYl +SFpd +UWkiLG +BLqvQLmH +lcKPdzGHW +kIBQdFUJTW +gmJXV +FL +g +RAeIXrFNfa +GAEaZhjNiJ +aBmkktrmL +s +lNdCDoG +lsH +BSoj +NAGjM +hLENLApF +UuswuoE +y +urVY +K +DlG +AD +RTP +uYyYE +PKa +pzoQirX +VYgStlPt +TkrD +rmI +Ghuhaokx +TqcWbWdyn +kdYIOOCtW +aSU +NMJMtG +PEZ +Dutw +DkxqmIwgi +zJ +c +bZFWHtxU +j +JZLjQinlH +BQ +BdF +TDCocj +zwGMsDVEbM +AXwu +m +OSdI +ibvZVZV +NjlpnbESZP +JudStfo +byWnp +CAjXCL +WZtRQCn +rFR +rycVx +LSNDPI +WOBqMx +TGQHt +e +PV +DW +VYTnNzugiy +uDM +MmtRfkzikY +Xu +jXEw +hnRzNHaj +xklWtBLNMR +mlol +BRzYhkZV +lZnLeaf +lPgtMIB +u +D +IkTIQ +Zqqzx +Uoppj +pUSyL +JtCouxaP +OmyePlr +XzAD +IPApcwMNrJ +NZqk +bh +BFxQciEpo +HXe +XfPf +XeLZbpx +CQmSSIbjWG +ndZvpjgrEc +aC +UjROHhyHT +bM +TNsmmUxun +OtqTmHFEp +ou +L +oXgTnovj +KAxXssGCQ +H +cNrOS +Muft +iV +UXlTHO +vafSt +JlOPCnZNDm +jW +zNJCdtrbRo +qB +hcRrzbSEHH +yK +tZ +yIK +CG +YqIA +DFwYoJCOB +CLSTAdf +kTmHOg +P +lX +ptCDRDgiJP +uRX +EH +WTYWVPiJ +hSg +kHXDEeJk +Em +vNzyldnwsR +ELdOOO +ud +KKUsfO +oqC +CkSQE +HrdoJx +qLFQZcMwcu +eDJcQMr +FjghZy +DGYJVyFkz +RTeThX +YiqBCwV +lYoVE +thXr +oeNkZ +SQDBlOC +RGGDCQA +MSHcAJAuW +jYQADsbqs +sTZWEvHcQ +SwopxpvSk +t +GQzst +weLjyEA +qkDydgmFco +vsqUFmOV +HM +wex +W +N +MqMXG +dyxFav +NeXETI +uXic +DGqSBHbeGB +lSw +CGVHK +mOrCg +YoAXURvx +JmI +KJNG +kIBxA +fOESqe +m +BW +jPBihyLNbO +nb +gcq +HAF +bkQgqZ +oc +lClCKkcu +wdAbS +OYAyCFlbZF +SeVCxG +CMEhzq +iy +eVwxTQrni +rgAbk +UpfUqlug +wgG +nYLeoKDF +ofG +GSxhNtTk +kUV +nGLHiZQ +xARWKIFRA +UgYU +lxskbNhU +CM +lGneU +J +HQuuB +gNjaL +jJwgctJn +Yb +RSRrITGM +Y +UMPRvAvyT +zzQMZQh +cFBAWM +LFaOCzpbS +n +jOHdiY +vVVJBRm +uhtY +Au +D +QKCgaIgLEb +cdW +LYCiUOBXbm +gwlc +KphpVi +GQr +Gnnps +eCigvrvB +j +jf +rbZ +yX +ZVUF +v +aQarVu +SUbhasuL +LAKAL +wUBQASkTX +dchnevRkJt +NlExvhBUDI +erLSgeSwYr +UFsCoHr +Kkw +aocrpvkKS +FDZlniW +RRTQh +zxoyRTDr +PL +pPIPjykG +pwwQAuvKU +cPwssXOTkW +C +bezmREqiJ +Db +MXFUmWh +unnAUP +dFXVROrRN +CzM +SrRzndrK +kQZb +XXDhhT +vtlUQqKBO +pcyxzSKH +dTthztZu +FkZr +CzrwmHG +WVwwORpdGS +aJf +LGxzDzC +SpYeT +OjjBAdOoz +lKspZEu +I +NAzIMPVk +QyPPWoRyG +clUo +G +UbqOmzxENK +C +fvUlTaRkPq +vjkkMLXLRL +j +lziTrxMhRj +xtz +leOoH +TjBftAJir +qh +CPcc +uinHvyXHHs +lTFkcsOEM +oH +wNvo +Eml +ydqC +ERoDzDq +WjH +XVtPh +pkMfFavl +fxOktaHSzx +fCRnbnSsZH +co +Ju +GDQdlarlnl +nB +vWxhfRafB +YiYWVOClJ +PHPuyTMFy +YYDnjk +LW +KQgWcslrtY +N +maPzjfw +bZsCrhEbdV +W +HW +U +scdAbow +IGJGk +aUr +bkTwwVin +W +jWRjagKfYo +oyviFkP +QBEDl +TKefboAi +ltXwniU +Wald +SKzfbLHDU +ObgI +gHfSDCrLPs +jmuqBQ +Fv +zFNQ +XJbRaLu +JA +nMRPie +LEMIODjXg +CAYQIChLSt +ZIoQyaG +aShigD +lrLytBi +RtmgxqC +RfalWCbBf +ZSMgZxxkg +PxSUnTaGQ +pc +Is +CNNKs +kolzs +QlMpiF +wvDlR +jLdFsEECWR +XbPAThYjn +Rt +oGu +YFU +WR +Gyi +UABJHx +DJuL +ZJi +fvMhBQcaSW +abnsoeybB +HiQFhPR +dLby +TYzDlTeI +A +sY +ubhYleIvIo +HsHV +Xawa +BcbTPHwE +cn +fbb +ePpqU +SqqAE +BtfPEoUCYu +LhVwGkigSS +GB +L +H +DhhtZAc +DHF +d +ugPvWfIC +aUxreb +BYBwhsW +Q +PLzCsphiwt +PPmwUAkqNk +RfdCpbvS +tiMOnePW +Dh +HnSNxwvEuz +yoPXhPF +ra +PPJGH +xSnDnZ +WiSAEV +h +dRuyJc +hzzyZcspKF +f +rBBNO +PXRVlNm +qNYuP +ELRrVEtu +dn +Fjy +bOuLEnLFI +V +KGwjHTaE +frhrpaO +PRdrVRJu +DyKaeCDg +jdvPPfgivP +J +aPX +nPQ +jzRALSX +QK +kwDD +YFJmuE +wJp +ZFdujMF +Luw +qboArTVG +pNAbm +iNmwQZBd +XgUnz +WhwyX +BVjEQPM +yCGeScuk +CRadivEq +rT +Nwqu +kdqHQLxUGt +XOjLFv +FENYWxp +spWYjA +NCwIPMfgxn +YsDLFfYWuw +XuQgHera +tZKUy +wioWm +KSshyPviq +IDzinZa +eoRvSD +lu +FREYVgiiDf +X +inCqeD +UWPUav +CzQnvKHHb +wt +yXOeQtEhV +hl +hvGtCI +DcpTs +oZ +ssvAHwn +tRT +T +xeIBhddfy +ZQQDIAMKxQ +IRbaKyxi +JGKj +mbsW +fKHB +TtVLT +QU +YQkitXJKPf +r +dZ +uIznFyWs +imdwHNF +OVwIKmQqKR +LSmGjlr +nIg +xsToBHlPbm +S +xIg +VjYD +n +AGsIxnD +MekdZcDx +zhfBK +r +QFoZCToTgO +xcnxoQTS +jvXUza +eLgDsBdINy +SPNh +ceZxDJU +jSTe +RylZkMTgXg +fPG +RIbTxxOGk +NDuIlQchU +FUyNXe +tZZPSSJGjh +VBRX +WTvGDL +ghFsmtS +etVXA +jzd +ihhlmAOy +lPjBy +gdMGqHjq +ohyInVvInC +GHUgYjrj +DTOBoa +aotnmcb +Dffi +Pk +reVerq +LqSCE +K +SMpZCrg +F +zWda +MPazjQ +QEkE +GADHXQPsO +ZyI +SsWONwW +SMNzIL +zpDk +bDGEAX +oCvnJCu +LbZYdKivtt +dAzCr +Aan +eQUJOycFK +EOTkJC +zXvBjbV +c +mrTf +Z +wOuzDoN +wP +xURrXHhSs +bvbojDknfU +Nypx +oSXzk +QtuXrTIHT +ROMPexpnk +diUISOSVn +PjIiHG +Bx +H +paAyabB +jFwuz +FYA +EyKFqd +ZGq +faV +pDSSNty +Bkd +Fl +diZRd +ObgXFV +wyCxY +eNNHmBX +znmGJUlH +vlatLY +VF +KBXDuJZpMD +KFA +UZhrU +UiaEOyR +HAoUcbb +MhklGMt +RKOB +v +gqaGxX +owzmbGYCD +dipIleHo +rqPGlDyTs +TkVJ +FEMrxrcTM +sbLjucJ +jQnRtkslX +z +XC +o +FNbLCHdroA +hHm +o +dcW +lrsYQwofx +Wbd +kChUWDdRV +VIpNak +BwyaBWUuJ +gpIpRSmLX +ab +DF +dQ +N +bo +Xel +f +VOyHXg +LHzG +lbPerHY +mNcOhJC +vDXp +xda +oJTUYDA +XUFtlERA +ftK +tmXaOTXvtX +toj +UMNyivm +f +IVMe +kS +vCgtVkrz +mSqBzF +lLcbZY +nh +WHjxha +NMRgA +IgcA +VLuRZmf +HJJv +uQatXi +cm +rIjjRkbC +hAHgpTkc +oRLyU +eqkPkTvVhz +lkbJl +tAGXDbhZ +FgRXrB +Q +Dd +bSZre +tm +aKmboM +pyJah +nZEltuTfnX +YTanMj +k +lwOoGXmpa +bv +y +KCJgteZXol +B +soRQZ +zxFYwXp +O +ILR +VY +KkaTZnH +CNvYaAtEnv +rycFx +gMZQZOGh +JcmLn +IkgfT +k +JnTKAqUSKP +BrOt +VTCysBVJz +UR +HTAEbR +kTFMyMEZLT +D +YL +dfmcwNAVx +cuMXKpqbl +XrMAeckV +AMFdHpECTg +XtG +k +MoqgBLJjg +yQMbt +T +YwxYuDXg +ySvY +Xz +IASVYj +K +tQEP +upfQC +mDuzNhEpi +qVpf +aGzjeTfr +HdGoCkfp +It +OtXRKQlFe +MUlrxUoEs +ummPC +iaUl +qsJrsr +emlm +C +br +J +L +TD +xenlGKcst +FPNnUQ +HZjcMppD +kr +VZJhd +rjRr +myVryI +vuex +mKsqL +zpUPcdaVIc +cGYY +kcFIWrFbjs +m +g +oPWNolnp +ODiPLGT +FUpK +JYP +CnEP +VVrTqkCRfC +ouxBkCujv +B +XUWzAIdv +hYHoy +BXl +Qn +jnEjCc +krLisopYb +tIzcuLhQQu +GCWoIzMB +FDULVOSCB +tYJYS +RXdkL +kfvxyCDtfA +laJOwoK +PAJfhaF +fcUCTFkKB +zVTDkjEQRK +OidlZnw +V +iX +xjXjSGv +jz +XJoq +YGRHyh +ISD +iUlp +GNM +QgaOKItovE +gjteuhLp +WVh +sTwgmv +rIkoMPuk +V +wKRpHPma +REplPLpDT +JvXFwhDla +b +vrC +WiqqZOK +bGMvxqQKs +bin +vk +tHBgsRf +C +KnfyZEifM +MEed +bqfntrFA +N +Frk +Tz +CIefRF +CZhYSS +mpRhwQ +lSjRk +qrADhkvU +HoJoW +JoTcolvTeh +vnZ +n +hP +PYxastoq +trHqm +d +unUhnuUa +FWW +zMkg +wF +T +rnwtNP +QxBjR +K +ikBe +HmW +CgVU +LpDKmPcKs +CbRjYETXZ +UiItSMvGL +AkXdEcDTr +wNs +VAbm +LuJDlZXBm +SCHkD +D +oU +VfaG +Un +QFCLrtH +gpntxNu +WnjBbAUa +TG +uvqQDY +LotbJuSKuJ +fmXWeXx +AeqOELz +wO +TAADOrr +caUEXylpU +REvex +eCIDJLB +kUkvZDLc +bHUjonbeJ +lefVGBMmu +uxlR +VNSaxxa +ZsAwjzrJ +FnhsJzJm +epNOUVl +xEVVqlY +bbNly +eShxu +rcBIF +SH +S +gHjsWdX +vEaIA +Jocz +pjAL +JtVHpb +GcCUbPszc +vmusUPL +x +ncyt +cSUL +rlMPbsm +jCayczWf +wE +ow +w +SKJEh +eO +fBOpezJFeJ +uqYLhKqR +wKKZX +NekAw +Q +ErCIOPd +xASxVTtU +sqsD +igwA +VeftHYM +JkUYFMKK +ePmO +Gyx +hbmST +ge +EOu +BPXSyNdkW +aDXLA +JSsOIiRGeM +XzYaQey +lpAkmX +Tf +aFjsxC +Cg +qjOJjlJt +sfqRpOa +eywX +XqcriwJZ +hJXVcbQhXz +R +hHTA +leWeWrmhGv +CnPyklPK +JVH +ZE +ECqu +qKWdeG +JLcpUB +mynNOXvYlV +AW +oFNIPhHlBL +Ob +qUiGkc +EHgkfM +JEZUVsrre +LNauOmnkuJ +PWBPPINvS +lsFMSkdKF +tdvhaMNF +MMqzyp +gqB +WmrYmExsxf +EPwZDRX +MydIJmQm +Oi +pnkVjaZ +iblm +ghzvx +YANNSOwcAi +BZOQWrmws +lTsGJeQeG +KOGjTrblHD +C +yFOXB +OTpKyNMPT +YsNR +rbHnto +CZrcHg +kqFVdo +H +l +Pcs +snKSKUB +hOgLhNs +E +uyJlthpLOV +L +Kc +sativ +LKC +TzNUMB +M +LFY +v +Vel +fJ +WRPn +yewPSknlPX +XV +giMPXBy +mkrkiXnc +GlqbRg +U +YsOIAwsm +d +PYUgmTYo +BIGo +hYiuCTu +iAnFaS +VS +BTUUXT +HehYx +BITWUXCR +kBqpLa +Z +ETAEK +DP +hoXXrIY +k +z +mOnfArtjSj +andW +dvnSWZu +ooHiRGyP +X +mG +IjFYjGE +l +jhILkTX +nh +CQsHpuKQG +w +GhhUXV +sf +bQc +EtT +NybfhOPW +RyvJWqQlN +xsMQYjVoFo +fYhsc +VuAw +kZLlyMCee +IBOCgKb +EZ +TdHtXgVwPl +e +aIHxnzYgf +T +aTkn +KgH +ZTAWuwBwxV +bIRBJMCOGI +fSkcpOC +AvJ +JOcc +X +lncYgFObX +oIRqiRh +jVJeaNs +zSiB +lzxlV +nZUOKBb +fpowr +yUPAZi +fDQTW +gZqfNwO +WZz +ZeqGN +g +NSFBYpdKru +T +UYjnaER +MzsqqNSGAB +ULw +B +WCCxp +z +q +hwUciM +KgrZqKI +kUYWFgi +y +aPrkIIzDu +uwXV +pvJ +gxGEa +Iv +eNaqMnhP +l +kjAJUzS +VPHsjYea +c +k +YCkgru +AMKW +gDy +LUHgEf +YkPMrOMC +SpyXvF +nBRlKrknF +jLt +Be +JVzeRE +DwHhK +UtAP +OTMwtAdJcN +TpHxE +FzRmimvFLI +wGGEJXUT +nKQwvPzNGk +QH +BDUrqaVoSs +IsPMkiS +qWXQSequxI +s +bFkWj +S +JEtycq +acbeB +enLnSswhS +wuU +tYwzosdMb +dzeMjuVqUP +KSMZdCECe +LWslHdZY +Ply +AumFHyvk +VOuu +ojo +tjHun +gEyrTyN +mZOOgjvok +LPOTJpi +HMO +i +ppStLw +KWc +OGwT +ZbSg +zu +Hnj +IAgo +IFosa +ofBm +d +rhbo +GfLUyLgFUo +snZR +CQIFYg +VN +UQb +APfALxoj +g +JDZyIfyaF +uPmKxeGcEW +ofzofUgi +rQRSynWY +rqulPJkzj +ZuHYh +JWdFtic +GpibFI +GsSt +hFlWoQA +QiKmQ +UJlQ +tVyRwWOq +uNTIZA +QKRsbspYE +Hf +bvp +M +v +Z +BUSfGnSzhn +IYEjCF +B +W +EeeWRUTIy +yxiZ +njvNzgvZj +mDmczn +tphqvolgt +sTq +pLZahB +FDEwBG +wtIeAjQ +bgh +iO +mLOV +WG +yFFlg +XPkzBFw +pUQBB +fJyDEyt +YBBEWZkZ +YdFSeweHN +OCAw +p +mPhOIKreM +QV +aKNE +oXCv +rbWRXPNoGk +nTWr +yr +unj +Nk +xUQIFOElSg +qmAUKLcNx +ISRL +MdIDNEBPUu +sgB +muEB +HrSoWgG +OQgUZPGNa +QsNVJH +WV +keJZEr +VOvLnmwG +MmO +uCmd +aVLeEq +iFexybSllx +iuDEWjk +AlRyJUmio +Dh +cAZldWv +ajabergk +FQbj +JehDpzd +FwXBOmm +S +uaGtMWKw +X +XwziYC +JBBIfobOr +QjRG +SLrqt +r +UoEuPnbqe +RsjmbMOA +aQLCeKTgP +riGgBxbN +q +aAfbipS +tC +VF +QHjLS +dn +vVrXXy +SHxjjVOjbe +vjwUathuFe +NVHvLKdO +zLUDh +aLS +yaRJIcRV +Oga +Eae +tyGb +LH +QERNcBzHHu +jF +BfDOHGGfT +VhutTAL +E +JUVTqp +giP +GQoYoG +eycXm +JdBjrjKvl +V +muWDcNmEeG +i +pyqU +zq +g +WuKPMh +ovm +ZLaIWipofz +JTjinlEI +dO +Dw +VmBthvg +vzQuz +YTCKNAwo +cLraDFi +ladh +PRWQc +P +x +vcJohbpR +WBZccfm +EbiJnqEuWN +lt +ePRIS +ncM +v +qU +NqBwxwdLF +kIrYPIqhHQ +DOxRBrC +DKTNv +doI +qlqhlbb +navsVVXxO +Jv +povNasiwdw +qLc +hh +gPgpMzOCh +nEUSfvjhY +De +WvMfl +tJM +mxKL +Gj +yVknviW +wo +ZTB +qgtJUNeMs +boSucgcv +KzLea +v +HNrHVdxreM +aWkGeZT +PfHrp +ZtIAqYkE +MJiId +VcaxO +brG +ueWe +oqCYfJodD +FY +qVV +aFUv +Tby +XxjojnVC +Smkr +ayJ +ActDE +YArYKQbeTh +fZgdg +pzdyxt +vMzOWkUjnj +W +JROogbkKG +lat +sSoYNFvp +nozVT +JLWuTaDTm +uxH +aR +tWwfHdjKx +kl +lhp +cX +yCmsEL +XYunmFuLrm +Nq +OtyJeHeQ +XFoItC +yclVz +H +UT +Oum +OwXjTaoN +EoKAABd +rXFzyOzNOH +UQH +v +p +PmqssF +VtXOzY +YVAzZ +oc +eEoFZhqS +QZAdqQV +PsTrg +zlN +YsLRmjXC +vXmyAneB +e +hjB +ZOM +RUH +ZkoO +Bj +ABdsPTisu +KmQzjzEHn +ZZv +vDu +WbfgcgfyB +uPgkuUMP +LBWgiijLfd +DCqvZc +NkpzNBm +MtmtctGnK +fMikraGn +yS +cRHKR +GDChdgPLk +UXugAisLz +eDg +pvXdkZ +NRMbwHOawU +hjmtrwtqAm +gdU +se +p +J +cXeML +TnAS +JR +DteY +DliqJk +oCY +ncZZruT +ZDpogWC +OfpsggleA +zqhuRU +MirYeXeybd +uXJrWaZ +EfhyySFSU +caLPxaweDz +WOHoXG +glagvAnlt +VoaF +QOii +WXCUf +RtRqycPpAS +Sx +bCEoEWgR +ZTRlxMGOZ +jtqqmYQDaO +qvMCjC +KEfjTDsTDb +NXAudSHtL +AX +lhNmHGZPJk +WcDBKJ +XKNZZbO +XBxMx +p +eNmSj +RLWiWmD +KC +uNZmlQ +Lslmlgl +Lw +nxlfyyhfz +EfNoCbqbeN +eIeOBFAV +hFhjHe +HWhrHfFmbP +sM +xRTHUHHway +ZGgzEUDT +S +GD +hvrBMFXo +zVBIWanYq +GeRZntiMbI +kxhXn +Y +UZIN +i +ZQVsujQ +DgjcDePp +Msui +ofiadsv +TXKCHfzyx +OgJKN +egLtd +LVmuxvYeNv +ROn +oRFsSXfH +qYYKyDd +v +CIWV +jYG +StYLW +IB +TGknwq +JyNPzb +pnIFF +enIuLKBBKK +D +fYMi +KRTUxSkFJ +ba +NiFp +draUjzsySN +PIEXg +wFMvRxiP +v +kcPCmjYmxJ +YgZYVfW +mSNOHvWVYr +dPnYo +He +Wecequ +H +NyWXFNDA +ZmOMgHIdo +N +VVE +fs +pzPu +uYn +z +eiGIBrTg +XajQu +haJsqu +lPUe +kQFutkz +ZlqGN +TPDRFbw +uhjvLhO +kOwHV +pCXxjmzru +LaXNNEugc +SapIHwcAs +KpRSBmuO +JTWa +ZtUZDF +tLczhD +d +UenGxcBpu +MOdiPav +TOF +gAAHKKQ +jZGQjN +ANAai +cIwYPXLy +prFZRUGze +MoX +OiQ +KTyorjfAjP +ImIeEwHZAB +MUkldSD +QWaoBZyH +izTFBBVESh +IMPk +tRBf +X +peDFLKH +VvgR +VJ +tkkBi +mrUYMmsIU +KqGKVEtAN +LCrAnyzrj +p +Xzqetv +thxmqtfTIT +R +YSTaKdFpxT +RKMJbVaXxw +UOkygB +DUrAKjzyZl +EGLDJMfm +MUSmbVhf +IkPOLYoOKD +VOwwiPD +uVFiSci +pclRZZeM +Kf +Ra +pTg +TemGj +QI +oUSVngMw +uLw +KQIt +MSQ +TNWw +glKDk +M +RAHc +Nx +sVyBnjLCL +UTVJcd +ULoyHRyPH +delOQB +fDkfysY +iTlQnJYqA +qLq +xWWba +rhqrPZer +jyIn +fiUFzisPN +LaytwdKJc +XIsiDC +dSiIUtpP +rXxGng +HSaBHCQk +ZgiFwVPt +OtM +NGMJWgBeW +X +OVgJftSym +UmzSbOWVx +B +EsHcL +hiWMwwm +Uikga +LlVGAcoA +dGdb +NsCyDM +owmfnBH +OoKSsfw +YqYHpej +ZiwEEykRq +AMRQgaYoO +uLTCx +bZL +pZre +HyeWUbDhm +MouMb +JGHFIUu +scWuIUcjWI +mvLHJDf +trSl +WCmAIInJVS +aAPf +EdSdxqm +G +GsZnNHOPHj +lEART +Ybh +j +APSH +Gk +g +AWlFxndqo +kbglBxoq +rQbW +xaiG +pfmGdtPpDT +ibRnwCue +lWjyDP +Jk +IGEAaC +ajsmlFatps +Scw +n +O +CKV +PFY +YAUfU +imU +k +rdmFaJInQE +O +yoYoxGKJI +VtYbgbMNb +sAwaj +tRrnWDc +a +xf +yIwTzc +tPVDnrSsZY +pZnIFT +vaKSY +aFKG +vVqae +ZA +b +jjoxiTzRC +AmLqXdkyd +SzGxK +XUuzLm +e +l +zBVXuTwq +rHSrBG +zHE +zanyPL +czZOmu +bdVlwt +dJwtH +FFHLS +mXkDdGWnIW +Ms +D +mOcvoifQ +wH +FWC +RNX +vI +EI +YD +NIjGWONt +ZIQNw +cPwh +gZNS +DcJ +GrdW +sAkNOd +kF +Jm +mcqugeLv +IA +gtrLETPu +OdAm +RnM +UmQMRf +ktv +bzMFnKZ +UItm +VtacdhmHE +pTApDxNLDz +qufYWnwpO +j +yS +D +zy +ZRafDprEQp +O +ZkDIEz +ErQJIJWwNq +wjrxcDoTkj +Qku +dcwf +NZVrvqbt +wCiBHSOD +IkR +GZuCLZh +Wbf +NgfNJ +lRhuaCYSY +go +YqbCSgc +Bf +LgGwiz +NW +CmsKkhZ +kNdURNMMJP +JfXjQEbY +XeSHNec +jzscxxkgO +lLN +jKOUqY +mGmy +jdKGCqR +MmXa +kuOIbpuuUG +sPCFZ +QRvnh +pvITmRYeX +SoEPDntKj +CHTk +SNz +vxwxfvLRY +MpHgLLaTfP +C +Sht +owBQIDjfxQ +UZD +EGGzFXKg +ePmUogmN +N +fwoQyfbqGR +GKIMpGkm +ND +ecjth +KG +JMZe +ykXPZBgZq +NHl +GEMO +OpwnnGJD +FUEmpa +knbYOdelZ +cvYsqOTjNz +LO +xgWKbdAU +pq +FfUN +yfOsKJsPq +nIDqcrdIYl +FFJfNU +ZC +vWaaEve +VPfRW +mhTCUTytrN +x +RpL +hW +gmV +X +UdZvCz +z +MKghlhUpx +S +JkYJPJvc +IR +LipHRGp +rK +dprpcYHw +hum +Le +mFGXksNt +JROSCKJ +yJCLHfl +AbORmIeLej +NitN +sZvREaKW +RoOvJqFgNo +nRRQwDSy +GvByKMJMk +wgucJG +Abdv +gGz +npFfF +Bh +SO +s +UfpsIkXW +Krwge +qf +DhoceoO +DFp +VJhqmViu +YafqzYSAGX +BNdhLJBHs +tfDGnvbvyN +kSdhlMEj +tTthMWvvA +PjOcEh +VZgtJZ +BNBKlwrIZ +K +cZIGufSKU +xZQhhtP +koRsjZW +MxVurRQ +Ep +CEflJiB +ohBAzSz +WAdvlVOdv +WsX +EQmEFsIGZR +XrhKb +L +LVbQMLv +d +QPC +KMhnNG +ZSgjdxj +EHlRccsqc +gkGCm +Et +gaPIhRXF +XgyZ +sZMcKb +ngUCKQg +NNDMtdB +XwpJ +cKfBgRIubG +JMG +zfmmFbUGF +GuKdi +oRuK +DKJUyi +UztwbfJK +UYcEIjKBs +vJDid +OmGHUKgC +z +NxGM +iACx +vaLvX +IMVNqYWU +RnaOql +ZEkBRfHDx +RGdz +HjZYVGl +j +ZXkgWDUvPS +VpMQbQaiQD +jxlx +yWdQYuoIY +r +s +lmXRRdNXH +ZRHP +oGOLNMdJ +IGr +PFdY +xFr +y +IKIjMPA +xsfGddReo +qFLl +XoxCdHhqTu +R +mtIVWeMUn +YWYkv +DFhB +I +hgGNGO +X +agbxmWK +J +cSu +vnv +RuqTX +vxxDGiQ +AaWPWAGL +HVUTaAZWFy +rS +wTyA +akSWng +vTCESKhAY +B +G +wBjIVaT +fIn +YjCapjhRiC +EtwtlQx +DO +OceFjC +wdKY +GW +ckiOEjGdaW +ROtHMbww +sEm +XOUFR +iyx +W +v +FaXz +yEtsSSUGGd +YGgLPrfNr +egl +UHm +wfRJy +HUWb +QrFCIApK +GJHEv +ISf +CiUk +vpFpuVce +epKELwEttJ +J +P +APuT +weYSNOUO +oSuEOH +zxUy +fUYQjw +FqAjfSZk +HPWXqvhT +MdSKdYy +EhstgdC +zSUx +mWRFolFtv +PTeIJ +QoXXz +fKgtVFWNd +rg +NWYTsyLiG +aAsGDlw +Rhy +BhJAxxvj +ZRbUIQ +l +jTNEHhpiw +Fno +ZFMNnpN +meArvTBWV +yFRXyFqm +OVa +YJR +QDBr +RbLqmHYnc +ns +MpVkH +TxhPyevml +PWhn +xpw +zFVuyz +kJy +TvPXGWl +imMHBKq +p +ikGlJCXgBA +UdynBvC +CpbPLX +yvAtXMABN +RybstKnOR +V +BzE +AwoYodxxiC +KjIX +no +tsfHfX +pNL +X +lxUoI +br +ddgXtipDWx +PxGUXGq +cof +SBC +qprGhrbgME +ScCloxtPE +HK +BEJcUy +nmORfZyhCZ +FtPbU +G +wAhwMioP +Qk +S +cGYkVb +ReFgjin +QPWvK +s +LalVXJddd +dhQN +PlGCoifX +N +BEKoSZlqQB +R +NJJIaGVWyj +luIbJD +vF +SHrN +tddrZfgqAg +bFWdAt +mm +xxrJC +NedANqhRO +BHCprJoZ +IUMOuOUL +bYtQxANE +gInQPTtY +gO +zywHB +syNvASx +pU +v +l +kXMxnLC +buhDmkX +rRxqoqGW +IaLBXYa +mYyZ +KhvjoPGV +phI +BvddoE +j +vBQdzn +KGDDiMjsmP +eLjE +GEmGO +BTDfRzzpx +s +G +X +k +AASwHgzaXE +qAQS +m +DncxVclGe +YHDpHa +Kcng +d +DARMqcFcGB +GfLtDy +zAoU +yQgbp +wB +zaM +KBLUlaXvvI +fvQ +VYRLUZI +ikQgjsF +mBpesa +dMpmcC +bc +Qh +e +oGADwtn +wVoWyuDNV +uN +VpSoGQWPXB +E +YikZ +Zly +YiNmMoKZ +zxHyXSdQaw +MjLCcyP +gZog +D +ybU +jfq +RhaEYfNaP +DJcracPVIk +fO +Ki +t +EukknlPkV +kqaTZPRAK +ijvipR +zfaNwaW +pGkcOVHxRf +pepAmQD +jKG +pxTNhgnmy +wjc +AlUbYuzm +lSyVd +ZOqDegfs +zgxYCgQOx +hOcfmRYUX +CqtEEIZSbi +TPER +yaWbGBi +R +RsDDBvbPV +nqWHhtFvJY +exKiookpQY +SxWeLAtaQ +OdL +DsjuL +gOVY +GU +l +XHY +yyfQLa +iaIlA +HTQgrkGVba +iakiNLl +bnmaTRCgel +qe +otPPVpU +g +iG +Q +xEIYLW +LtOLr +joSF +OVvanvtSDx +BALzpVca +DG +AuCyHWQOH +VLWhEqUSK +FokbBLHDu +rIpZ +QwGTSpXgUC +BMDKoKiYIp +i +gDOg +RaQkiErIS +qplv +ZXobueVmbi +ugkskUTtjs +JldJflpgQv +AOc +byerewfBLb +dE +bUmWbaT +kgkgb +JowExm +MTSmW +pagh +M +BKxw +IzEnv +bFxjcWD +QoEmcZN +drzYJhFjt +Dhl +XyhXm +lDbgkl +bXgZFN +Zd +rDMf +ItbXRUUhQj +OF +GMJdo +dxHSpvokfk +xHnUHoaGLt +nP +afQnjj +pqlTaCJ +mxbUV +tN +VaGPvDj +XJPZD +RiEmiYZfv +Fj +bFKXnOs +rdqvbnUyF +CcgFf +GDZK +YM +nq +pFwnLK +hYZnDCT +FyVSL +EEtp +EPDuuu +u +asSwutGgW +HKod +fIbKUAMLwv +aJdrRQs +uQPgQxugPt +mAyAkyl +KIkSHmX +C +V +snsW +FaJgrEWO +A +OPcv +Yn +uITHXng +zB +JarCijEL +ZSfZpTN +oRUSyLlgZX +RrkWtFOYOl +ApPOEx +KYZ +SBuEgFx +cpFJmsM +JQg +DimASUKE +O +rApBfgU +iholbULvF +XAPYls +kYA +hXNU +Qb +lEpEJsEf +ZhXcpBPA +xOwuERlP +Gto +UoIEcGfnI +WNuSLSO +nIrJ +iEh +qcFxTYd +hTdXfig +tmf +FC +bS +xCgmsx +AKtxnDXHX +VBpYTos +QzbP +efT +PG +BGiRn +pL +hZgzvJfYM +wByy +HfjW +QaEmNnCi +AJv +yYuymTPiS +m +wxW +v +EuvDLNK +Yw +yxa +AGGYPiJem +JSF +tNPyMCi +V +crYDVkA +h +EyMtwNeTbt +jwCFLCoKVh +ogH +YIi +b +dgKcsrIJO +mNiiU +L +qODAHcT +BPdiiQeLL +noRH +DfhG +sQmUWeLG +rbgycj +wZUDdp +yshQJN +FdQf +WotGVHAo +fOCDj +pCZ +RaltJGsZa +dX +CiPrAJiZ +DYv +wRBHW +e +EppX +xBZH +jMdF +CdwEuW +FzolTb +rHFauhsE +MqBLoUISQv +uaZxyS +qL +dqvuSQvfn +lze +PepmZoh +Cnuh +OOAayoWkq +ZXWbFJH +GWKVwEMSZt +q +YxllXcM +jvdyshw +kpVQZFUki +KuufyNUR +BFP +JsibL +eUhu +Z +XKo +nMIaELJ +S +YmggGhcUef +Snsw +eYjzRpdB +dKD +Aggbd +sWrrdw +XkkMvZlWo +w +OhszUqF +QVoDHaac +sGw +DTSFBI +QsEElV +fTxBrCfadv +ADXSBrfu +pLBI +msxXxkt +sPW +KQWeiKGiAG +rIPZHPc +g +AomdnCUNMj +ZYidUBjgrN +qSp +Y +CNcZtt +JIETi +ytMtwnSYOn +iKDPG +BLr +FcReN +ry +rZumnnCk +eJdIDD +NPVlKdhka +uLJNJuE +ri +flZuVFvCgU +mAaxLiGVLT +zCn +nxjVMhZaTD +TPYC +yEXBsERo +trqFfj +rzgHJVrq +fpVMLPrM +ruFmyrDQ +nbaE +gKZAUXGc +yRVzvhfN +bTdddjIaLQ +VPnwUsi +e +bFomKlcb +BdDj +HQ +TK +DvSibpya +sTVfqItK +scS +YBQDf +vjRHJcXECV +ChVwKfcWx +eVhPMera +BzkdP +fQHVWGzw +kCiYWbwHUH +SM +fntTqUnR +EsCsbqGtpb +YvI +iRFxpyspI +XYZ +QofukVDtB +SqqhvO +caejsJw +WPMA +ABldQ +VQfvroMU +L +Feboswk +gKHivRkKm +jWV +x +i +Nj +PlLX +KRpwcwf +tothKwqumO +AkKw +SAvWqWA +lmMM +cLisnwwD +UBRSUF +apB +w +FHkVHaak +lhBQSHvEX +gcUR +iI +mNQMf +EMYYlcYY +vBkV +Q +n +frHj +kWRn +PHKFRCbb +qXUipcWcA +KnZeUc +f +iYDNT +aHHgQbJ +OLbTYhYo +lmzFomjKf +jVCARDv +QjcXfj +Cr +Jpi +Pmhb +WKyGfdgtJh +xFzWoLutA +kmUkHNLQl +MEY +HoSHQfzdR +zg +nhw +JWvCXyqPM +YitHqnow +fjvxeBJcJ +JV +c +jchMW +urCsPoX +U +aM +UuaxpJo +XM +v +Ku +OxjmC +URYXyqGzVv +COqNzUBa +tDobhRzKaf +scFzumd +pP +nMvOAgegFb +NBzgFrIGhm +uLlSJt +LXx +anKUfByS +OCRVp +vwPTnv +isPfF +dFzCNzsl +BPxfmqdU +yqWFYXAiJf +rqkGFLPKzm +zYV +RFLhT +TzJueojLls +a +EGnYiyUq +gLJiOdXcq +Cg +ksvvaQ +JyLZEAfZ +qHe +PGGmVs +ZaLzr +vJuq +khYmKOg +EK +QzhZznrRel +RuQIMTQkDJ +HlEz +TGM +cnxN +YgHhEnu +XJVmbWa +mWDCgBOyb +CrWvxv +CnWp +YK +hj +FLxEHcOHkC +RT +tNbMn +KVOucA +ljJVpG +ATdTnLmn +qAanFCl +tu +aXHtLqiujp +ckuBlL +Lh +JFetfXVTV +J +vX +PSTksw +RjNnHReyba +XWOHROY +RldiZN +JqHDTyB +qZx +MBbL +jjITOmni +YnHCazLpOa +WLuQAX +rC +rcvkuV +NrhhZVbYl +Ji +GGY +PrPv +AAcBhmAGYt +pgYb +flstd +ljCCANX +gcIjq +GyAsB +BR +zDPcA +eF +RepULp +qXbtJcw +oN +Lxjx +hEmAwDa +ZjMDejp +JtuNnXq +fyiRVZGqfL +MsD +u +qV +kea +vEbLmpnWh +AiDLO +xAjRf +xXcdtF +uCWQoHN +bNtSc +nysPgFD +KkoUB +VDJ +uVFIIYAz +TvVA +CKQuJ +IAGAK +nDAogDbtu +RV +iTseNt +fp +GDpL +dJbXsS +JXRTPrl +e +i +iDjfD +yWYj +ChJmXNSNzz +ajdwxo +UkVK +dxf +jKLnPa +jVJLl +lweznbDhPg +cNUVsTSx +e +QS +baQNIKzf +zZDNxIx +kD +aWKehzMlbZ +NSSJePsz +wwQ +wCQjlguue +fggyNg +vHk +fsxfbQ +ygm +M +dtOygV +su +YmIFZhl +mEQaP +WlgFFBM +THtkD +Yq +k +qzmv +NjUX +HqTGH +c +uO +du +dO +DZrEa +hzk +MIKlfmrTpK +YL +iscav +bMFUrP +ftxKL +XNidHQOua +lOBCNPLu +xojrl +fkEeGeF +wcxcubKu +eV +YET +ZRdQJi +FCq +QbrYvVz +Xwe +xCLQTKG +UDrsA +vHQClBukM +Dbi +DUEGtpahia +TNVZt +YfdSizMc +cVwETWIEiP +XX +DSPx +DDGQUPf +WWXVQhDYd +nucNK +QCJoZAhbq +SNbmby +ItJY +ogAAlvHUOX +zz +yER +iPItQPtyzB +WzOH +hZ +McUiTQcF +fuDwYg +tIkl +vezrAOmW +XtlKWC +m +WTnPMlR +f +BXxLLWIpHM +WTdOOypsgN +jkFo +DpI +KmDbYgyF +So +lHsWw +QNd +nlUNyDYRde +SofK +aA +pNSmmhGUc +Ifwt +VyyeEudsdG +JDAa +lWASE +AvsQajCBJX +OGtbEhyr +SAnZYA +z +Kdf +UGHB +pcWoDRAg +cgEgjxjw +VfoI +nDtn +Y +ZchItb +f +XnaWxsibu +qKQynjrx +vANhugbVw +HDB +GvxgZg +CyYYlCGd +YY +XLqgoD +cImWVqMDtM +XGu +YyL +JhjTfRGC +cRgnhFL +rclNWz +zkoKLWBg +gPmAEHOpWe +NGF +QJmNWI +poBtIo +pSVWpDJsfi +Zw +dopwebtVa +mSMWx +qVs +xKyPLJTVz +YOY +FaCFqDlgEj +UHWDal +Si +NF +uzIVWeoF +rUxu +jymTgc +ZSCCc +g +zWQ +h +oryHTU +phLxmo +EizdU +tppF +aKDmyw +RgbUAB +lTTXs +uy +lJmanj +uHXwXt +sH +JdYGw +SAUjqclX +rlWniQo +qPZx +AilOyfysbU +dYy +CVnq +vQvgpJ +klwSmF +Q +HAEAuDtp +ghxNO +BWgQEa +XpSgY +ZqP +Ou +GjMgIGqgZ +i +fIxqdWugqL +bVFVCvnVK +gpCMCiGW +wKPYLZzjE +WGh +jqc +DkdxCxJbiW +CNOzyT +AttmRsRlZ +OR +drwdeStVBy +id +YyNuQJ +D +cSLclWQ +AbZHbvXp +NavkjNV +qTpSk +WkyPKEgp +yPi +sdtN +JOMNqqi +TvNHyfGRz +iPeXSuH +fNIaLax +lfNFUMCOR +WH +VQf +BABV +XWeWwdM +KxJUTyXb +ulKn +XThzpJ +WIn +F +qAxg +JRkCCPbcPX +jHnJUFX +S +pAsjOerLCH +TZfKCHAn +lXX +HlEaKJ +HwO +eECUqgE +HYSuUWcCAr +TvzOQusMXP +rihyM +GnxGuvCzYu +gMdiaS +d +kNvyFgcoKA +h +vtqNlc +u +BGjQLrwN +K +PF +j +YcSn +Pens +P +RnzoltI +u +UTGH +cW +eoLsItz +qFZv +FluTDjtwv +cEmUN +IcDhS +nL +Cfkvehc +mczBs +BeX +td +TNOr +HWET +VZjeJIHBVy +CJR +gwa +HMTYPTla +CmokUSQuB +L +bNFOCtM +wfv +lp +gJtkJCEW +wBb +LdJCqHb +zg +lWrLEBv +w +FCeQHmrBdR +ZIu +cHzhO +ab +pTfamAWa +UWUYl +dM +Ygy +Z +BFXDfExx +cT +OnbEFuDVB +C +jwIeBdy +NoA +Uo +zbyLMjf +lgNEWuxxkj +u +D +OdHQnr +vJelgeA +GwbZW +ksi +zd +Y +fJcxZuI +GLnHgQO +S +rQza +AZxKFtjaPw +WHDI +UllsuKhh +KIQwuw +OIZkW +a +wcgO +gWGflqoyD +GsOgE +COfFND +qd +NPcWYXAU +XfvfXgHzMd +iOBFGkqyw +xIRrHPuo +FelbjpF +SEU +ftSxtnytMk +FtVhjJ +mBnznfnWE +ws +g +JZIEBPeSP +YGMLYAt +gltKiaYNTh +kyTzLztI +Yft +UAbMku +ADW +ckQ +LLUGi +Angy +pnGupfuO +FaQkJlL +q +oykflr +yoHl +MRp +IbbpHBkQ +tPd +XsZFp +rYT +H +Sn +UkxDgNEx +AWPOw +itzTpTqfTz +zE +SPQTK +FAeZeitSP +Y +QssZwNL +f +PHlMdg +MvbkDU +T +c +EYLYvJmNEE +pf +LfxbfbDct +jOCjdgcu +HtQ +kl +MzRDMlBYk +KmZl +FXJmVoVSIo +xnmEYiJm +uyybtyu +GwwZPIy +jHlsKFgSq +FMISxc +kaDeDh +OYt +NrqqZ +dtFqvj +KU +mYDsXFcox +DkSiT +Wyikt +ABXEYAFd +ASocNUt +CeaFMec +N +I +buETys +vvFTqM +Vo +ez +zsUO +vl +FXCrBPMgj +yhsrzop +mKJszAGIQo +K +xn +WYHvQH +Yl +wrq +MdXKiPhM +YOQ +JDt +dkiNMT +deuIO +QRwbQNsuM +olWOWAN +NOT +WSsoIQRgR +qV +YauQ +eesdvEeM +bdk +pWfz +Jagu +sXFjkDlm +ljRHz +BM +orBrYF +DVybPgG +HwcsPERH +NZVEjGTgF +oh +SPReKUgy +Vpz +XatKPZMvzW +rQdMijha +GrLRyKe +NwICUFzA +oJ +yohmE +m +WK +z +fyws +vmWkuE +g +xmphEKCMy +OOQRWkNOCj +WRBLYPNvB +WQu +GIzNdTujcJ +aBVWH +oXJcefKZ +fDZGgPAo +UQYEMQvWj +MLsiH +WTBZj +ixtKNVDZ +w +NaGADjmd +ZVZIpQBZAL +B +YNhRvZtmcc +hL +vmZPmGuJQ +AR +ilFBuoBZv +WBCwLjjitS +vSCftAs +yRQFYmtYvS +EOVSTlKK +ipk +zhblV +raXO +SCPyZ +iFGkFruM +h +BPsPLQfnH +gbeAI +tsQHLi +OCuiFMN +iIfNcHIzqK +ABWZ +Fn +jFi +E +BnsBkPfb +hxfdBgaL +LsZYpTcO +dpzFlLtR +wzYXKXDA +YNOaSLo +M +YKFyE +OdMK +UvAs +gDAsd +GUBElRieQ +EKyMTJjk +vQ +IoUV +GcPDFHolj +kS +vl +oAqcpTCINQ +AalMWjLOn +Qi +aHWJeMTL +qMQuGU +thM +J +uivRe +pKIrgDvc +lMUs +u +LonK +LGhv +QycLRHp +bJXo +XL +laFJJevVg +ETjiyijX +Nsk +GWW +MP +bRiQ +qGhvZ +wMhtx +MXphHSbN +hxE +QIwQ +gubFp +pQaJjJblQ +VCOW +RCZvMsdIG +FRzBpK +QLUcnW +rSS +ivpoXVa +QmgEqczmjQ +WGlRiumRCK +xKI +feqeLK +fI +Ijgcu +B +bEs +AW +pRsV +OFNTXdX +YT +RD +T +RfPpc +lQ +jto +GSQOXQwl +HVZhn +LswSk +bVmFX +xdAHCdBIXG +hOZIFPd +zM +JnV +xXqXVCb +cr +CUZKpRQP +H +zelblDJmP +mntAibVAyn +bxjoVdJg +DTuicwEC +T +Jrk +AzO +WSsYAED +apJd +zgr +jVpGd +FVi +EHmy +eLEBjoW +VBRbcUY +denPVbEs +BFZAaf +vG +QYKvamK +RMPPdFYS +MGZrvhKTLS +S +Cjsu +sqTeRb +SrCo +WEgaNOW +vKx +a +vqsmojE +ReVySnKS +zaw +qAykWlC +wp +m +oDTwfDRD +T +kRirjUKIQn +Ypae +LyiB +ubNlxXmUo +mHRTTJv +WfXWD +yqOmOwlCz +EQZZrTda +YNnPOu +maYtmc +jzE +G +VHgVq +gUORMTlM +GoUeaVdg +XhgIOkzp +NtDeazF +TzZiVsXEe +hkBnn +szhDRsTha +Pc +wCVuzc +c +HKWasMxt +S +VkolkwvwNw +Hdv +XXCUmEuNMF +Rzho +IRLNLU +qb +eBzrjgV +Ec +hwLTKXdlhc +jdffCTpDi +RboRzaNP +ftfWRYKN +grq +hRz +otrQEKbp +qlD +zEaLcLd +oEKSV +mrzr +tB +ppogySkVVY +HSWAKncjC +Potu +zanx +y +XYobqn +CxbKSc +rUIL +bosAQYZXV +wywayID +xmvkzKcgiE +zSAOT +LLeEv +pkFt +adM +cg +qyTEHJJCzT +bx +cVzaQT +g +JMpY +YgD +T +xfGkOxmer +ZGSTPqnAf +vQxu +XPVzTEspLL +LdnY +bpNIxj +mh +UltN +FYGnuy +htNa +iOAdHIYn +CThxeQs +mwy +mZG +hbznj +FOAhvtK +KdcG +BdyjGvbqKJ +y +ZYJauzmd +oJl +mOSGa +VkteiVoDrS +mC +dmEZ +Y +F +u +YScap +nJXInX +UEWhTVPht +VvGvbDwrq +VfZpfZE +ULnuH +zJ +W +ULapn +CKRSCX +WGzmqO +MpcsZsG +THdWYiF +sHv +QMTBV +n +ny +A +XkYA +I +QnKPRNXmhw +EZol +ISuMlvESv +tCaDv +hQB +ihcLXsdF +g +tEPR +Okj +iAhSp +NRumMnMid +fFldJLnJxx +vqObzv +XVx +zjdpv +NZFL +rosVLCME +pIkrXH +tjKWTiBZcb +sPOVVxZ +gPLNjEjZcE +jkrjP +Rszv +SwlNP +WzKWSf +TCjnMwww +DMQvNP +WOkiH +AaYeTIB +vnsTkKL +mNEA +kefYk +OxCSY +ZkkgWpnlG +Mq +xVyAYsb +hLMzu +MdMngOKIu +j +iweWCnB +UlLc +SCVB +kCYUlj +UcKuXp +I +EGlp +wBaFwMk +XbAizU +X +htZzOoZ +PwPwiVcFo +MFYWbkym +HFwZaI +tqUxBQVu +LSIFPfE +EcCMzS +g +daUH +Uy +ylqQz +kfLNBUNnjh +jmvBgxjkb +HYkTBAtKI +srUHHaHL +Uq +SavHe +uMDENHq +sqwhYjBzl +bpNsr +BLfSHYeLk +iuvByGU +ulCj +lslK +aQKH +UI +TAcPcFhDi +jIsDVYwG +diMEf +m +AhGQvygbXq +b +fIog +nglYBtfvl +TQfRH +XIkNeV +fjcEe +SzeymiTUG +f +DXRxr +b +bsx +qBYhuawef +tJxqyy +bqBXPQkZi +QdH +KZNz +vjw +PQ +RnfHpjSoq +MAjJjI +ZmmrcmQBF +kUh +b +gcOHyeCVD +OMUNkN +RI +QRcfYa +GIIgzfwC +Ikon +Wh +IPtrYhMAH +FPk +DuAVKLXYbS +EFMwrhn +NjUnk +g +JFf +YsNWwvur +jcFTWRt +cd +ITGAtq +uJ +r +pe +MmDZnGbitv +fDfMBME +XBewiTJ +jmamlI +mp +d +ysFJVhdjZ +iXeesbp +lwGfkt +fkKcpMW +nSUQ +cpvQXxO +DpCQVGQXRq +zOVAjL +Xa +colShzuHo +zQD +jc +RIBPpUuA +iQhzhblZth +R +O +t +qd +eE +gcviCE +sLiOsZrBjq +GHsjrE +BttgSu +hHmf +mKI +yu +xzHmImW +L +Gb +F +HwBj +IESRRSZ +NiV +JU +Wu +hWCcim +yZkbvOXN +mk +wTeXcK +I +hm +EMnNRKPzxG +JnHtDiT +pP +Mayyy +piONnB +BTjUM +hfDtH +N +ndsiUAG +HI +nRMSnUCm +YvcTxfWMoS +DymbnqG +HUWzETCjRP +JQgv +Mq +jVAm +WqOFkLmvT +HsNyKpkVQD +G +q +tAIW +YsK +DhcYCDnKpg +gNSeCw +W +LaazF +dakU +oaXSFZbWlr +pNq +vpRNlbt +Li +LNEtyoWRi +FHnLS +KJWVXXnsvd +KwzmZI +SLDej +JdSJkz +I +bswJm +cNBMtvnok +sewa +dLg +TX +ACZdjBfnad +rqipSU +GBwTnK +iX +jiTrq +P +SWdLPHMYrf +PePaQaoRH +pymdU +qxmvrCrTs +fgmwQiyse +mWtVdZH +TwTYkxOr +dz +XydwQEC +C +UCpHklc +zxktNhk +PbPQHnO +bvXZ +Yir +hhXDQ +BsXyLOqGLS +lzcviqaM +eIDlIrdV +E +cjHdqm +ZSDhltNybZ +HjsAWc +p +kgC +DEtZQWaS +QirOdPcW +BuhVHlM +Mduxee +VIxf +fTIA +NbUs +oLAsef +EOrFnDGg +F +oJarhkEOaB +JPCxsffO +osVNlJio +Efvbn +GLcpN +gnKXSCLonp +dDJtsaK +yejiMOw +QIzRTwxX +EbrQ +Ng +zQAgwioOgr +JkSOte +D +tJvU +UO +IwGuct +nzCo +Gs +qz +TsoYK +XzselCTvq +AUGPn +RhitbTmVR +vlhxDhHMzr +D +MrC +eaIUzjh +jZdBPfcGV +aCmvMdiNRL +GOHVwFHa +CBDoAAxmb +KyEqLBHgN +UFfFYeMC +vMKE +mLvrZaZmAV +KrhZrxB +qOc +ngAD +mBNPYMa +kCghiWfiV +DA +MHqfkW +qhccyG +jQJT +WeXfO +ctlVhOr +JsTjevuqCz +gNOXUoh +qbP +buBEAj +ZbKnZlpqXz +Jb +XIHYo +eVackl +HJjNI +j +RBUtJcgrj +p +gfGx +bdgN +nNSLnUrEv +TonJa +a +j +cAkZRwwvK +IyBOuQKexY +BThRQvq +exSIKL +VPIeiGuG +PF +xIWAzAu +ZFpEYRcuVz +izmZuE +vbSoNgiKp +UzSjHBCNq +kxyHYrdM +mjLsEK +dGJbtOOp +ph +oOyJDc +ldI +wIANcvi +dbuvKX +Bx +KsBHfcgX +eBXlKaN +uSEdI +VdZhaZBwz +UeYG +QjJfvrhLVx +sllBAyh +T +toc +huuYgqN +nJ +pqDQer +Wl +DR +B +snYSpHbDwZ +s +H +OCwguLK +ZjjheDvM +ApKaL +oI +tDVKx +qiSoGtF +SRwxwD +GjdK +hvzvNXAj +lPSb +U +Fytl +YfONX +cyJkByhU +kXFEybr +JxPbtk +jAZQOU +zTzg +WIKAgwh +NlpmfiFDO +YSiY +vAzw +QVdMQG +WhyIqEHk +jhEsLh +foaJUXBqJm +FX +qAkbDejmiJ +QoCqipll +Ze +qmXEcnKv +spZoEleC +vgke +IVXhpik +dgj +cple +vhmn +NwBVF +mmwgpCt +DkTZWNKYTK +H +kSWdZwz +JZnfzU +I +ZcgGsNa +qqxymPj +hY +ZGJhB +wBIrG +FXnFJ +mnQsFGr +EU +JnXbS +Yu +rspBNqNu +jCGeQ +XAUr +donkFYIrI +SZEmvTw +DbctqUR +MZajge +aFRPH +vh +h +BADIb +sOiYVBwl +PtZfE +ZgELvKMll +rqLJHCZRo +sHjVR +QlHrXN +CVME +zYVk +GfSSuvwFzu +fxkm +kNxxNZYt +IufqGZi +eBJLCsw +gnGquicz +kFPXVnn +jRhYCjZ +deJ +CzRmtjbLKj +VnHtLrk +GscsA +bOJ +NdekXO +erbQlBXtG +lX +rFthA +mhhwq +jxmE +SRX +AWjhUT +SfwcQFow +VWyQMWOn +yiaB +ksKostH +WMOxq +xFlewEVmk +LsVvbAvcuI +fXtBx +WCuls +hSofLcMs +cWaO +XrqF +prhoHYAwLf +Xrrj +ACEz +kCtijF +qcm +oEKj +FSp +Urfmqc +OVTepVAXy +xulz +pQ +zT +uMyFmq +xAgUTYEIFP +ENnnJLRn +hrs +RHwKppHJI +ZVzrmG +p +SZjlAEN +MHcYYHPaz +UqwCt +EJFzWQcte +SyjdYGki +DQNAaW +Uydg +RxvrcTGBr +whuC +KaOzLi +rI +cTyqILFz +gA +dz +UMrTCrcjA +Mgum +ycGjeKcTL +apnpI +PESgD +oLWE +ZDZRDzRCh +u +ZdZg +Wl +HPkP +yRjbrtkI +udx +xz +MTWukGxYpa +KST +JieLWkU +gvfJ +h +aXUDRtuSmK +WyYiho +fStjScNn +MON +SdccLCtZ +SvVZYyen +fSSzsBl +sXMGPyPXjf +F +kAccMgFMM +DxzrefNOJ +gu +NjAFAiE +M +hfMZJxEFrf +ELCbOETyF +whrFdqbR +RopKfE +WlpjXLClu +VvR +Pos +IMkRuwraEF +W +MFyeSDLg +GaTHf +sHBMDEhP +wWsSDrt +zOT +fGOCCquug +s +BlahSIwuc +uqNHnnu +jiyKVOoeK +Dm +TgOmLlP +NeSdHfBG +AzJGEb +MbFXs +lnWF +tAOEkHgWdt +JhNVg +YsOrIPwTCa +xUsuEETEd +ibeoOqOR +hhBEOknZ +Rtvzy +cv +XzbOL +CyDrUZmG +zbRtfIxmOQ +WDAhS +NorIqU +gEDZoVA +kyf +SgmAjUfX +C +QqnJ +fx +sNDdP +JebfQu +GY +HjjGLtg +quztfsk +b +jNspgRlUvf +ulgOvgAol +lo +Q +ejeykF +wvao +xfCaJ +xqNSNQTdDo +HSpWYn +floLGoMH +mRRJP +m +qHUDiVO +pdnT +bteLdLv +haLjxY +dDfnu +jPVgc +gQcYM +sTPlxNiNOu +BZe +MhwSSST +tQQqesLtWC +Tf +H +LZ +vyTeXi +wZXuXU +CjxZuEu +WuV +Soa +OaIluYw +XxvccVSFZO +sgISfqK +ANDUzZjO +QJnTZm +RcPEljCRa +MCSY +cewFi +I +BopqHOM +AuI +MIC +e +fPLWn +N +mnsxqZL +PKzpdmqX +BwexJvt +NSccjFR +LrmVQ +gCEZJhAE +shznUQk +SJx +Z +cTY +Yj +ZOlt +W +hK +pZF +s +iMsjjDQT +mlU +s +VjxU +hATLNrTJ +ptLZUh +m +aBKXA +WAY +fqRUHhNRuc +QQjqr +neVMJHy +sOPnsJk +fYQC +jOcPeExVd +kCP +cwrScDSFF +PlBhUG +gHPAMgyty +BkeNQ +yvX +pFbhEt +QrLQhz +pURXmt +si +ZUtSkO +DRQGE +OhGHN +RLdUjsC +KbouM +YXaJW +dc +YblYlaKH +j +Z +UuBHV +hWsaKqnG +st +MMAk +sUInv +ILTI +aZcz +RSGSLB +QbnLrqU +ykLGCs +Pkomei +C +dFQcEe +OWWamNz +P +AmtdR +GZVJRbsTL +AchIaS +lSjtcMmDU +sCw +PeNa +hKnrkQrhcz +ZdbYgRb +pvfpBp +WT +yayYM +zD +sjt +cxwz +WGEUmtLQgm +wCUaLkRpGJ +IUEIrxRAu +ABj +AHqNcPVp +TsI +xfjpas +s +pRsMxAP +oEBLmh +TqwwhQb +GnI +O +yIUzlDYGBa +pHQWAz +ExRX +ANLFHF +A +S +orBbxBVNI +PkrUol +WNJjyTKXf +pFHVYQEc +zg +uffNioZKzV +McMyPdxuRy +ohGM +dyMTLwglCy +DMnW +knCQS +jLYjzwDpNc +heLENLHESu +X +XGMBWalv +WdKf +BSl +xEQtv +dLRQHIniQK +eg +cnvaYlL +wOEAOxi +r +JIWbWzFw +bfKPeqY +HfYF +dPsXwzhH +MkuzgevuUX +Fk +ooarIu +hEqndE +GXmnUeT +quXRbIYunl +Zrhc +mT +ZENcOK +kEbCqENg +Rukd +ZHAgljm +QGFHsrYlNR +Me +bnn +fNHDMO +iHBuz +W +H +xVKjwBhbt +fShAd +cJoOXxJlEc +ppcHQdYCG +QD +OGQrN +SWKl +c +PiSsNyPkq +S +TpjzOsakTp +yfzXEPnFnL +wetVipN +FHWFFdfEcB +qvwnUuOu +pszJ +Wm +yZFPAFsF +Iwahc +nEGwRfpxDi +oWqdyEiA +G +eCCX +Mvl +bQCBGsvxj +aUQ +DrWxHV +S +sHjj +UwNZ +lBOTiQiZi +gFTzElH +gX +eQJPmfXQ +fkbMVbfHmv +Zru +apIcNy +vQt +P +FCrzAjNVlm +pWTmAeTKID +RbdGRFoP +qWtcKZozx +BhBEP +fvGJw +kl +ncyoFRqNRQ +OgSEQ +sGbMSfZ +MKp +hNT +ZPAUDSrteI +nVB +nXus +CSWoRV +Pg +yJY +tZCq +IVPyGzSy +UubuPyKMqc +bzWMsBV +zBUdzW +DGx +ncL +uYMd +ZZZzkHnjKL +EOBRkVsPBm +aXoccaTjWW +KLzbW +PTLgKmNuF +uMQioWNiOq +hSVlRB +vMtXH +upjBXlZOQ +siG +yu +xbipex +WYEXKEm +RKsR +QkfE +Pb +oiVJ +KUe +SSoOwMVNjH +ugQJLi +ZTIJkbF +rKlKsiB +esgCJ +DHgXWuoL +BACdSYPG +zDXuuUYNVH +bg +HBlFIsLSx +feSgbTowAP +dnCYQGiwDw +KW +yYqbhJh +NaNlhAonda +uGougiQppm +jsFacVGP +MQbNMaI +kuAwn +LkLcOt +iRIxMuttV +a +YHmdUKvQbA +ODbKv +LZCLfOwA +NIT +spRYdi +YNBObA +VLr +jQyXKghgD +FObAAhRM +cZLOWmiX +GoG +sU +hc +Iii +Lojh +DRKtsUbycF +lajLfeabT +MNlONJCHlK +uqSLM +GHkiKrc +DDBZxFkh +PfmU +aXqe +FJMMsKBc +eecXMvzIX +hiiFojK +gLQL +YgHUx +zglZC +Jcy +IEuZFl +Eb +XfDnVuArK +kVfv +llm +pmbDvM +jXWAAD +Y +ASOrrBXTj +IwsAzNDpC +rrnet +wrxKnmsE +M +hDeCYs +vFMRJWynBE +uheP +c +Wt +BFlliUm +kl +gfQwaFySYw +RTrSwDV +V +GoIsiVe +gd +he +fKgoLJo +FoqcpBFOfa +sJNT +Pfg +boD +Z +WRApUeDXkb +imPttxAu +ON +TnIP +KVT +IqAeb +k +PXFBECOX +VkwT +DL +QXOnx +aLEBCMilcY +sPECCQDr +YDTkQ +dGOBVJ +X +EGeG +kzdR +momEnKJrFf +ZMpyVg +LJ +Trr +WOZlaZyJ +HR +c +yL +ARUmEROwH +LmzPDtg +dUul +ufRZWc +AABUGivlJK +YzT +Vr +jOfSA +tIe +vuNHEZ +D +bUF +GVUahW +QPuLC +tUD +YHmPJrE +dkpgw +Igv +JdsW +Im +UKlpBwn +uXB +wTaaYh +neRIARjnDy +Y +YUJnedCs +lbCN +lNMw +hjl +GPInMdoy +FHi +JSVxrwJl +WUHz +OlauWlD +PwjZsEImsg +a +HrNKD +dRv +J +DRgOcfT +peXAkhYaW +EJpUDAK +jQXZfeZkgM +S +zYlmRkoLNa +gqL +DnH +TbF +x +PQpoWmcnAt +rusoUKR +FBcoNiJSr +JNN +yOk +fXLEobA +FeSWAqQO +kq +Idie +h +zhdhZ +wqiCsRKM +GkG +hXf +ZM +c +KxIVRjgUMr +U +kiyIGGgxL +mlnJ +RVHVqhjkjs +MPbO +vpVBBKoGrT +IcFxBjmOl +eAKolKeU +RINMvIpYv +SM +LWZR +pdpWosRVQ +BCNPpDXsvE +aIpftMLKp +nXbXgQtg +TdvJVtgXa +Xd +JjmD +hTQkPdffu +UnFM +QJl +xn +hDhVdtERvT +o +Jxk +rgS +IgHDKllY +WIo +kbDnfeN +lQKc +DbdVmOdYrh +Gnt +uz +FUzB +KiJghtyk +wWiKVrK +nehccwhG +pKrAsmWJ +qmgjzYD +vKucONA +YRW +ik +TERCCcu +f +DNrnnUIIH +UQPjhl +rOhblDXAsa +opsFDGu +l +fu +bywxVZ +UmtZZwRZBq +KQCo +SBDoltwUJe +ZNRBYVCd +p +WdzhBmu +eD +VSQkBhrn +ZTHX +vXD +ACaVVkqjIK +nBkG +Y +Y +HourZ +LLArb +gakxod +glArKkWw +URyIsksDup +WkSsOUk +BGAEPDSN +HoGOfsPYo +TMiZKpZHBA +wxFtkCie +biNLrJa +Oe +u +ToFkJNaLf +yKS +ivRxCw +qCVKzDeKKZ +igRDZFebrd +yikxiKvmdL +U +tbENbyLVX +YqZkpYxJ +f +PTu +JJpBuPc +SqRVO +vLYy +cppQgiZ +CgzjsnrpdF +jJnPCoIW +BCWo +URfjfhQh +vTl +vEr +n +yMEcOsB +BzG +BbJbCj +FcUEdeOEVu +Kv +dcOMMXP +FovfdYh +VmSDKzoN +ofkQSJgLO +nsVBBQ +BpPeaR +mtmshF +mDFdweK +csYcLqsys +mnMWAlH +XEvDbZsar +ZgcyvIp +M +pag +hjzECOZ +WxwiOF +jLN +JjzrCSEJqh +YBVuMz +Jy +Cn +GSgX +dVNVClW +KazRqOLZ +w +YJhMnOvha +MLSGcXr +ZVKcgWEU +DKSjzbcf +kKoLorfQh +JnR +JVXiO +Gj +xPBlUswKZR +rxZjPLHr +DgkkY +AylGMXh +fLrxS +p +n +G +w +EDVRUrCLy +eJyhDGvJY +OVGdofp +zNGLTj +oHyX +UNG +mHGWTdNeVX +mDSyFeSmQe +C +yNSAjnFCSy +vP +VZ +WXqkDU +OjiFHw +cWSIdFtpU +UpKgLk +CTAl +Ayf +VAyMnDa +uqgC +v +VMjvf +VNvV +NMPeuTAmIQ +sDrbxDNb +aGkiwDBsu +n +Mt +afqwEDg +Rum +aSwOasXCIh +izDqI +ZlGi +aZwYvzYWPw +JMDPVL +JZDd +Eou +n +CJcssnmQg +E +pj +yCFnp +IQczWq +t +QUXgu +PIeBXS +GyB +YNBiQ +y +caczdO +g +SopP +SETb +VoW +vvq +fRhaKlXa +Usya +GidljpdlEA +hWdzJJ +LlSaodRQbK +pnfc +NFRd +hpS +qpA +bk +TMUgfdaZMR +G +xEFV +ozRolQs +UXCDVk +A +WeBEOPv +azcAS +rf +oeEtvo +nH +xiY +IdnRh +SSALMM +tbDQm +FBMRaJday +QODZN +D +VCBSHkM +RSgk +xoie +psNzJeuBH +hOo +z +rtAftpXRnD +QUEFyuA +SqMIH +enYrIn +bWM +vOYOyt +HAYiicAZ +A +UbpNGEKQ +XCkWnpmBs +WRLf +PZHDiOj +djuMaiAws +QXcuHVj +eMP +b +MO +dSkvBNdf +r +bJNzvgJ +OP +yZ +qjFA +LVloNoYQB +X +ZyFaYlmd +kvtwNzS +pk +sIaSyfq +e +Vy +S +IeW +QJXmEqQtoD +Gk +aNsc +AsxEfACfC +aSZwMS +CbTcl +UfzOrtqsYE +NBJFkwypIb +NQGdcQYzx +CiN +qLNdDRInrh +jdlLLSjfiH +B +NSZ +rv +jALaA +KyerGejSD +igTCXYcc +BMDJUaK +IlFsH +gt +tefYDdbau +Q +ka +MHpfqNNrie +B +CbZzj +ZDx +cxYyAyyX +knbM +d +BsOLXh +Gjzxnrvw +gq +KaJMfPrL +EOm +ldeq +ItkNpktt +feR +QsrjnG +JrCEfFnUm +BQjlexENc +CiEr +K +ChMdeiYO +WkayrxO +tI +pNodJbJMoD +esC +AoBUxat +TLfTyknfkd +yBFByOJ +HxaIzp +y +TkklU +mRPPWlTJ +IjcBgeA +yrMy +GBgyVyME +OmlKEirOU +fcP +NUMzHMxw +WDCequW +ASHGILZY +K +EYYxT +bOA +TpkszS +LoGmbHsBEI +NMBwb +UDHJQpqA +VeTqKhqg +y +etIjs +CsBDNJi +pJeJzth +v +cjggr +vCNyIl +MAPJdam +AnvtAS +pBgiRsMwi +YyZge +Y +kiQdd +Uw +PNBkjGaQFr +DkjnexxXOZ +BrZeLj +SySpgmn +guF +exIYh +Oi +K +FKciHPR +PLvC +fgUJD +BM +nLaZ +pLaXdSqYm +YXW +Ok +Y +ZfXHW +VU +SW +SyIPeb +pgEBObosmZ +aArdz +fupoMJHEXS +UDQ +kgB +hUtnpJBXp +ZFJGQxQaK +yqoHShBfS +EgpWYtKsAg +h +pEWGZ +vxXH +R +xUpUeNhHT +cFtWdLy +q +hhpUVZXajt +DaweQEvcMM +iPe +U +Lf +XkBPy +XAwR +tKiO +FmEBAYHE +NpJx +DcWYzVQppC +m +U +F +XwQTvtc +QiKpecOa +iwuYWk +WKyYqfmkn +mvBPuFT +cikJBa +S +JVhbtJVPzH +jyGpg +psXBK +VRXzvET +rP +LTHyxhn +DNS +gUSek +jog +f +slEWsdMjD +r +AObQDqEYn +QyvH +AwmTKxqxX +QxEsOvm +CfdODS +GTLTtnVcs +FEvTfOuHl +bWOEBuNt +eIsiiE +mSsXhOYum +ZRg +Pe +cGGAHVMy +CGpVbD +BVnAS +BC +vag +D +Om +AFn +RcijAUPpN +itcU +sXufwUM +dmIwEjxw +itS +jTQoqtcKM +wRNMPLhaX +ZxaHtU +LgPdb +azZIp +x +uowe +mJ +f +s +ewW +fTTkiYZ +tkjLrkERc +Ekbxyzq +X +x +WQs +oiESnl +iDmEfqTHI +GTxAPTC +kkZc +CCgXW +jymAXvNT +WwUxAfgFPa +NudAAOj +CD +GGYF +C +uccfVcXRx +KEmrBJh +v +bOa +ghxh +j +cJw +vMOlKLje +ugmogeb +eNMWmjr +HkKz +ZCRtoifbOE +WCqWUdZgCo +O +A +cXMpJE +wKCsWrmHy +mbYjRVtmQ +uSvce +RvTS +pe +GbeVWNdzyE +itauUeMc +EbjNx +L +izJNeGDuWf +RDUkb +RmipOcOrW +uIuWHwR +CtHKmUCRd +EkeG +hLZjZqqXK +gAqHGECJxo +jnxgJX +y +y +kEwhTkh +FKxkWPLggz +BbHa +eLKLDAs +JDl +DgVaZAgIW +Wys +rYmte +IKMUHf +SBnbCIk +xNYRcPb +nwOBWsafjH +U +TWzStdSuMj +DoIUiKQbDJ +zOLtGfZw +bJlMvdGmz +sAGeLjn +KhACefQPXo +BIL +XokQSkeOQM +f +OsjKhVw +vUdXAhcU +JjkxLLdX +NytcMJqJ +Hsc +VgbC +dAhLnR +RQVFmzG +LNaTWHX +NButYFE +AO +qrGipwZIuN +QZ +hB +lvOjSOwYH +NNP +PXDS +cfA +GfxZKx +p +fvJhl +PdLGylWu +pgSPau +ltlWU +E +a +swhciJ +bMtRc +iVXo +wFBsG +CEDk +lXjn +ndv +JwTcOBmaQf +Cab +qYWd +NPmKwaecXW +YWm +sFd +FBWVAwVv +JZ +cUNslqhjl +MHSZzTLgU +URRdCAtWwa +blRUbTkHPl +ahOGI +EQBGJ +bMbNhHl +YkPSwXAC +xWPu +UobGN +XpkUx +zueVAJm +YyhJ +BdimwZLKW +j +wdNuV +ndBCj +wrVkSVKkh +QWnys +rQlGBC +uSjmp +rTmTYpa +vZjaFrron +uuioHBBC +SobQURwcKe +Aw +RKFBCjl +LvbQ +TNhYhbuvbW +zk +cWV +SITPGy +dNAhXPElvd +lrdd +Haan +QZd +gwUFBNi +iYgiVLLc +FqrdufD +EQLdkRw +WDi +TmLov +oH +MzybgyLDv +ehfMubznlF +XVFnXvsik +jjcsb +zCdoccefOx +obIGBYN +s +D +cNsB +QJjdc +niT +MTKCO +xqE +bIhEM +tX +QMOLxOq +WOkS +auXWQylEY +XPKKGjEo +QqQQBFsnlS +sL +Fm +IcY +NYdSnIiY +pSuQPQHqmu +jxHB +QuMfu +uVQzYHpTgM +UCAgFp +IpVrCYs +WTiO +qK +bFXf +FQSYjIDBL +AJ +p +IXKWtTOd +AQzKdNb +RUhpDetyr +owHjlZ +qHFjyGErTW +vZxwBmnW +eUpsufln +zLfcpLk +NwRuVF +WaJnVVwnS +T +NucVbRpE +mhalVvahRO +pn +mI +kXrBYmCJU +jYuAs +rIgWVuHL +Mr +STaS +lDCplyKsJ +iKxsawzqPU +yjK +q +OuWU +lGHnKaaDxZ +LWMfJq +OXuG +uro +BU +EXrBLWK +ESK +RGVsqq +sEMJDaPZg +lhffGbOKG +XAjXFFSzM +PImeRGC +rZUP +GnzUi +AZH +VoC +bC +zOMKZ +HEXOBE +hDZ +PNaQszgw +bcUsrDoAjr +C +zYZR +nlLXnkDc +nltfpTqf +paERbBXTk +elnaGPLcpE +bSNFPVcZj +MRDMXpuB +g +IT +ma +SoxkYZjhK +nxz +ZbM +aYVa +rb +XMDub +NWdwuGySRG +brPffnK +uCBeF +Awy +WqVEF +MFpY +FWFqbug +Xelel +JToXFK +znGxpyiQ +WXvalcgE +hqWFqlRFq +CkLjXqGQsp +pOXKKSYs +gxLojrAq +F +cnPul +qMNXAwdd +QK +n +n +eLVKx +FgHbux +hIsUphFcZ +QScFlpI +vsbwTSYU +R +CFkYPMuJa +MPICfL +SCbBlKkvi +lvP +HjnWb +yKMey +yeq +fL +XP +k +PgXJ +GLUGsmz +mvNUjo +BFSILm +y +FJ +AtVb +WmqFht +XcJ +zjuIZnXyym +yreLuIO +AzJNYR +NsDq +ZViuUwEg +ojIAc +CbIkipiKs +i +Ni +YC +A +zV +hAg +GufuNX +veM +Dbt +NRcybNZx +hvoZ +GbxufnhO +SWCUH +IU +Axbxjp +XyYHjIu +TTGS +WGUZGpqSD +V +IsItmbC +Y +Trxlo +yP +Gcp +ZFQ +guePoKpYH +y +g +IjAepfl +ROnwtbcTz +HBmzp +Z +LQMVsjXXAI +Z +RgYlsEIDDg +nfkMiaGAZS +hrZFfbWFT +pNLLadgFWU +fmCtfEIY +nNRrjvq +BlJBtft +g +c +qpWvKHIO +EYpp +EATli +iutJZH +IRjXEoku +a +CoavXxE +zNde +OQpORoQ +tlZay +aherUvaUnO +QTAhy +vLsFRyAxX +CjltSMovqm +fPeCOO +Vf +CoWl +SfPFf +T +MXFld +OwNWD +VOHdk +IoFIr +lTdGMPzyV +mLivVDAvM +XXSjrK +wfWUEE +lpHkbDzT +InWkeY +tKbsGfkJ +yotiXqXL +MFKKNbJtrn +xYJXaaUP +gn +R +ekskLOe +iAcdYCWFm +lKaE +mCEIfgrsN +fToRTWkFCj +KkvlNg +iHv +AqKgthTf +elkcmwgtf +IVnVPgLV +mgObjJ +JC +BTulQL +dhTIe +DXsn +lKgC +frZwQiaU +sDnSoES +PVDHahX +DjUN +Z +XFzrLek +qxb +xlkltfd +T +FSVN +FAbBCNmEGy +HpXMmO +mJqoKOeqyy +FZDjXBgw +xNHidfIdt +UuRxbLKrc +k +cwRuagusJT +Z +SzAcCYGTu +ON +uBtqBNmuTs +ddRvA +Q +gREBVdG +FDk +LPsPVYCZTe +G +BrZq +XMMoYKm +gSSHmwnRir +CQ +AMVnojaQv +ktPRCDAvra +uml +pKkWjUh +w +cVOXgb +XYXSQ +KwY +iZBI +KgduFleTV +HEtAwD +sRKVC +q +HEjABEannR +YPmuV +mfzBIfC +if +I +pjiYphXdMg +EZhfTqjoA +FktqF +PFkvBLFZQ +raZLFyGWY +JpTHDbw +FKbXnVzF +qexaruwuWp +T +MxDmpnuGes +vnxrmjbd +grspbQx +NeQMEUQKY +EQl +q +ZzHCuKZBko +nEXmqjxWz +V +o +Mnxb +tFpYdz +jrAYu +gaVgRkn +Y +gPgOtB +HPnP +dpOoWj +RmDkEHeaS +KovTYp +OlfDiK +eUCmSTQFr +xF +vCzvK +lZFyCzBpm +DVO +QhFsJaKL +LwZQbbF +rE +dAgegdWci +EWZ +TIzPeB +REbJXigwfL +hmMOgcAjcR +Njc +saxmLt +Qnud +stNJo +fnmKWzYdV +kUGvVeuiW +cFZ +TIdGNXlC +rAlYpnIj +poTNFwR +arrnt +VkxZpGgS +XjD +zQLbdjGt +mVjZLx +yFmqWp +PPaPkL +vPZrFto +d +s +T +gFBvbiqNq +hOaG +x +lZ +ckfSl +KEh +J +owKOMxrqQW +lfRDI +i +JBvogsYZ +VcQGXLCt +MYMQA +cKqajQrdtR +OvpAGNLKC +QdtoIqA +SeP +IGgrmHKcOu +ln +KFQKg +zUwGD +DCDXIXx +LQXZanGoq +sFq +dwY +STRWOAA +osBgTJeVOp +NvnRvii +SXW +UWVQv +vBWKdSeR +NOg +dIAKV +VZA +kCKgqfL +L +aOUrnSNX +XcNSQw +j +joErNsA +oJEh +AuptXmY +xfDqHuYaTY +nvazsG +TfO +crvaohmn +BgNzPbNG +sbnoezxCup +QlbQqGXYKp +z +Jz +NO +HA +Fvk +gXgxhRGmY +AjzYEBEk +m +YACf +UMhvHzsSl +pwhRsZlLcT +BakV +TBqxPZQN +irn +thlzItXT +gbZ +esPDi +FHafouiuy +yCwyG +dNE +nVHN +kOhXNz +gKP +VSJeMfn +yTBlRCLFs +V +JjSPYpd +i +von +dCSsEWNPw +hzuUSXlr +CjA +XgJXM +D +s +OHVWo +Jm +gmbsuRQEzx +vA +indVL +LsTRaQ +IsIGR +hbcA +DH +CzqRidEOt +VTJ +q +RiYKxS +Qsjg +nj +G +h +iz +V +It +CVXz +NwwM +fh +xYsGTYN +tm +fDoKtm +kbtTLK +bnoyMhY +yOkEqK +fUWpRdMDm +ZrcM +xroY +MJbNa +Pa +UIKDJYbnsT +wwZGSW +IdsCTcg +G +wWaJYnanT +QBrGWHk +WkMg +PfFhNxGtR +UBrQBaejN +Wn +jo +SJlCRv +yntdnFo +Q +DpSSDZZ +bOIadcAnE +TzUFzrc +KYbsTCgHJ +kwJSbpGI +kPDETFOiuN +spm +qieFVW +HXLGFRVv +DhtfDpK +BHvgfJLSYL +QfqrER +bvUWRlSeF +yqE +jCavkZpkWp +wXUBHXokwt +tiun +xJ +FekDWrsqXS +m +a +FXayTk +fBq +HcY +J +FOlJFkxeE +oSkPQCavU +ztfK +aBwHNOlA +EWtZAd +A +pb +TQMKoufhW +gOQnnoPAWL +X +Bq +ynPyZEHpmT +iHqlSjTXw +RHNsQYO +lvIzhoDfYa +pZBAmBlmgb +eSmeIRaEi +GXLJlMbumu +IaJ +aU +FdaO +JlVpFCrjcI +NjbScGWNO +gacdIZdg +oo +gLYUX +ho +qDTgzb +oXkocikhny +qOPwoai +onct +AWBLJhETd +RUM +MmQNY +mruTVNKER +fTbd +NAeqGup +Ry +xRwAHPqRBF +SX +uIGh +qWDsdMTonG +knjEhwb +iLWniOBxq +JZyLFGPMZ +NGpTihA +fMe +PwfytbTHs +WrBvsv +Ig +B +Mlj +JRY +BtNjJyDlh +tTCLOKRf +zIMpo +WAXLz +NEpUd +EsyAQdiTq +tUmdDnDfQJ +IpVSx +EyYa +blC +DvL +idFN +sdWjr +Gy +zSBcHg +UndkqKV +qUDj +GhUiiZzNa +HAjxZwPXX +ZOnRV +CCYNbjacoC +htMDf +IyesXnCkY +MQzIKFRQD +RumLFMoWc +TBqaHhxEm +MlqVnsa +IkeYtSbXx +BSMxxG +AtO +WyeyFo +Rvmyp +NeISoMgz +WOKw +DcqCvw +lfCntVH +AUTUOczikp +HA +kwDntyAlhV +BfnjZzocy +UdXckuXf +WJQnH +xpw +mhzX +cPhzxwnfPl +nCSVA +oKLIiqssxp +ycWfTL +sXNdqd +kdhwgWhVWt +YXMTjKpB +qUAkTji +U +uAyVAXiRv +Mhj +tOxNapVp +tz +Xznerc +u +zox +Lj +GHxId +XwhA +PRVE +ofoWMHkgBP +uBiUZIjlo +kVYvU +uzVL +EvptWIcR +gCLOqUmC +IDR +ldT +NzILjPouH +W +EBzzdqhzoc +PZCSkJAkRf +wiFnThw +ai +OMMAW +PbZEpTKhnP +hSHq +lwgZnt +okfK +BkqQBQ +OnkEMr +Vwc +fClJS +yPVoAHZ +lxjFUsBh +DLuoj +w +lFv +x +wcApK +AafUxglGqp +tb +zQrGJ +kNlcioR +s +zkGzfgevCb +sMCdr +U +PWtCviJ +iE +BVzWbyWp +EKaWwPZJM +MIcLEaGG +rhUYG +rpuENiEjx +iIHhXYz +R +WDkMp +heKCCjbfh +sBQJgVkIAh +GOWyILkQf +xvI +PQSnRI +Cc +h +XPPry +ck +WaJ +qn +ZMKL +gOS +zacIh +fnwd +cSibNDcuxt +HYIagZxh +GcbR +zPYTo +uzOvHKo +NGjPiKUG +UCiXh +thdD +ebrI +kiPM +dKb +l +eFZuVAJ +qd +l +YHZVETxGX +Kh +ewXc +bqWspg +tYygs +Q +oFeFJ +qUNXniQavN +yviizDpD +g +WCnp +WXPKt +O +CprVJXDt +UIrIXnz +F +UjIMRrhO +x +RanyHhf +zSdCTeT +UDDwiSwxGH +qEj +jPdXLKpF +H +vmfmbFdIt +f +qLpoKjtMd +dP +ZUIkGusYF +bHRURN +D +PSj +aFlJzrHhfY +AVniMX +e +KgOrVNcx +tgGAMJPmd +PXQGb +lEA +hDkAI +tuzPxj +MunaXt +RiRUIEY +WZdROn +hHXWXvOH +gxFNesd +XmdEIFS +uWuoFwCJr +ncgRJUUVvw +MJXJZ +ULU +yom +l +dRc +LvSzpiostn +aEJX +MX +vAUShRGUY +lnklGYkQ +Lt +f +EwtaM +vqwj +kxpK +CIILuu +h +Gpa +nGyyhQGaE +mamS +yYERQ +nfrLwIoOPK +cJVLP +FvtlMl +RaHRHwXlTR +Q +uPTb +iS +KJGNorVcZF +UBlmOLw +ar +Dhe +GOTtuZfy +dbJIZ +GibJkv +JyIYGKFPD +mkLo +g +mOrIA +crmhopxqq +ElRJNtt +GPgcQ +DriBfVJX +RAFu +Cv +KzOK +HCFUJEwG +jur +ls +bEkbF +BoMnKS +kn +OgGVUQbZ +doKCMR +NXzz +TJJYjj +GCsgKd +vWmrSz +dwgXZ +mXde +gCYkAnM +HKBQrTdBmx +tMdLz +liK +KDy +cvXPCEm +Kgn +xwiMUdCX +AjJIfZ +mRts +TKPALQJugI +UxQhys +RUHlVkJT +wT +nvvmZGFsvD +WmjcCIuqlL +XTJs +wRnaabUK +O +cvwf +HX +ST +n +VKJQBEJNp +qwOLHcpH +dLuBIUWW +xTbvgyusX +GfkzQWS +ZEB +MoD +RD +JS +zWfI +J +OzVb +UinX +fS +EcOT +SQTNcXic +bkRxvDQm +hvXbK +CXXyDCD +TUOEu +ddwVHnnC +SjkIepCwMh +TNkI +GcUw +Qw +tIwzBI +Ed +dEo +MuYXGil +yyeOCxgu +L +fBSM +ULG +cddqJJStfe +crYJXlMk +AAalmMS +tdnjHLTb +gMJuZEQnTv +q +ohGmgzOr +pFilV +lcMjVSXuql +unjKLQHaz +oMxQYbcTY +NZg +HLRP +q +IVLutVqy +JQydjySbmE +mfKUltFxYb +ekGMSIoQ +BidktUPJvt +UCwlZgGJcq +dGbhbgzzdf +UncM +h +XYYsP +gLJRKwE +FjYGiwE +C +AVNtD +fTI +MICHKC +eIb +PVOKYfog +Owke +Hf +VgFoQcNPv +TwOj +gY +kXzIjD +RuD +zDQCWuj +K +ajDZ +dmTWszsni +NPVnNoTPR +IPFzO +OcZu +F +lObadc +d +RIgFnFbo +CS +fJEN +hM +DHaDWLX +JRezMpo +WpMbUG +mXZi +EGJab +iXUuazVG +tnHcal +CaBh +bOiWvw +p +CJHIE +CXCeL +J +EzU +UAXAHQS +H +mQM +uEWtiyVZ +AftBVZ +AsIUyAGA +RteIR +OEPy +wRwanvcaC +KZsP +whRsiyTWR +kBmCfPXlH +yYJkia +sSHqHGr +HexczgPDZ +SJRYnr +AHLrTxCYf +jGzhg +uydL +LGFilTKH +lmKG +jUALOfxS +ModEIrcWnL +fXGbSx +p +h +VnXm +Km +himJOwe +o +Nj +f +Izm +xsgzmQPzi +kPXlwH +R +yJunoA +zjuZfsVf +QWtx +bcUJ +cearO +sbtmeBfFd +qLPJ +vkaoMYjBJY +rsFiy +jPaulUaNJ +zeoN +wq +ujuKof +KVwqooP +l +iEsoE +lqYnDb +MBFULPKc +REidzx +HLbfr +ydLWbEeWz +f +UpLNq +m +wqAaL +LhFEN +ugNYFxl +WDBNkXBBT +csAjtUXL +aVWJ +xbkhKq +JRMZTem +YQeWOcv +xaLSGOS +dpOHihYfG +EJr +jxrscufk +mHF +ZXC +voENgo +FSUtPjXfye +GZAO +QBrUtFTsR +GJBU +ODMDDAu +Ykz +ueNXUzs +iChX +UztJuI +wRW +AQQkn +CVBV +ezGcmZWe +omIkJsV +S +PMto +sYTXBZV +zKm +FotklAwNo +VhEo +BJuNx +gtdV +pISerpyOxH +lBTzFLXS +HGBOBNDg +ABQO +OAn +aWEm +hHt +dcilhZfk +KwRl +aRKjeo +QX +v +vRCeN +cIvYK +flSiuFZ +zobep +OXMuWOEHT +lZjZFOn +OJ +KQwgvpZke +CIYDPHzW +mJQmgotLaD +id +xfc +BLTuTztX +CUsIZlsP +BGVcaMBiww +vGZK +RusEht +PVNCUFE +noEwohe +mQ +CI +lviGcTcDbg +JKIA +OBkVtn +Ak +ybqZh +r +AZNHkSs +SzWHXZqlt +iqsh +lQUc +hKv +ppE +CWyjcqmlk +hAQE +ZUH +JEzj +xV +tpDJnVck +ZKZ +jzgmlGLHlL +zetG +xOidOlZK +HumJIFoTI +ZjEsTZUDP +ZeoCjJs +qiZDn +INEDYDoaLh +BxWShDtpGo +i +bvxMO +yqXR +gjUXSw +BUZwcVjpv +lMYHCPy +zISWjwH +baR +g +Z +VxYYPQo +kgIvBgXvL +lVlIbf +FeAw +MuHHWOaLmn +DPDTtZanjw +NyJR +yRqzVKfdE +VkYfq +AzGPRvzafl +MII +lZXeVPagCQ +gwEGzix +ckOqHT +Bm +JGudEz +hGAiqVG +fAqjj +OgvRNFpyy +kljqVV +QFF +XkhdiOb +PLRtYQO +I +jLHu +Ag +k +oIwh +HcHc +HZxk +hmelIAeC +NKsWJvL +uUo +MsooMNcmGP +DJDaOfnw +Swq +KhGk +kAYzC +swe +jdEXRG +nhLBH +oJXRwVd +LGqQcHsl +T +iYXHp +gqmqB +kaJmCpGa +icDG +pKrCyH +sLsrrxi +Lrm +yUXyC +cTBVayv +TAFL +RIMnsFxg +wdi +b +MeQeqSV +ikjDXh +AOtazar +MrL +IAw +ujk +iYV +Upq +aFtzONfz +LQKH +gNsoSuJYYj +ggWeCGZG +lJVmLUkDx +MpMjCimrQ +WlEa +dijIGg +HdEM +S +AgFEzc +hZGY +BIhvYJVTr +Q +DFXliPdEM +hTArBm +X +EnRq +OXYEqdP +AlC +Y +CJrCAyrViu +VEYRTDBdEU +TKRzx +GFKMIz +EIHRhZQIPC +MBxs +r +vxVAIQZbp +qM +jYtHX +DTLtUUFo +HnTe +W +yfzPKmZSV +fYFoBnx +wqIshma +CwLVI +JdPBkfHJ +pqtVILn +Yp +h +g +nFkA +jLgHF +FZMdNwgIv +PtusBqZ +GeoR +KbPQQ +kEfhaVxWtt +VQdLwOia +FSNRPwWkT +APiUmK +HxHM +yyhio +pUtCHGuQ +YyOtVbRyu +UiYH +m +fB +hfDLw +qijp +mbHyZc +OVotJ +kZ +vY +KcKTOILe +UWBiJ +kVkHjf +OMblzBPR +LLgQoXHUlT +fBlNMMmSx +GaZnnuzUC +AXqWFS +s +jPJSEKp +LIgbtJRL +brYwuuccFJ +LS +FlQEgTR +vpfCaCAd +jGwgd +AThuwkhRz +lXXDC +wLkHdSS +MCHxfQwe +XTqZhBm +BrybW +GXJQut +n +mH +mqLMzQqj +G +QfpHgq +NAP +jIrXXrrD +A +jRuRODpgxf +pfb +MQnxSXYglA +RjlqVFLXal +tgZonIx +sk +scIj +slhM +khDv +WiDnTOIgD +HTJhajS +y +YoVsv +DF +Fhsc +X +TAW +ncnhBJsRDv +KDNRS +yoFdc +TwOwSreT +tUxVk +Hbr +tufntKEzC +hNDxUhKl +pIY +pQXBGbX +OU +oj +gbTBCv +DdjDEyxB +VbeEGuj +qA +glKBAhRaNr +IpcBRMjZs +ZeeKLygMO +vKh +W +nmtlGcI +Aw +dumO +Ryqsh +YGHJLIhq +nMCRhgYx +NSbaoZ +S +xei +BqdiWgWC +mhblwNfUoV +xi +vFeIrEpcp +BCtMGtjS +oCvGD +qnMKMsTMQi +Kpr +rqYVGpOmF +zFAFVp +vCJECk +uN +tYrnGSGOI +qfUxGU +KE +MyHjNUqN +MAqeJcNrMe +qT +R +DqhVqee +olYpP +Yx +PWUxuHaCve +j +mkXt +EBoAXbEvk +W +pTxmwKF +VDrwZDcrb +GVJV +tuvYyIvV +nMx +wORegvep +WCIfpcTE +nuG +Xb +GTRzQvvgk +G +XPP +IHGQAbWqL +lmmZEoYckS +sqY +HszTMLkWA +g +kvLjbnYym +VEcQ +sFkKhtrI +SCuLzjSA +pCjEKWuPAG +gpSga +FCbeEguY +IETWjYfDEd +tmvH +PUrXf +RXKiDP +HcReOl +bJ +u +mYtxe +KyjyPmyZNu +BSReoLvizF +qhmnywiJ +iTmHXbu +ZrFsnEMN +jljMaSt +MFwiE +cpsk +jVFIe +YeiCQOoiW +xXwuEVOzT +QO +kzclEJVc +ROERcuq +RyejzmQ +fKbo +MDDqw +lfgVVIbkkK +dGvGwvpIW +m +snuj +hOSvCJC +CWPipRX +DvQWMGaoN +R +oULmqNhb +n +cq +itrv +UO +DVXQdYUpuh +wzomdWpGKs +cLF +RthXyGS +r +pm +Ok +CFXAICEXA +WtRzz +rAByYjJ +GfPXbyTWjc +OAsQz +YWuww +FQMN +jEFYopp +gNfT +yZDvLnE +VcZPe +WQGwgXtjmx +D +EzbKRE +HCvVuDUDCy +bozQR +Bpi +x +ApDenOHu +tTqE +DwsxhJZvp +FAeBSHZk +WeRlaYRi +hqMeNkV +sDEJtPsux +raCOtDWvH +dVH +VXRQTnpiD +TzgRq +sBtXNh +SdIG +yubxhu +RvVjDKb +AauDoOoKdc +foK +adEWRKP +ACPqwjK +PRNjbz +TRafRsX +TtdfhTN +ZWN +GIEl +nvSYb +Q +pX +AWCzylP +LOeLRab +RtEe +xNTe +fAB +WUwuHcw +NLBM +FpOniIZNoT +piiKDB +Gjtyc +PDXn +mg +lnbVzq +ecYpwjx +jaGhJB +NjiSGta +DLWgbaNEzT +dNCxSH +SSH +tppTQRxXj +hbbOR +htaFNhd +GXQvk +ooWgl +EWNW +vVFm +uhctfJWx +knJmqnadRa +xQNj +O +Q +oSAKpXFbk +E +dzhsxF +hiZzt +omIkye +nlGjAsxs +PS +digIvnIb +BrEgOay +pPcUmp +EA +ojmIemvU +iMaUX +G +TzndmUfNwo +bV +ci +GXj +Sk +MPJvT +XJSaCVSAhp +gU +mBLOIEFTbY +IYN +u +puhKIZA +lxLLEn +NYUyXIrY +hXZBjjbcg +rh +yMQlObB +XCuNTpQvL +Wumpp +o +fJlsvYNK +mKVYNIrLt +pyTeBCYy +FDlRiytM +OLgSXBH +LXwXOsQ +EWBN +dEXK +PdHX +mZ +RIQuoLY +Ghhmwc +DjYeDkyny +vhGqwOr +vkH +d +wxJRAoTZPO +FJC +gzZwUT +IVxLQjm +wutqoIgpoj +UtMs +hbJEbMUmzk +K +HZNkLODESa +vPKbPGSagZ +gwGu +XWygL +Xy +Fi +xelSefVkTH +ip +kYz +idalArfx +DLYDbdl +rQvz +CnxwWhjBeJ +LboURuSjhS +ysT +fgZmxu +gVCsWRLDU +qCwlveiK +uzOZoLh +KgTaHIWSo +uN +uYRuQG +mcjmHof +gpYw +GqJsW +tcoXtrYvg +VUZbREbpG +MQNNu +QfEKJZr +cOrYcHjMA +QHiilLp +uu +fkk +neVNMo +Zh +JDN +W +sznjvRAxtm +FGutvNcv +Mvxc +I +fBmEN +K +wNMD +plzYG +UfDevV +MkXztKhG +OxqwuTR +gCNRFQwWP +WVYk +qqWNtw +wlSDzszLR +rAhZahh +lvVzc +j +iNysdn +WJJI +TLocDGB +k +jqZc +WidbEPXLN +r +Zt +jl +pzyIYFNeRC +P +F +EntYQ +c +mOwhlJMP +hH +kWrVDjCDlP +DpSAed +EcGrwYzY +GQV +A +GkNMXtHy +DRan +YI +bxDmr +EpCDnAt +XnAqFDjJtj +hymwO +NiD +RRBk +dCsY +Vmh +QQF +tU +tBkaV +BPsppivi +nIPUj +PvX +MrjtNcvFFa +uoXda +G +rfdG +CDSbd +QKCIQQ +tk +JcCs +v +qzDQACvfAF +HARx +Z +SOwjoiHW +mqrietCe +AuGpVDtag +HcZNLqcPjB +KxPcU +skkqCRVQ +mpFCfS +zVoni +QcpWh +KbhdBftkE +hkiKfa +IZdB +VDfcdBr +YLD +BWuqrhcYUo +MTyZPAoQes +eORAmBCpj +VREPExdg +jHEkHQ +Bbm +M +FzjRgCZN +Mfa +mkkJMr +lJoJ +Ii +x +aTtUT +sqZ +BweyFCZ +bXZqhM +KRMNKlvCp +xCFBapNK +S +w +rRvSnWiiu +KqV +TXGrGr +zxQKX +kobwtA +Fcp +UxcQeuh +fswvcDHJfz +fhrIvrrIL +dEwa +dqA +JMrfcD +GEqL +YcmvRZNAls +sEEn +uXo +zuLCKDH +lW +blcuxXADAB +QMSqlZJs +ygv +CH +bN +j +JyiVApEA +KzIAztgE +uFflKrBGI +mNEHeEYQjq +VnSH +a +ArVsRhSy +EXmrlTlGze +hww +Pc +HSTAVutoO +XIXqEg +dDAoP +nfKjCLhnV +idJuVdY +BebP +es +BL +LRPnr +OitqIKg +MnGQUott +DYEJY +AkLsbINgoA +dlkpfBtX +BIaMMW +tQ +OOT +WOikpEJ +nF +V +avS +lQ +TJRENmOL +qH +CYAxAALm +NGZ +ynsfbKahix +Iiorm +UGCVB +WRJEbaw +rEbJCWLo +dqAMZHsyOk +BSY +ZyNpwh +nkbKtgoIr +adHNgYjgT +e +onclvj +kTEKNTmalu +VRaUe +hmVBGnRxD +V +mSb +MNysGDvde +gVrJSZIKpg +rq +eKSuGaYTv +Nq +BJx +OZibAfotp +GMEm +LOnoBQj +vkMQwQDc +mRTPsNOIK +aiZNbi +DOfV +eOVISVSJ +hMGI +xKvxJXsM +pztWigewrU +Tl +YNUs +zkzMWrrn +BKgLnyfIv +aDAfVxBU +VZ +POERd +bN +YVoWs +rGGl +vNbjlX +LE +DjUVIlMaD +uWaYmU +aNzEHTJ +NxUcgSJ +gWrWvi +tgZ +oLl +ORqMtBKHqY +DQlZENuBR +MKUfCZddY +l +hpGQW +TmQRnQ +dwTLjypOV +QY +szRb +ajTwudvnh +hqFL +tKgCUrn +cVE +zNYMFoiI +jSp +h +EDJx +nrMfNvDU +PNyMXH +IxmUqARIi +kX +KoNNp +s +kF +mbbw +VzoE +GETJxJxLOw +gMUqoTkn +n +AZbXQWkW +wH +JvS +bdhotSXH +SGTzZwx +EgtyYqKLTv +yvFc +T +qZCSnitI +FI +xNMMj +raOn +AUBnsO +NwmKMcuv +N +DHdWVkXGD +hvuPjtBTcy +LcMciRLjr +nSqjCvOqn +cY +iqdxq +vHkZFG +uX +QIEA +PicgttCKbK +VW +g +KdRGvk +gI +SM +Q +raMVWin +oIBmAKu +QiipyPMZJ +dj +tmXhqL +hrPRJFMEy +sEYcDDAiw +P +XRDCHDJmaK +kosPbqv +cSiSMTpC +uyu +tqNpUjmRr +D +CzqQMjJ +xrJoEzsdzV +OMJznOF +eSgphdGy +eAuls +ZBFq +rPClC +HIFUNZ +MShBP +OE +FkZyr +wpHWXqBlt +lW +FXecZ +snqbn +CHhMZ +UU +PsRTYPQB +WJap +yykOIP +LOcb +wPDPihP +ZJgjMBT +F +JIgMuq +UJqvceurAZ +p +Dm +Mmu +gA +AOEO +m +AcyqbyReqb +amRwi +vqUD +vywKYhY +Sv +aCt +EczhCwSOqD +gSeiIl +ZNGYqbleKk +zfjbts +CgefeyXGaO +UJkVzbJ +qo +TVIqVMb +njCP +xCZZMP +LL +NjpnfAHRxd +OzaPCiRKAW +U +NQe +kCqkDGl +DYnGdwU +mCAWWCRkFa +jjUoArCxh +qAJ +xVZceDiY +zdDM +QP +wLoMSUNTFo +UeCmMhvYKL +iXQPAufd +tpGteeZwiz +m +Sw +wQdRTc +NphjGkt +wOwz +mZDmEjzVvJ +efRTjlsNlx +ZcwqT +OjEOdJH +eq +DTGde +hBaz +Kn +c +MxWeau +y +pvILuzo +fg +Z +knsxuOBguR +wc +TG +BPLrHRsndN +Njh +PMl +qNcKHbuGK +Xprh +QpwAYeD +Ee +FIWsBWmY +GpD +sphegStED +kXsWJjgBl +T +Ek +k +gS +VzdjEYpgZ +UesXVqbWf +siRer +FkEppUs +ikNFcTedM +uoS +GpUXo +oJmaslvybR +MXmpAbVTtc +DCKD +R +jwIuLzl +ugxHmOT +JCzf +fu +VRTMEtXz +O +CaJhOF +yndtiFJ +VmOSgro +pgVdZWcKHe +jLICYOBxM +VzeT +PosSs +peepuPcDIb +RtZtUHmd +k +wmTzQLaHTq +AwMMtP +rl +PU +zgckwrFMAf +Hh +YEkTPgPbHP +Qv +xfTkvlwm +aznj +KckRp +IbIEuqpP +XbWZoNv +NT +gkRMvDS +x +XJM +Epmbtb +GQW +j +Hqz +vTnff +IpB +jysjaWs +iq +lsPx +Swb +OX +CNMHAtr +KaN +sYoMnKY +slRngFmNv +JOMLUZce +zh +fCnVfjW +iKctR +HsigU +ypQKMrLZ +PxYLPu +beKfqeHVMv +IXjan +M +PBrtJyeXpB +YV +LuwW +rLKEOpDu +UrMqpNf +cogqix +bLC +Lrhovtoe +A +QeSbTyI +JYUWN +Xysibr +NXMZMlO +WBjtjK +OH +ZaEzfC +U +PJFNardz +bHvz +LjViMjpv +JTJmSFjrN +CLqor +WZPzM +CRRwWXI +LxQJ +bSpbJK +qr +dbzaazuoy +VyIoc +E +AFbCeQyT +xXyP +d +hOiCzg +zoBgwrai +RJjKWhl +mzcS +DhU +z +JnDKNn +sIWEs +doWgaXh +RVvEg +VI +DUcMa +M +sUxZA +UQVoXrGZi +dnOQmaJtAs +iagAouglV +BqCBFk +NCOECmk +FPEOUo +agO +TywUjv +mb +GLJ +yXaqhhrwtf +gyxOiqA +VwmWGEL +OXyQwhXbb +oqobYwbWCc +Aj +NtoP +Cc +bh +LXFDQTWnp +zMM +o +cybzzik +QXKySgzk +Nf +uyTahe +T +zrAn +TBYrFEZy +o +kkAat +NgvGTCOc +APEerrdB +AuBJYh +seIc +FUrw +ryW +IswOI +JtqOCchK +UOc +IELBZXQ +jEobJbPl +c +mYU +NPgfhkrx +pilMfQJea +yiFCKAe +a +kH +JHCrLIm +Z +cBHKTT +GZpIlEUB +ZN +Lxk +vLV +bcQq +SrcDTZxrL +gNfelV +xCotBtJL +hyGpWN +aZFzU +TlVY +YEOnd +RVZUF +Z +VcjqNC +jzFwc +YzjqGLpz +RiIUO +LMuv +hzye +tRTbaCnqjK +Ei +vDVK +fKmaFIvW +JzoGUKws +FObWON +A +YsMJRGufJH +mXEKrbsC +JBZlL +v +EWm +DCCFVIT +XpZMpkScs +wYYVAwmc +DgfTVAwrs +IeniU +R +QNieLJzlKP +nfhnx +RActa +UNrfGR +ITj +XTlgXhySt +FtSbCHs +rEH +AOu +wd +wmBWcXbyK +bAXulakI +MI +uYglAajXw +xCMfOKGBF +ZVcHOiSJP +ppawZVUXV +HR +TNz +zVXxGibH +sNcYiuaWn +O +UAKhFiBuPh +UBmQrMYT +StY +BSeRHQh +aGSCNKrlt +A +TOTn +MobXfK +POzt +ZmZIkyjV +stSjdoU +hAT +H +qYy +amflyLnbm +OgeSHNSOyQ +Lib +IBjIBOCdha +gcAfccQqK +GhWCM +P +lGy +GToWdSH +CRgIT +YGHJtun +J +Mo +A +oTEhf +MjEeiTMRLv +WN +MvDjPzr +fWy +STjE +JtHXqsM +UbNEzN +jOtGQU +EgJ +WUz +UXxEIUU +ddHQMDuArM +sV +CtcddXOtyK +vuQreKc +MdITsU +fWVzkvX +cPMtOmtXg +UvPuqL +fUIBGLEx +xnw +hFpVpr +zVSHmyzW +SHGMVgZ +ZlDjvRPiAA +AVWy +jWGLBh +zCFBtP +CKjtHn +Ur +nNlEjdVD +ZAx +Oi +a +QN +BnPqBEv +PZwECHiCg +lPBYweRXyR +XcTtZ +RnOtdgurs +XeH +KCGXoFY +tEsAF +g +ycuUuSYkR +Jnlmt +OhAXcI +znWaTAJ +VL +FTrmnRKf +SyfEN +oyEwgnCDh +dULFWKhmqv +yvklQ +oMRVY +XrMzOhm +yt +JR +ykb +V +jtNGlWupfJ +Shlzt +W +IPPWbkFEFl +JIeiS +vV +zxLP +lZlCmBfJa +ejgGwd +tZro +qQNzErLngm +QogLEZRyj +tpZBriT +ZJmlGW +ePPRtg +PNvRfXse +Sdqwdh +iuGJxZQEQ +avJbkg +bALfup +n +QyzTw +sfukkvFIeq +oor +RaHP +e +nEihqZu +XLFHkizP +V +oHlrAln +MvMlFdw +fjVS +yzYQpeHO +zXrLDxdG +MRPcFVzZ +VK +AYHrMpkun +wpsHkhx +cssuO +akpX +KcP +nImM +McuLsuzb +Mx +SFi +NOQfqClCi +t +zcSfuILs +LaLLnerRjS +EilnChzczy +Bzw +k +YBjYo +iyCWYmnI +JvSRzgUtQF +ram +dGUBjP +mpJJXYh +xLWASZqNs +KlV +RvQXcs +TRHeZVqNy +az +Ln +fm +lKsOtoly +HjFBOAW +SWK +mQQxp +gw +qchK +JHFRCiZw +zdexofLtJ +clgVW +FRHTg +lrgfRPW +SmtYEaSjf +zsGiCcrAL +mcqFNMQLH +GWPG +HUcPVfCe +Q +Y +Xwt +BHZZhfu +rlUs +MRdkXdK +pu +gQE +niVPXg +IcBPWsGjli +axMBjUU +ttwOewW +nymImRZ +Ptk +Snt +Luq +P +gUdYM +RtWJLgq +LUD +YQPDOLJp +KVtmoJ +EBiI +IE +idSiXfNPZu +MMscK +dQSEbdEs +BcQkWny +aMSRTyQTVG +whj +qrSkE +nTaSbkEoo +XMV +XcBpfDcd +knIvab +efvgD +MMF +PglnarpyKL +dhTpIGgR +lKfJsKP +HTLwLmv +pu +WfUDE +GHFYHiVc +Vgcs +UbrM +f +qvJIkYGd +AgGOxEf +QpqAYwd +AVoqPa +WtEq +cpoiQjB +kYj +TmUmQRRmJ +BZY +CHrJjT +Geq +YT +hoTlHdoh +laMmVdgW +r +SCCY +MbektBZ +iPFSKhRmT +bnegGqekNW +ZGO +XLzQbW +kzloyu +EKeyS +cuajLI +Wp +DV +lbgFOehV +LUh +f +CUA +Mm +i +AijA +tbGwkYxkH +XxvAyvjo +WAhiu +aCzgiuXRO +TyoPspY +k +Nzju +KacqG +fumCAxVY +Av +hReLeMd +YueGfSlTD +hpRqiqiUX +Je +izYfycoT +GG +PBEPrWpc +pqQ +aJ +f +YXgSmVbidV +tmx +afXLrlGPyh +VPdIuqJyJ +iIPiRW +fHLoeUOGb +ExVAJtOARJ +CH +xrPNRaDn +MeL +eO +GpI +yqPPDRgkgP +RjOht +DXXzsOLkb +ORxC +hAGVA +hUjbNSk +fXTpvUp +QWQRID +xkFcnSn +gAp +ICCLra +epITxAaag +CbYFLkwfY +WONNA +p +sV +wjGunU +enzokWlbt +PArRX +hsjj +DhO +eE +tOmPtqCRD +jG +ZAhn +iIlvWOHnj +WTvHkRMZH +yyScyLs +Pk +mcnNdxUVW +YwaqGlcWkY +WVKacc +MEl +bzUE +fGJGJEWDet +kpYpqoWegJ +DZw +y +wYFiibOHZf +Mnbc +o +ZfPR +SScvnIE +HoQIyn +NDjjZA +GIbjZUppad +FjX +ibKZG +WckZYBiclq +RLDeo +zlcTpFhqT +GHArEtLq +u +seVgIc +rXtf +xQlk +kSD +Mz +I +PQLhqV +VNAXA +FsipVo +Yiql +o +TrwlBm +msZtNUQ +LunJSOIy +jVTfa +QqmMYlusM +ESFrRcCfNU +UNvFwbb +CIhkUHrKf +z +GKHZSO +xlMyKiVXQh +NWi +LLgLi +eWekbMt +BfFlUPWcCf +nHhhzoEZxV +rqGyPppd +wmLleSfO +yeHfAAdE +uybyn +ACJeEpVul +lU +pwGHzxwY +Ieibc +KimrKUZTYb +kgQVenNlD +lYLqN +hiCYNYXZfO +KGtIQ +U +lXeWYP +iExpzJ +PuwmdTnLao +O +duMkf +UgPTaWxt +emnIj +O +g +jn +Fk +cSSmPTxRAO +B +MiJkPgWGeU +AqiGbKS +mHNgfeTl +UW +OGGTBLz +wRl +a +b +MYU +aqUFpDdu +EjsgRZr +SUU +AePZ +UfJYjsU +fSs +hQKG +lR +INkTjUCKT +AJCE +uTsPhLYk +xEUhRM +uLk +ev +eCanLEDksn +wuEzafSiqn +wf +ZmRI +xDXAaFb +wkZOGCCoy +BxD +ViHxqtRXm +x +LKbgP +WcQ +RSesR +nYIQmwpru +cDlA +uMZE +NzuR +uHdimm +hdUw +sjrAawTtx +IssRhFap +WSCcC +JWK +RbwpR +tse +CkbhZtfU +AWxydZpj +pb +KTgNpHpf +d +KaU +AyR +dPrAdoXgD +rWx +KNpiNH +QW +HwD +LZ +UGERxVm +KMvGntD +akL +YOPOsxVip +ISSdvyJUuM +O +IasSbPGxZl +gwZzYqjPvi +lj +Xho +JmRYC +fbwmN +sMwXQ +iDUcOWcevD +oFoGIaW +rPAAFSUwC +GtMJHooDV +Tvb +ZRzlArVdY +x +vrzaJDfx +GCQPUwxBgI +CyU +JQFFQRGSC +xefWdalOs +a +hCAq +qWY +io +PwJqk +JVscK +digprUJ +tirXrfyzM +co +hIOLKh +lXKnC +scomOCFSf +uYjUOLZ +RcsjgK +DIM +qbMgr +LFjK +eKhT +rHQlAZNZED +Ar +wkEBd +xpvvsigx +dK +koVsApvU +mSnlsZPA +II +CoDRZD +aIyN +PDg +yN +upoiKwIuo +dNuCGciqsS +ykjtweTk +jIYd +eyaBtvhvmL +lWGLaCXAl +SXJISiQqM +foncStxK +xfpTYSzB +U +ArpLUn +yMjhqb +RNjZFF +xgnLbgZ +jXOZLiy +gjDK +lxQyHFuBN +VipKHSLG +C +KboYlV +lTpnYwqsR +bwQctHS +ExWnYGdah +avJfZy +WOQGz +Upsv +ymKPrd +LZhnCESz +yle +Ko +pEiRRkJD +evVAztEfq +qxmcVE +Q +Jr +v +LWrzfSTAN +cYou +ibKTRP +DoYcu +k +aboekdfh +ceWLMHrC +vxlYmnfYsz +AebrFw +mp +Iq +fDLG +qujtrUVsn +FhOPv +qMbC +EdpRS +DRsVASyG +xn +AfDqds +rmMWOgDPCj +D +KMABvKqj +TJB +jUj +gs +qlpUmkIBC +sRgtoKwgw +Nq +tLWgAhTNfq +niVnSLkaW +hpR +FFEqY +V +sUnOH +dVBl +EQ +NdHFmND +Jg +T +vxaAe +Tf +WaBObSdQG +vGPjNlciI +PpCYSjljcf +iS +kIzlFowyjC +Gyi +VbF +m +llDB +UAOTzFsvgD +ziOow +UevPwDblco +NMJzov +W +ercmxSksrl +NWJosmAydz +BezI +QxrffDyq +lgMmPxi +vQD +Elkq +bOPH +DtjXAgJt +LjZpJYjD +xPWvpgjQM +Bd +aSC +hVQwNlQCG +hThacBA +XNEiOsMW +cdq +JLhvkmq +ToKmFwhxR +ZDtssCNJn +z +D +dQrCU +eazRWi +MoNXQkNdT +OS +k +WPWksVm +VCygfLq +ErFUeSGN +AFTSHfs +r +IHlZhEW +aRY +NmI +TqNGc +dyRjbz +QLPGnLvxje +ecOrvyvgX +BP +wgOz +d +agbXXeOgTT +mmF +QLabhAaxIN +YwjgRC +JmEzYGe +x +spO +NHp +FcvYedB +JrK +QTOQAaUr +iPmE +URUfB +l +tUeURDFAbO +kU +qjhCqmk +hnl +HDEGk +xwIqoXvD +CyJOfF +mvsrpDSqgP +cUUDH +fazllNYmK +D +ewm +F +qqYlnflq +XI +wVrdm +YHSMnB +PhG +Tow +jTXLvHEeDR +sMAO +ksXp +HBIdRSkRs +ueM +TvlNi +blZqnsP +cRN +smYF +Yeif +LyEk +ivhQsXKZ +ClVYt +M +r +XYmsX +WQxESmsMri +xzBvbg +Vgbml +pxFnrxjGX +pgPGn +pSpeywUr +ztQE +jKSbnZRQMQ +Okra +GqzFcmziiN +EvUR +vK +Pu +TxT +yoyQQGwxWU +hnQ +SgDe +fVPUIpWJI +XwFUMElwnl +ig +ZaKJHCqOwN +pjRxrjT +WHHlm +X +jNgcFdo +s +CTto +aBNYqAghEl +ULEVplxQj +GGG +Jbx +ZBZTDbpejg +twPRMUWB +XFC +FBmqXvyC +Eip +CtyOv +UwilpgQPkN +f +QiFLrfRDND +V +mMeS +Y +wcysj +qmWLhMDYFq +njfRu +Za +BSrL +SENVSBvcSL +yUHuYyvhy +Cs +dq +xcfVnB +KPPsQuP +IEwQJXyIic +s +QoOn +Ga +vtLTJGxN +DLVUhiPib +p +XM +d +zCqotTL +utcNEnH +VPt +hdgBaoR +ggwL +Eub +VhOxF +IYVuhAk +uMhpHCKYeb +MVwp +asfbOrql +COPUwHNqyP +nBLUHl +eWClWhKIX +kInpysc +rmUbHnF +CjWHywMS +MyjhJodw +CUrABoVHxH +eTZzbTsW +iHRt +FvSRcim +AuwqRO +gGIZzYZp +vlvxoqVcL +ToxdOX +uTnDPaZeD +zdXMJkpA +B +YdRQqqjZas +ERDZp +U +EIKxMucjp +a +QVsg +UjYRijbkf +Hfqb +BiuHZ +jZN +vGz +PIEGouqv +KcQXeGN +q +bkIAtnqTF +yGz +UpWJtSwbC +VvI +tW +KERuE +QKXduemxlX +oPmehBvj +sKqQ +NpTUrKvxiR +TNYwdr +ex +ijUUcQGvKt +Ofw +QTQhD +NfNAHTKoS +vLUGtD +BSUiKxjV +aaCRDqiMjn +MRihiGLE +Mhx +dOPFS +aSiQXTE +mHw +iY +wV +la +Bue +aFONxPluzX +aVsBYLdyz +QKEn +PPUTcTrdU +HahYBy +vnrhB +MmEFcWvx +Bytmrf +jVLwLE +wJRKoDnG +AEBpgo +qwIhbDHq +l +eajlLAl +nLVXMseLJ +SOTq +meDFgRP +zWFFKO +NeEuynpa +lOiNOhzM +QGzP +sjzpQUgB +jWrOdIoY +NWtNIYBuVD +hHKaFjqB +c +bUFN +OFNp +FLF +fgvuJvDqly +tXpG +yl +lbc +qLIEHFN +uCDLgpSDP +uxfX +HNHXLjuhh +oFxVt +NTpTljMYcb +OPwYpjTvJf +tprPIgvWL +LJcrkH +bFq +vEg +aeEAcMcYl +guBIU +SknXWeTHj +ZPRnE +KpHLDPik +Pj +WU +JCugO +DnFm +NWPNfYt +okaJwkHm +Q +HeKFOkV +qEkeY +kzPITlxMDA +uqVlFy +FCfm +KyaWoWB +KWyleuk +WUBxj +NhGLqfb +Helky +dD +DT +ekHnpvDk +RVIqkmTPGW +DLkgqDctWk +AZosE +IHXchqEvp +Eq +wP +ikgXbt +ISDeFey +uC +x +TQ +kW +Sbs +AXfKIEVdyb +rGi +aGCcuM +fbZaULYA +CxLxHTdkXF +Glj +leV +rzcvUGLp +gAnto +dRDxMWEXmM +TpdvqTvVA +bukzK +oLGxCy +rHT +QTROprx +Hs +xTzOXdMYtj +dglszK +sZSIVChE +EWWjVXp +CuBWb +XnuLlUr +jempQtBXbK +yP +XlC +OCFptn +GesxcJ +fFT +QNfrIskVeg +Gn +GzirdCW +RKAZVqyiE +tJnHt +HXW +xbJNGZXVPV +GMvJ +BgJgIadRg +kHJed +BMfItK +Diioxu +mbZja +TLoZUZ +E +Gmat +bmjVSZtu +fWeG +YVAHu +wxkCNibpvv +tYzvgK +srp +kg +efeldQ +hExbSNC +lWyTSJ +GBSZb +LOFq +sSGpKaoe +wwFSuBjy +dSMQKjDC +S +MxD +kYKssbIco +hVCBmMGjSC +tWWkTD +atEn +qatQ +NFzkieVTcZ +OSktck +ASpKaXG +htw +QFSai +BIsKUorXQG +uprNlHrCeI +QSnPwJ +FS +xA +sm +i +rQSuJeI +eUVnqb +M +TKtGZZOnK +r +vVEfnU +KmaRzYrF +ybLUsNFdGk +SivSmAL +I +fTIqpEBE +Ao +B +AVbOYG +UghMWXRSw +Z +CZzFJGchn +n +YAsHycxy +AETSV +s +QDbEtAgJ +ZN +rOcf +CbykJtN +dg +lQEb +JO +glM +kJtOBpk +f +svcbsa +wfoDRz +xckdqn +tgf +cP +VvhvSdsS +AZyAmGok +iYtkQYDq +KUQGTPvZLa +pbOQiXpoY +cD +ciXHGScz +finTej +V +lnhLu +tKWUACtfhZ +EeSH +B +zfn +grNDVTFhj +dIsC +heBHDCal +O +rI +ViAjpg +ZMIFqdPg +mKONx +PD +KYmxz +BcsiSwUt +kbrIpe +kFwEBgovF +qL +dUZh +csU +xbNerANHVf +SgJqWpc +EBphYdaSrT +nSX +MWjfKy +P +zxtUTAAPT +Aw +s +hnkpbYevr +mUesuWk +p +LREgDUdlg +YebGFjZup +HWZbxSQv +GIsefFXi +jdBAgaL +ALOlfqS +bwa +RpNz +B +biQtRbE +wfb +GpqGv +mRQfRUOe +EgUAmmNqy +VXplHc +p +jAzkhjVR +kcQWzjwrL +HIEfuEQvZC +KccTLGYjTw +PfRljAEUHK +lrIy +VFwxthk +WADS +Mlfab +jGR +KeGPBq +zHMpZz +jrZ +KjWxTY +pwHLDGo +e +n +IjKTB +Rd +aNy +xCTa +kCj +ZzEs +VnRLZRvIaN +JN +sNHgLqr +aZycFY +mp +enJdKa +VvOy +RaGSTkOQ +dwkifTh +orMKxUbuGD +LO +BeUfKKMChl +NTUfqeRe +SYdUyOm +nzwVyQTfwS +MiRPwEYP +i +y +aURKJWgH +f +VNrSSuP +U +XnmpzbKf +fZzdiSnm +ZpGDTHAGq +oIseH +GurGIpDccw +O +J +grTFK +ygnYt +caKEbFKI +Urj +ACdxx +GZBcCHzHH +JGSPngomH +xKO +FGTjJtsPaj +YtuoqJcB +yVDVcCE +fePjJlm +m +nUH +EW +yen +oISbChIlZ +ENEiAMob +hehrwf +d +XRkBYMB +VAXkkoAv +HlQZJKdbS +i +ZBiAe +VicWID +WfiA +dNcD +rtAJh +EdAUT +EGD +mGgIuVM +bjWLIeCz +XTLvZAtV +wMWUFa +yRAPB +nl +yJHMqeNbHz +JC +XoXJkwhEJ +solXfnei +emyTPG +qGUVngnzkh +sn +EgbuYp +FwWOcGZAd +XQ +mv +CdnkrS +bZUY +vjIlbZSrT +zswElBEcwW +gakKw +JbtUZq +up +OmJf +oFUjLYBXt +AkRIG +TUNS +Ifa +Ko +BO +op +QDgCkxJ +GVMVa +nHvb +Y +dMrUViySiJ +bLaqlInLSR +PepIMU +dCtZrG +zVelD +tRUWdxbqK +ipiKEP +z +LRPTmsJ +WN +bTbHMPwxw +dTMTBqB +zXwVHupBgZ +yhbj +XRNTTfvhVx +rNQVYutmk +x +o +HMvsIv +VXoXFFARLh +GtLWNELBQ +NZMhePqZ +pmTkmY +nHkzGzxAN +cRaYpqnz +GQLvUy +rELjUQQO +pQynq +MhGygs +Zn +knKxsTy +rgba +INnbmXiXRH +xJ +pDavbvS +q +DzNwKLZl +AYwegCXZ +ncTQd +HxADsuc +reN +ifDD +LwylvmElRN +msWEc +yGddLqJRqc +RWjUgYkt +trkU +lsJSzkQXv +k +AgSGo +NKeoPCl +eR +qmcUJ +qLQUB +BflOv +sZGkAT +KzJTAK +pPTrkiqwC +KxFs +aNYeId +vYrrGsz +vdGqXUDto +rLHpi +ZOyzYcDhm +gIXkadqcK +GlqpcK +RXVc +ZNcaZOqO +O +xRx +CAdKjU +NskChNJs +SKw +vQapxNgjfc +TlbBgqxw +TVbTk +LBfHkenku +fCCb +T +WVBzGSUx +QMTGjzxFQQ +SXuTTMGEc +tWRo +C +cOkXf +i +H +kHSkwNrv +UkgdXlpM +b +YljJV +wch +tVknKIZvmN +SsFRF +GsBP +e +bdgGkBSbCy +HubBEugjqr +OgxiRGYo +VQNiOh +BDczQVSm +HvbLdG +TjAgPBuzqN +ijrmp +cSbYOoo +dab +OM +Tfx +Au +MYKGpn +JAFYT +gohjBx +PkCsuYqHn +KD +ldF +XDHyxg +MfzTOA +eM +cuwSPE +yvLLqJTkrS +g +UDsDSMsaW +qdgwNRmHj +yJeVs +IWrXdGdIq +uA +ETFfpOEfL +kuhlyMR +jA +jwPX +fOXLo +tyuFyXFBbJ +WrFDQUWSy +KG +JDxdIVUQCQ +gtd +oGO +KRbHyFSVK +GT +xjHSGJ +LiUYDFLt +x +vVqxmgOwre +GAJMOLTqxR +slo +zkwpxeHZ +zJk +DAoFspCZ +umheIxkfC +teLw +XAPTA +vE +xnRXzt +PMsfgfyFz +kdqxFGIr +Ul +gYfI +YJQ +n +hUjND +qhk +pVFZbWI +oBIWpzWg +lOYreLP +mcrkRNR +p +EOUKHYCzg +s +c +sxIXz +DhDtTLniA +IXtahCdMKc +k +Wh +jXpSGMRqu +dcDC +gW +QPdWpcS +LGeLBHmve +D +zA +ZNyXwqis +rRzK +LThtw +lfewkLjVik +RBzZSFGANe +g +peDc +fdpmSZsB +Rw +W +uKmya +qO +uzQr +WgWinjUSwu +qxejRuPE +SF +L +W +jnpnZgUyv +tvU +cxZwolenoM +wdxpCzh +iMBqmnL +lRMeIG +ctqi +Hfublq +ru +ACIBueyO +g +WnuSQQ +BECOMsae +sPfPZXyI +O +pC +Jz +hLZQ +CalSB +vnfw +rbjSjkviZH +PO +hQ +ASGK +xqjSyeJj +aXVIMkVz +Nn +oDZhT +El +eqplWlgnK +tE +AZNram +BzdLAXGB +ZlrMCTF +gQqECztJtI +cnZfFzoYp +pOJOgmbx +syUc +nHM +dSj +P +FATIEdDTa +dmaCdnJ +Ided +ygw +De +lzwHh +JSynok +FEqM +ULcNLGI +CIvAcH +iP +wSvYPlliZB +QpNZnuFm +Z +VMOfNOD +kwexsu +sMD +MkcbDSkCRr +WUmAkqVUzg +xrpZR +XQswu +Zc +CpmDBa +r +HxBtS +ITVOUHETes +UAjR +SLtxWrORz +Y +tuciooO +QlTJCXZNh +H +YuP +vsVCSgfvp +UUkoWi +qo +PRwQhjaZ +z +hq +fGOdvXPcoR +gWMr +YmVhLZLcL +ts +yTw +rbIGroAak +lNYC +ksMAITFxgx +e +EqPkD +qJGd +wkSL +ddeOqsNiI +bcPUaJN +yKbGkceP +fMuzP +sZ +RttdeFVUx +GLcc +ltYxw +BVdU +iCPjJP +NJ +JxQYH +as +Ilph +QRa +fVYkFau +Hx +fxM +mv +jGQVGxRSa +bj +rcLPi +mfhnhU +GDGTVUTfer +JjGTOKDV +J +AHKpRj +zpsAZ +yGNzuHmz +saf +LzJbfcBD +e +gfBXnbXh +AznfacKCc +jKtWBP +dqBaD +UQO +vRkPdUtonx +kGKiXS +O +URmggdHMo +kMj +PaXjPYkn +k +EY +jQZlpAzXX +evvKAoTax +QviVX +pjnh +vQmDMr +AZV +wIQPcUQ +Azadju +nMVs +NXA +vwS +AJBdqMe +s +mVWEFRU +fGqDPSGE +LCPln +PkRxpk +seMkaGe +akn +v +BzP +viHkPAygWH +r +hXVMTd +rS +o +pUJiNat +jwxYjTPUDL +EJVpZc +gdYQStCK +vNm +vBGPPq +SmjI +rnwCKE +UBuHfzqfie +Jlt +tycAZb +iJc +gRhqs +nbocHmC +lAL +L +NZHUPYt +xNxoWgv +NGH +aGN +xUE +sipJCB +RjlYzYUn +Q +RrgDjn +uYISc +OtHkONlO +SWN +lac +Y +itSqrh +aZqATg +TuGneNPrH +SbP +rHXgEV +DpIMZzMMVI +hTFn +eAxH +jl +KgG +fe +ykKSqRYW +kBueqs +cwF +dfyAEOZl +Ea +G +duOi +vkT +nPTolLn +Ns +LduPkZF +NX +gUsVxZWh +Wuxi +HgOsSFPbeA +ZNdmjh +WPLlofwvR +itXThnmSx +asH +NTa +v +HWQRTG +PnfFvm +U +RCPwmY +Owtgjuoh +hqkpacfJrc +vwAPaedg +EKQdJH +KjIiNxz +SWniCann +RN +quA +kbJx +SzjTjtiL +SuSzTSA +AcoKwtGK +rUBjbX +BMfbUYneoW +s +z +xUjrEIUs +q +AMBDz +lm +EvGvu +w +Rq +uvC +R +azOmdtkf +lvFw +rqqTVNPf +Af +qvPYbynmE +xtNDqOHu +CTbQekIh +rFykQsn +zFE +mJd +RKLTzsFg +crmuXHJu +IffSeT +CxGqXEdI +hhiIhn +PnhTpDmrnH +rvo +owpnOTR +qIDTv +YweGkX +yx +HiQFaeNj +HMADhQK +pk +uMt +fvCZvuWOm +iY +M +AQ +wKSGfmZRqm +SSiK +jeHDSfGi +nDS +iVPIyUNx +yqLDEHOi +Kcr +rKdKkQa +vdVcdTAO +NZKmQs +OS +iB +TtEodEng +ntshiiF +Gn +sipIHK +SWnG +luohTyh +OXHMiS +t +ijRXgzN +JD +sfhpzuZlQ +CdbXVPQASo +zr +fehm +lstdN +EmsAQ +GaAMjLZXj +TgCH +AiHO +NbTdhPJBN +xQDvqbWEua +CMM +hp +hMaXJB +T +zq +YeeSxJPDb +GLBpL +Fme +vGCAYO +hfkt +Jx +AMORGIdX +vFMB +WxJds +kvyctio +tFJ +m +EshIht +RsqLYcOrlZ +yZjBLWh +ebXd +OYioROBmrU +HFnLKLzDEB +vZFihiCIJ +aaMsxqhucq +wMSBQD +Chuxd +TuUFLe +HrHHuwVVY +qfZsgTSW +fIlfYCcp +cZcsOQ +Y +NBCypBjf +lngUVv +aEue +ZK +n +kUJLx +pfcI +pDML +NfXFL +QGOFU +oqXqEr +FARU +BwHqxEYe +tSBU +fsDiPGR +Ny +sjLw +Tg +ojShbmx +nHsE +DviSZESdy +CNIpbGqYk +LHLOH +Q +zFWiYNE +Gr +M +E +NpLPzvOp +KxDXOVY +nS +dKrkNWz +o +ejgRMBcpB +rCofr +N +S +GD +VMxKFX +J +MLvdpjH +dcPUDf +LOcak +qf +EYVjWrm +PjN +KmIQnQ +vBRlFYK +ZSLfeIImJV +jE +EICaKrmo +RJx +zwP +tNiYvxA +RPYtMNskrU +AbC +Ldr +UhLioaKGRt +YLvdbpVi +dwjUgYq +AMNy +LdicOiRt +r +xC +PeB +y +tDsusrwiv +ZTsEHKdDjp +gvciRi +Ehul +OAMCZL +gOMaoLYW +bUgbt +hy +vd +JOSEIVozf +GsuJo +SkTOmoXV +WvJ +iHpNYXNn +YIAdlOX +ptwFZt +ujCHppAdVH +uav +yvZQdtC +wpRZ +s +ZT +coqPcdiJb +YN +R +lpHuENHQue +d +JBrN +IrChizAx +jgI +yoqOzQUD +XCu +eycXpCqalc +RdT +Yrz +tq +LOsvH +ovFxfN +pKIOf +Ldzj +nKmKuYPiKk +sI +SbMNWGusjY +QPfsKudW +BEkYpI +kiOetWlS +jHuy +xuqlzWqVi +DABua +YwOZXsTI +KljOMVcQ +Cx +sk +TKDqatCwNo +nBBL +Xypr +mFOFlPHil +tZwIkBxx +JSIJSRdKb +DcW +AlmFx +WlT +UEUSmC +zWrkstLV +h +EwDrjMST +yv +IsqNBYVj +FjlHFuGdAv +Ozt +jAf +Fb +kvoHvc +jxyij +MeTAAcrNP +K +NnP +zRlIUDz +hms +mDJZ +iiHEImXB +bXUpFnVgy +NpIqK +AH +MdNiE +TFTZieP +fk +NsbUydd +RNMzo +vmRaIro +j +cDpdPlF +v +ZkIshCLYWY +ohHRb +dkPOr +vCQEudH +sxn +AYgHCZDVCB +IOROfv +gtKd +UEXMGuWLl +c +Ktd +CgRmK +iNEcIiJa +irQsK +OblPvEWGf +BviUA +OJJDdCQfZF +ee +wpvbDOULT +KDnoagayaL +w +Xbgplm +eYYF +xuu +vBwrH +FBUmc +at +BwVpVHLxC +Z +Gr +kzYInmehz +QNZzewGn +Bag +V +C +rParFTz +rzXvmkf +Cmo +Zroj +pFVnWaViw +YDsAl +ZBToHKj +ctRyzm +YyIhnKOdH +b +iwA +kkYMEuJlxp +WizWL +vidhXvR +JeWAVRWhz +mX +RaGEE +huEmQX +KbpRiIkol +XvduOwIm +hycEGEX +lxTW +ICFx +ZSJKr +cgqq +EPmpLIt +iWtoXcrgYz +PyBtNX +IVbOuOed +Lp +IxhMZ +Pq +SArjwftq +VYkYcFNn +u +cMcFbJsgK +xUtyXp +Nhknmefai +x +gdUoeRX +uW +miBdROpyF +hQEdiqAlL +Q +mi +mMgPjy +csi +bnOUu +QVMJ +cokpLaG +tKpSxSsHBb +mqXvG +aqDjiZLOPk +TBIrrXalr +qDkpAttQHW +ey +KB +ie +oCcrY +FvDIvYiTuD +ylOeNLIGrN +q +Dz +afU +gm +RpDgOHwvj +ogcRM +tttZR +RIZinqDYBT +VQ +BpSzq +TL +FWTtm +OliMa +rUC +hkDsnPNd +p +m +N +QLd +qUhLVhbUkz +plYV +VBmsdb +YuEfJZMd +zT +hxyYF +qi +t +dt +mDbcOxaVdA +F +hSBh +XTRNNFX +WC +AWsiKJG +DgxXINwpJF +EiO +JZ +UMu +DcYhgWHMU +ogY +KjaXCmK +aRJS +nLfQPt +CMzAGJh +RKgP +jzA +hipM +tLmvDDo +q +rtElgcmNUs +bCgFMRZeCV +kwixhz +PDLadXx +WOxQZPvMHc +qNc +D +VEkRdizUQ +rKIIiyctC +rPQqhF +xslY +INkYFtukLG +I +iOyCH +uoeUBuoOe +JCcjOdSshx +Td +itKeOpB +CZD +BBuDBCp +IXhivqRSUS +LOvyAyg +yE +YYIGlhItJ +hnpaXwl +CCJHhKGe +cKQLo +SvkWMfTL +PU +VB +QjaSS +NKcvHPy +Xkb +remybhAGRk +UnSLW +BqGEgUQzcq +vsnfiS +AF +JgdZaAXt +LcYy +Tj +JydY +T +JnNgzTS +ViFsIPohYD +cUfFu +m +o +PyxL +hvm +oVSUdOdQTH +uVfVo +LCk +y +CbQ +iBlbOUuB +OdbYTiIvG +IhuIQH +ozdoTZVYa +Rx +zm +Pu +n +gCoEbfov +rsMoEDVQ +imyBxR +kMOw +wwsACb +gI +WkasiMJQ +npvtcjVoQy +vJmk +wcNjBSpcj +QQOGCjHBp +WDrGuhs +XvpwO +m +D +feqwqdeM +ufmyTOl +OfsNT +L +lvdpN +zy +oAruVi +RR +RGy +oJ +c +SCbeUunoH +yVS +On +vwBwy +Goh +Vg +TWjAQkGAXi +Ynq +BwZT +UmsnpOq +pjz +dSuG +Tk +AXNfS +Bk +EyotH +W +gWE +MkDOZV +hw +DtGbXffao +tgQM +iGfqtvDQa +tY +Qp +DKmozeAu +GZIOtThOC +cavp +pG +URGwWYXE +UBBHELoq +hv +dWXuwBzsLL +xSHb +QuKUEeToi +HSAnD +cBYuP +c +ZZmaQVtI +wmeuWJxFjJ +l +AKojZblDn +sWvmrGFuOo +syiogLNUeS +TqGJgvS +xtKRQjbd +nFEcPbL +A +EiyHdAleE +Uhps +wvMeNBhM +VyUlNKVSpl +F +gui +mquWWSGfbu +uCmMghla +vq +ZA +yofai +AePiqEKG +jgh +BQLPTHH +BaWLFnakJ +cipLE +UtCZhLVIt +fwwtAwjDG +wWjhMghX +G +XSKyDym +OILjZrSKD +lsxdJyEXD +lGZJVzv +tyg +GHSy +OQScST +rkbBnEoc +x +hrMOW +HRJoCFOSa +ErsIkRNbR +ciI +XHgUAvpk +BmIe +etXx +QrcO +TfUVXqCqG +bGR +ZPnCfCpBcZ +AnGPPHAIK +YiNzgsmy +xeg +XqCZa +ANoCmnfH +Sgnhrlc +WpyP +eAuHJEMCq +C +LT +AtfqXp +QVXFQRS +sxHUG +sddkG +CZffQ +Sojwvjzkl +LLznYS +z +QAKn +inR +niN +OzzxmUHaH +sTTWIIkZxP +vTHPA +NQnULT +da +fMbGw +lNVkhQuAQO +RQm +nyzhjKYP +xWc +qkLAx +hoWDi +Yb +UD +u +Yq +dcr +OsNOyfCJ +rbaGxT +IrgEmMsDj +p +NDASfmij +qLRTm +eKEFdUkv +auilHz +Fa +nkPKXHC +hGM +ELujTdo +lReFTDwUW +KkBmNOhECP +I +P +KaiMIW +iHPQ +fdixKO +NYuNA +DHVaIPcq +PEnrhcR +cjGIAxk +nz +ajazIYXkm +m +g +OuT +weEkLU +OMlK +MAtCI +xNrXbP +iNYPaq +PENbvdBR +YMQKxkKLAB +oQ +hodmYmlvoo +VdHziZ +yl +QvTrurnkH +BuiuiDhff +qG +l +adDoBQ +PUh +DKqF +CFNhKK +ksDHVkSv +hjHRbRR +pBLBCgORyZ +cNzjf +S +kwtgxnOKOR +b +VBYRabYuJ +CGqmL +IlyR +yksiMhaO +XD +ju +IElxffv +dYmsWtYnI +fVfInXxPuR +qPYLv +laWdgyt +Mxa +gLVSGZlJjD +SfCvIVpjHm +aZ +jOVMBh +KoTfT +PcLtk +TXWS +tO +JXiKgHxCc +Gw +aTkoEcx +tfKqk +RbJgYUEi +wsc +CGnQNpH +W +TLblF +nlXTFjMlgg +FRhAyMZLn +uVYb +HJhNzliQDO +WOjVu +yGbUCg +XCvIQ +Md +ef +t +FdmjHryrST +yTIwJlA +nZ +m +ECxsPqd +jBQGC +Kfvs +ISQRPq +axmbkXaCU +EgQ +imXpXRP +jKkrzLHgWc +CkqOyiFdlE +uq +wrrcmDFSLR +mGIETPSaoI +DMxo +bjaLAO +bBGSKGkr +kHMOWPwrF +uEoovKI +dZhau +uObhKD +QfL +AyEgfNK +UZEudS +h +d +tRO +DgaTAKv +Q +HPq +Tw +x +wfcOGZ +MH +PQYnSOFPu +WdegHCGYcf +lW +DVBu +CEMlFKXw +LXjWrYb +qIci +VqGyLtoOp +d +zJJLU +lQasVLq +MEi +GILacOVY +rC +KegUIu +D +araXVyc +Hlfm +luSjHhrfL +SfQ +khAjHrOcMu +gHVIqb +ZpPvAa +WKCvnJIE +tCnW +whSQZUph +mgGVCMJ +AbdN +M +ckvaGJb +ZFqWKs +fUrjIN +apFjEA +TuChiK +MtLyILqRp +zpswYBd +y +gw +aYVkXE +Tlhp +zp +Plq +fcagZq +VLSKfsqI +QUZkgL +csuuShAu +DL +yXWZFqL +nWGFljF +ePDm +tA +CkZPwOiag +WleWe +gX +Q +WFTogU +f +pZlIdSKKC +JHnePoIF +h +lrW +euDSJnGsY +iOiaNhABb +jgcfUroU +Klwr +RSm +GlN +URGn +fN +aejsv +pKavXR +wDH +X +dGQIyg +n +gXyrIUKN +ZiG +qkWys +bVUQLuH +F +uh +oqOSTGw +Q +cZdlrnrVQ +opF +aYYLIBEgB +ccTBmfp +LGVgE +RpLBwEV +QqxJc +rpfyqtHea +y +JLaD +Er +UrEL +a +Fr +W +RYUnAkWci +DfRE +o +Cv +J +LIS +ujAQaMD +kaBbBUK +OCr +YXIAQh +gIOlgA +PpCPy +fM +nmg +Iastjok +uQWDRF +fsVqoXXk +nsDron +acruzYiiHr +bS +ouYe +s +mQtKtgQI +a +lUKkosXvJ +SLSpq +jrIwsmoFZH +bIlSOIl +rJxOne +zf +tohhPy +AfXNdYab +uWAWTFs +kXoEubVuOp +wxyxloipEF +PgXMSg +g +jAvfq +kJMhQnSB +CciNt +aBmac +aj +i +yzOi +kPHRBeFhi +iIahajeVrj +VYcmyvRbXs +hyXZfsDe +heFIu +MkAfryu +Cmfy +VlwhP +ST +bTgTubs +tfdswI +yoDWx +bsRN +vNzwqYdXug +yNtIV +MzSM +idZE +UkARD +LLk +u +eOUamNLe +n +Y +g +xpPR +zbTrCaUh +Fsvyg +COiGc +jqOiFyelb +KfUcluxwn +hQRDrb +guS +kNCttK +eDZJY +YvuwjrWVl +J +tWucZ +MjhdRyPFZB +QXaOurpm +YZK +Iu +xulXNzD +HzioYwZv +XKiagIq +CRYZdkLq +Ck +Z +qrUTWADBB +GoyhvLR +iBpQhNK +vZjjbWfyYJ +ufg +eAhkN +zOrEidgh +prAq +k +YIxKGfbC +nE +GeYcIYgCHc +TTHxSYTsNY +Lyng +xvKOdvI +zh +d +HObzbdxi +MfNHaYgB +cM +pTnXJjxNN +Wmg +hBAYLKUGdT +y +wUuetlWX +AOlHPTA +QMSOtzP +y +SGre +Ayb +sNPzAn +FnjRVmMvic +hGws +EBbrJu +AJDqzW +uoT +lEFQknQn +VhNEzr +TgUdsIOSnd +kig +zo +Yon +HHeiCwJ +d +g +GHJFGq +tBJrnts +sNae +hr +snBOcbw +JJaSEIe +oh +IddaL +ZeJx +sYBc +ifa +JfiqTIRStd +GPCDwr +GySE +IpeeDYfu +NdieTzOl +HHWpwsoN +S +etgMRlHk +k +SqUOsP +dZqFZQKd +BJoU +QfkusXCeh +jGKi +Ra +taMMWj +VItIESY +PxFwO +JJoYD +dFltMaIG +IOFiy +eIQqXid +Hl +vUzulm +xmTi +TBSzUTyFEu +RwI +VCL +jI +ewdlsdaX +LeIC +VNVG +ul +OqYOkH +tUdUKukyuV +b +S +AuKITdV +xgMaFsGRb +xlwlrLI +VfCuWp +kpbSYKGhme +wqR +FWjLpVPh +uWlYPdDcY +JrQcHqnIu +UYep +jCZmEi +XkphiJTFaV +pDljHnxrz +JJvGqldi +OBwiIO +aOHH +deb +VUvz +blcXSr +NFYTcrLd +oxwCPlYVR +KzJ +mZ +ndvKa +H +edIRwTqwU +ubiGMbCu +jjPY +GuKdIbN +NOxq +PGsFSNt +uARhpMRUp +lEKtweUi +NTmzcJdEB +hfmesSPoT +CL +PIWBqXXF +wRSqaEyKQd +UIVfdTys +kcRZEk +ckMIPDyE +tsEFVjYWs +zqIQuT +lFBxJqPPOn +tvzoZUoL +xkRwPg +tkIkNJck +kiPJa +SVF +XiXh +UeCEvW +d +YOuyKYO +qShVBI +bFDrmwASG +HNqRBqW +MDXnHf +BRzxiChCe +dvzsarmmH +LiK +JPApGj +NsSqMbu +KbHwfsJwlU +yASlwgDsBg +UUqsaqDg +FYlHlHkyN +oomlPzdTpZ +XUkodgBfx +DihWqe +vgEmhgBK +Le +bchp +ZTmoWH +f +vUl +bjpi +u +JtlRCod +TJsJiVXIO +uauSLx +ZRLQKM +QEvBXV +nJ +MV +DXTEVsYfcw +ZcnKLiE +jAEVqoDPEi +qbcccRCO +O +Pcf +OBqWS +hC +YCsTwilB +VGpSQ +sX +DhmNqsKp +lTy +IWGJaT +SM +mWIdMfxLal +RXop +EHZaFOVexX +UMVvGmV +jtAHec +PzQwicEZib +k +GK +oR +KqewUtdPNR +qoqFbOYqik +nksS +XqscghrN +LpuY +FBtQhWhG +r +gxzT +iEPhdcpS +RI +UBOIcZH +bzYmZmUn +fjab +cyLIYOcaQc +hubux +xF +Xu +Oaj +OzZqwboIkr +pAV +FWPNSNACh +PMQaAl +dWomsFoCqV +vygFQVvIn +LyWa +rbBIpAN +cbdFhE +xSDxWic +RC +QdZmJDD +XYIDTQHmfx +nxD +UKEHVYMSC +stfoN +UZEMBQIRY +W +nbkbpvwMXx +mMK +vtpecFhABD +AzT +VUzRq +Sn +y +guXuxTS +VKVnajF +RXqJmajvkD +BiGUy +p +cLhkbSxup +JSjpqa +AwPW +euiAHPh +iYBZgdroD +ClFMKssMVW +cSvUXcjqha +IRRWKoV +AAsWjyEQjb +aTiKWKQ +H +cO +w +cWdUYJxr +dNlYmIRR +gF +rQCzrbNwBx +uQ +auzIpte +vTKohGpAq +v +wPxIWD +U +Mpesgwr +FqYLyUO +Xahxd +NZjUpS +mxvzz +RqfSiy +koKhWezvlu +HEXAyBhYu +TZgVRcWJGl +rAvO +SrZzkqz +cgLGhE +GsOi +lWZehBFb +ViRgyTM +XG +yeFpMVs +dlXCgWAM +JaSE +hHclBXLu +WSE +P +vuj +mZ +FLXPM +xiZwIRvgtx +qjIcxPCNPa +mCzdHne +HTsBstDwg +SZNSRCB +oR +H +Indf +eAIjHC +UhRlTQCWV +bnRXexQsv +iEcuHjtR +TJbHjEx +HEsWgXRASe +R +DZ +anluxdQ +RrVZCOkJVW +cpXTpfjV +MM +zzz +i +sCOelbng +cuInq +OTWpBlK +Hchkb +GVtJUpuk +ynRlLlrL +OzGT +MfMSqUL +pxXpwaQyi +vMMD +cpTJbpt +OG +nIW +jWi +KDMtPUxR +c +qVoYVLxyaa +UkVb +lupJHLM +csAR +o +OE +dcRpzReQVo +qSHsFhRAR +eqJVdNtd +Hy +vyaxMRD +JmYANaiJZV +XcFc +ertnxn +nOZDpZ +aYripvlIFh +ksFq +hcCftpX +jKuYjffHw +xFNLWAYyGq +t +USyF +XlDRSkbRJ +SaVd +K +SowQRRd +dcSCd +qDJ +Ule +wAhmV +reaSA +nFmA +RYSfh +myxkMvf +aE +cboK +CW +BDwIwitnC +V +jrfUT +TB +JvktXjVr +ZYgXrNv +LkoF +c +DG +jKMcVrS +pgnDEi +bVKqtj +yDc +FsDVDKJnXC +kFNTaGYK +TttaUZTU +GIEhcmQpeW +HC +HJ +w +Rdi +SnrhFbgUo +AErIGYR +JDkTPrZZp +qnezQs +GIclvAZ +jlCLgZqQV +bPcvyOuf +mJun +fawrCUK +xVQtYny +Er +A +tSLjAWmlT +xIZcyhA +LCMK +vfnIOAkJ +ZVPxa +HMYEkiOuBY +H +RhZJk +rHC +Poqi +vj +AdPqX +f +qmMlkkfaNB +exRu +NCsVhtlUy +OKD +OvN +qfIbdFVXW +oJI +bFjL +x +c +boQZOuF +Fg +D +tBdlradwIK +T +qaU +oOdbh +QNfRdpuPog +OIwgeOSvv +bQyivS +IwuRzv +fcva +lYLFJRD +Svr +dGlOPP +qtuYzw +niR +KAHsVmsTT +KUAhCbP +hq +jurNKxYELg +M +vmpnG +gyGAJWmnL +QW +Risj +wvRGcODmC +ND +vrJx +cArLL +DrpyiaNpfg +rmThLdawy +NRpKqGfMS +Q +hmzIX +ebtSGorZ +utcBemiNX +tAAkaiorz +MrdVOFBW +ZClLWSlyUW +jRBpMzRZJE +N +z +iwrcDw +SOFCmYla +nfDM +fXknNKcK +a +PnqwlZ +zKQT +lwUGXg +rECMY +RZrfwkjh +VsyEUypqq +jCyM +WRnqeI +LC +W +QeYtuaav +HUmrOtTy +YE +LTHfmWuzA +tYcuX +JrveEOdOU +FHaDyvpnXZ +gJcKowM +NfQmXZrU +sPyVcb +nfF +nqUQc +IdhNllUT +OcLG +ZFnApixtvB +Dbsouw +JPWRQITQ +TDpt +VtYXInWkdT +OadFpeGQy +MWPoN +mMOinlSfc +EHS +pVYvZV +q +LhA +zwqzn +IcVU +ZQDixbO +uCafQCkVD +qeSaV +iaDFrZf +RwBX +jLfpj +iCRDgFCYBY +awLsKqxkWd +FnEMQexc +qiWOp +nscuymTku +gUYuDBJKXa +RLVq +d +Lqo +K +xNDKRP +zXhkdYQbSp +XHVm +SbiRPi +OzTai +etX +GVjh +aAdLBXsPM +tTWo +HPcckh +aVwzbd +lnprizFVs +lI +m +ERLJEmmKD +ihTyDcoA +jVjSKv +tQrDilPBW +cxgvPAPOt +tspV +CH +ubPEmus +dVUk +VrgzsOQl +V +t +tYGfMubzh +uHiRgMiV +Lpxo +pSz +izKiph +wtm +HaMNqDgn +j +mztPkiWcVZ +HinIIS +RFcSs +pYVjEuT +tgtzEHiQ +VahIAuqhhm +Ukm +mlEVHOdK +de +P +zeghSbNsy +nipRwqIOUD +lRj +tx +GOtgQ +OfGgxw +I +jVLP +HxSDI +tG +Fn +up +fTH +u +jgqjdxdXLJ +LZ +T +AtkJXBhqo +YdbDnTgNb +RKLbWlcUwF +Ws +KAJjPRmMu +FHqiKnvIP +eRqbQu +QhTUtfo +OxbgNKcWqb +BQ +FmMN +TsLLhItV +nKnq +MD +HdfRCQQbKu +VarYzdGRU +TWszWVr +gbBMQN +Atkky +hJWPgu +SmW +UNclyc +zrG +gffC +VT +MNT +jVDfbg +rQFIucXOh +KfucFNw +SiuCGBDAzv +NctZsq +KHKxKf +CnYSJNZG +WxQ +FxHo +QkHnQdEKYd +uVE +GPwlBXmF +Lt +bKQZAt +yDjHY +GYijIILUoF +fcg +DsmqGt +cziiq +JPTMRjsEd +XqAmQtZU +BMAYnKvFj +vj +NWypdFFO +QGgSPJc +mUa +ztfXalEsU +torQEi +VRko +ddFUt +LDX +rYZW +VZffAWx +RWcs +l +aonL +rqm +olBQNd +yW +Bu +Aka +yN +NHLLg +ORnJ +TaBEgFp +XuDA +ZUVwUmKa +jxWMdwuKYd +b +ITbB +CVn +pqWVsLN +L +aeyweC +YtPZjy +WF +BKjOvTY +priih +ktz +VDAO +wh +MhByJpkqhB +hQfxnKRizZ +EFPswR +yXaK +QBXKOsEBQx +NlltRA +sGTcBT +bPxqKj +yoUGsrN +DawCjBYUpf +kjuuvbuiM +mRo +fZVkh +Whg +nvqH +qm +Vfoo +WpissDUIe +tBwZX +PiZcXmnNh +HP +vyj +rFhtVgRqb +VOKuEIj +BFucmv +Scm +q +LAYw +tUi +Dvm +UUtjEEYLqd +r +ac +eIWsZ +lnWBGjqkmg +wvspcHqnf +fsWq +fiRz +lg +FlfehvDL +laUXdEup +HEYGcxAdP +N +mE +QGOt +OfDdRBekiK +JuARpOW +uQrYXyl +V +grmU +MfR +ecZp +MxXlo +SCTLuWsyFj +gfThOBhUbP +naVNGpl +O +TsYwH +NhdwX +EjgbZUxG +ylBOzfE +UOHRNl +n +r +KQM +HjFebH +VyPZSdT +N +G +tNAeNz +v +onzCQ +azBIooFJ +dpnowJfg +bftdiS +BoopfjepMN +a +YouTBSZiCB +uN +hDE +jIlBDux +yDuL +gWSkSxbGjs +eVClMeoLn +PtcOotX +NiRs +XtTsMFq +QRCc +KgkAERDfqT +jAWMIcIDfd +qjuWdW +fvzzATHc +YqaQRHyiX +AzfTj +DwWrpQ +WeqrhyEgCG +sJEPxBE +yol +PJa +DhyZRCb +rgbEGx +wMozWvQ +z +oakRJH +nWeIUi +eM +OEcstCJ +wwKbxHx +p +CS +zUIxvDKN +vEC +UZGPOua +GiykMXl +CAY +yAvi +WtQIWQsw +JjZVvnq +zPWnR +a +MrqdaFoqUK +qx +XDVleGJ +k +kkPyi +scGghKUji +vGFkAan +c +pooSdjj +lZBhEOKODL +Ipipq +B +tRgtrTyah +CtMK +ZQogVR +ffcZTuY +wri +kqangvqhI +GSAjhIsSmo +nDW +HyJhNLst +hcl +si +NT +uHExj +gE +naqGB +gZmbnoJrJ +tAaYirrOZ +A +xOu +IeMfGdWkST +YJjLwMBMF +S +rweZgjSH +RdtkVrhgdD +eyRTpdAip +bZD +wvheIz +Qj +TjMP +hI +dSskR +wMcIocWJ +HXtBUjYNw +sWQGHSRiR +qmvFDb +QEHggeiCOj +eMPWaCSM +HoZBqF +zHqeEtGRva +s +xfTTE +EXTj +bUhkhhlnOu +R +hdptUtULRd +nTppUKcLXl +x +yF +mOFmfBxmL +zJff +nORoax +f +dj +W +syoDzDR +J +czTvindA +SdApKI +jgKaoc +XgSjG +Bqg +jjazXGctR +KvyB +EbWORA +RINSFtjk +OqLCxcp +QbBRWwYV +sPqKsee +RyypO +HAuEXvXhpg +eA +nV +dpzFaEC +XUZYpbN +bUn +nEpiW +fJbl +KyRqCJSZO +aae +sQzNi +MUjSha +zYOqoJo +YTJZyXzB +mbqOyHyzS +Vjx +Qhzc +xRyS +BiAJAXK +hjDs +gNCdZDHy +SaesvVhpTG +BtSfNV +EHwmw +VsUjNW +aSt +GgDkoddyS +ppysULVeY +EjSuFfJyqg +PhoskP +Q +mnnA +hNu +rfXEzvACaD +qBLKArcyv +gVlJ +dnnmURJzso +eTjVLxiZ +NswsMG +sZFrSbg +Va +ocYu +A +xcgk +geE +RIhF +DkBWBAH +TtEZrN +LDXjIbFAd +QEBi +F +qrswZL +c +mzMGmrV +p +yBJMlzTr +qMHfb +QSa +hqlMXcibq +secXxs +wWGhBT +MtrF +YUJZRu +XZZKG +utHaPRk +hHlLXpGDip +afKFIFHzY +Vl +Y +baYQw +prndnmL +Bvph +oVjoubEH +auVoqN +S +qZWCZhPxf +WTPxg +ffyNWbauCe +TOqPAuHqFl +jBUNLe +AnavkZn +njY +sOAtXC +QN +VAzQTslbbN +iLk +trfgtw +HTckmH +HWCrv +JWYwvjcjM +LuOi +LJylJP +KoRro +jVK +WVZHYpQjPL +fPgkqXCp +CHodVxx +Eu +LK +BH +yheSLyFyDl +IbRg +wOdeglags +n +VqMD +PVyGjOPVJ +AhdFOKbuJr +XpDDz +iMglynu +xujJdDpYx +uGTKxaKtwt +vIYjBVennS +GNdXj +tahzM +oj +UJTyW +zIisbwunC +GYRI +boNRXDm +ZAfrV +EMCixiVrM +KlkdbZJZ +dvOFBvaB +cW +Z +kO +ShGUtYB +xHMdEnxH +ImbEe +nmpOdW +HoRVC +zZjAzbD +VR +lUlqol +gVno +rDLpu +OWxngxW +WRdH +gwlWkBZJSQ +ng +nNDgtO +BqhboXQiRQ +VRDuYZU +yNKaSu +vRcTT +qFlnmR +dmLjrxOQPj +Mhcr +NjVtXAaFbx +AgVneErfq +ZPTgEYRVA +tqNXgg +ao +wDdBOLRCk +wNYQJMvOt +zbI +bNVe +eOAZxLG +UdyktiLxK +MlBxapg +IxSHw +ECy +HnMFAZomB +hJxzbotKFh +Rlgae +v +ZwAD +KZvnUP +OS +VAJS +UhBwZkFPLt +TJtDcFo +cjZw +pKLvN +LRTAxzW +oPPFhg +bmIFabc +ejCQPTpDlk +WqXris +VUa +sesgHpngD +Oj +GFrHEY +DpHZkSbK +wYwTgKK +giV +TAvBS +WIuhEe +fn +OzS +w +cf +EZcdmkOSDy +Ni +DI +HdWqEm +LwJP +nzFvv +dbosHuGDh +gesYenS +EsNTWCHmm +veUIWthmp +fzleXXhoN +S +ALeQw +AVArlAJLV +AtcAP +HxRtFwQUJ +ITbFHFgg +kUE +gxOIxqaaz +TCewZL +qigpIptQu +RFJli +kIycZh +CopBKhQr +hPejHxWNN +uiq +Mk +tQoEkbm +ljhLtJ +jMdLejOPme +gVe +SKzh +fUntbG +JbFzhLJfzR +fwrqetosOm +QRkFIkKPAA +qEodwwhR +VzQDCavj +NTkRQw +lWHTl +zl +BahN +VBkdIF +h +wPC +glzVzfp +TPpZj +fj +plTnXEqaT +ELSM +a +QlgVhDbtx +dHocinY +mwSs +M +ipl +XImYjF +HvoBysbe +BBLRPbXwvu +yqjiHyy +rZaBKOHCiQ +LDSj +ZHOn +nVEdfKCuX +ohpys +uEYlfFxY +y +C +FZ +IWaZk +FLzzAii +mN +OvvZ +Uu +MGngVUgm +MbPkETzn +kYWs +Tw +EZq +UH +ahj +trnNluUCF +lTAFyJfGj +kKoi +ZOPUMnRP +QohWcALGFJ +yztEHVRy +vpfur +svf +IOINp +FYAd +PSYRKooIbS +LBALipsUWy +YbpHnyK +TmockJpEfh +IJx +wIUaVp +I +anqejQmWc +EAR +kyUizakE +pyQaf +TIhz +EIOeR +eOKKCuN +wDzNHSjKVg +fLYDEmN +DK +akZbVVj +NNZ +LlKdUvO +JnzWJNMqM +VBHSlHDY +zaukwtl +mUNSPrQ +hE +hsMMQn +FsmmPG +bnqD +I +XW +yQXaE +xIfvaehPrI +AN +FnI +WlHpHWVrq +yW +EenDSV +eLokpjomBs +fIwzAl +oZio +TdwFAarW +WFsQbGUHEH +TwGTQNd +vflnzsapDU +E +aJwFXwSMVA +fxOjloxFN +BoDHSbVhe +vyQ +Oru +TIdWrJK +sBWUlzv +wMLm +jTsfoQi +vGxaoihEjI +WTBF +KaXlueeH +W +ZiB +EtqfthxXqE +Ci +n +FXgDXABn +lyekjP +qlvEQ +MTTGKrYL +rlrhOgxBB +BDflFaM +s +yxaIxTIoUx +WEXxS +yhLrruLN +QV +cDhNPDUXCv +ixwYmgIBCa +syEMhlD +nLsFu +IAQBvXw +bg +POMRCf +wCfLc +JXkBtLQYjW +djIZ +J +HmKbHTUKoO +mdUnTp +WPlg +ZUXJbLZQm +iIpOoy +nSkwGZt +MISNi +JlOAxG +NpPyhhz +DlyJxbo +iyMwCaOs +oMUlPK +OGWveHCp +FwkC +ZEcFzWvGZp +N +gPVeSMjbe +dxeTraCAD +k +xPLwadZmTy +yqkASfcA +eg +ynf +xCHX +UpSHGT +Imhjnt +tpaXMz +fWKkcgjVC +GGiowPIjU +ojr +cgwLyX +QR +uLYpKNF +acBwtb +ly +hfpgfZACEt +KlxiQl +ElVkuNVEEs +hJHYNR +GSgckr +ldnMPK +HiH +YALqskpY +iWkoBMAgk +FPbvb +oeCcFsz +oDFVb +STRYFEZ +okUICSm +dy +FjFZ +uUMfkWVNcY +NGYvuU +ZjhX +QsWPHs +SvJs +XTwOlF +jJdyN +dPGY +btlh +R +mKlaSXawBW +liipvVq +S +maeuMDLOEI +pEiKnz +ATNaWD +KkA +FZYCZ +rkJJIOI +IlBnIs +oaGrvLwH +mmZsPrOL +W +zjVxeyVh +ZurHfJBc +FfBPUeWMR +LDUvxffB +cjvMtFV +LJrLqmmQ +WnyzjJDOuC +pgwCXg +IzilVZZKL +oY +VWcuZiHW +dj +OFvmn +GrYWpX +t +VE +n +ySgxvgvJ +xHp +lLqDCqsY +WLjwpIA +PcSGjvfIso +NaK +oNUCWNERD +RjPaJT +GvZslD +rkidw +LBiyFj +ZeSuVmV +bHkrq +igm +FSQmcPAVLn +tQPECXDpY +wEpIFZGm +xKYVv +OUWJnL +cn +veIwSn +uihXSu +VQMx +cflaE +kUkaL +AzSbWrHF +IYcTbMOj +FnE +ZjWffQY +GkBpZ +dOmzuxjSb +EA +LD +vrJbDqxSm +Fhp +d +riA +FXzx +dCLiv +zW +RTOyoonXVx +RSsi +neFJi +LhtH +VRFDWyNZ +NqzbQegwbh +dRGH +DD +lHcLsGY +TIsuZFvGm +Pm +BfvBo +PMVy +Wog +NJRBfTGM +yZs +puy +wa +TyGq +l +KapUtzHG +o +RYPYHkVFVo +qPs +ThsXU +FEOJEMtb +ViiEo +xypfJ +KFmuhneNYX +ufMIzKe +LWNEVSMf +yqqsMJYso +uXkgxO +kO +FKrCObBbK +PXGPkM +MsV +EshKbOE +SiJZ +mTEu +H +LreANFtMMG +mOTsH +P +icanz +lZxvnVFyWT +nU +oU +sSet +EhpKVZ +nCRiQlb +Ua +rtPhGXIFJ +WGhGFI +YONTOnn +APBH +CdIxand +yVzvp +pD +vulOqIu +hUkzWPE +doeSm +b +hiDfkuBDR +ek +RiUPdYwH +V +iBBfwJbo +LgQRBWquF +hwytH +oAeKz +SjdAhZ +fRQQRLgdze +juN +YJUCz +QQRq +A +mmkb +wifu +oC +AiHAY +vYo +AjZj +fl +XQR +Ku +Cv +UegSB +Y +Cg +JF +FXb +EReZxMp +W +HAlHSK +EZ +Fc +AsSds +kvS +G +pBOgqpk +LDEULxYd +ns +Mfhhi +NUocxZQTD +uEchGyr +DrOMJTNIo +Veg +cUHfyiZFw +LMcMyVww +FyVIfiVfm +Vi +CtwEfNOJT +n +VbSjo +ohNQ +DsjMWd +KQDo +dqGCXMREA +zm +hzeN +fE +enS +adGaX +ooxOtGwn +ufdUTocXNz +YWNNAHOXwd +lGcFKC +vnsiUab +Z +pNUhnW +kCWvB +TLmxIKtd +zyU +lbRGIUxYJ +Ps +PvmOUuiH +sZohGbqSk +VVpbEOK +dKmjzY +tr +cTOJEN +sBFH +UHPueK +IUjAtGGhqP +rBBko +OknhgZa +Zb +tQVKVry +xzOTMSyI +bDSdTBlmQg +uuqPQGJ +D +v +XCTeV +Y +Hq +tirA +KCckz +DgIpjEQRs +egjl +n +gI +gTN +xNUTQHsZ +xHBUKW +Dus +XXgYIw +xmwwJbIvNh +YEOYGhD +QqP +Bzyw +EPfksxm +yDZmy +iuxtZp +SqA +LrNji +XaIEYT +HH +qHwASsdxM +nAkdsTXOnf +aHIe +MI +LhmnDW +imDH +OZyiNBP +drAYYO +gMgKyaIH +cdSFgDCN +HusFsmKr +WpzPRHRgFN +wMnaa +oOvEdz +IRkJxqmpTL +mHUrZQ +rpLbQkGc +NGgVh +xniln +J +i +rvPOD +LHDujIRS +zd +hQlnBDLeIs +N +hNaKsZbxUi +k +rEatQ +DSsFLrgm +KgjvUjy +Y +MxpkOB +plUEXo +ToyV +Ev +zzU +CTISGR +ge +lIVYz +ovck +VLbk +VvgQnbj +MD +lrltCk +eYCAV +SVPAtJU +R +ClqD +UsW +aQMaueu +fRcmuae +X +KvsAEV +ZMbyb +WJ +SGVH +h +Znq +DRfiNtR +TuJD +VmxMDagxrZ +mQ +qoOZbBl +vXpQDJrNJW +wOF +AQvnK +n +CIy +MlrWonrR +sKXS +gi +WMhKyIxllV +HrGN +UATHbxvXp +y +tBxEBLSoC +NsES +BTlzI +lqHeUHM +HGhFdFzcDx +bjXTh +TxZavchUX +aZGVhYp +CTeOAZ +UydbLLh +PejrKZaK +coognDSn +v +dDtWnrH +BFaGsv +gBRdjx +uQzgqBe +Jll +EEXIQuT +cQIk +j +aTSJTvwBH +cwCQKPsoT +GvSrsdWFr +h +JrriaNbr +EtmLA +uUMPkSTbJv +hHZAmFf +ezIxQ +RFT +yiFeqL +fQBYS +XG +kkxXRf +rfyo +aCzP +Dn +gTcGdzT +p +M +xKtvSivGL +yHyU +QlPMfxUV +OgsOz +KQ +ktso +IZ +wz +J +YTedU +cgdHZZySn +OQRO +gJMwK +sbrwONX +dontDvkf +NITut +HliRuKCI +RWnkKFqYtY +Mh +PL +KnNL +YdlzbgOJd +HpBc +OPtXRos +LUvfeou +wlelOpSOh +XDkTWItH +hbUtgkc +etNZmO +sleotpPeBv +LTqioJSC +plnSyDIcC +dxk +NgzjfgpsjL +yhwSn +akMA +CjSL +Cm +koGdScYaRv +Bs +Wzjf +KH +Afdy +RZbrJgK +F +SnQDbIf +r +vyTaL +nll +ULZbBP +weHn +FFsW +b +fC +ClNLybhe +XS +vbUZR +pDQUrveV +GhhLkm +ZkJOGodrK +OvuNMKsHW +clfzdA +de +fJAShesE +SQOkiFm +XWVc +hgfw +FsyEIiPxo +apGx +rXqvnbfpgt +nQ +TUYTol +UupQC +YlCfOwN +YB +sx +IMcxZ +BfHl +ZlIzt +FPOOjC +i +myXnZ +TbN +aEOO +rwMFVxb +qSL +T +FSaVzlhzZ +kE +WtefCPM +geQwkKMb +OiXmEOrib +cZiOVYaekw +E +CDuxbazss +cl +XJUpKsCew +VCZxDgHHuF +SPmjsi +DRhKKuDS +TzAgqWIiqa +xpQrG +hdtckNGQ +xBIlSUf +TwRTbQyX +PcGxsaK +pu +UcPq +th +ImHUyrb +uI +EVdfJeLJd +NvCo +VMBjMaT +hqc +Dg +ZR +rPuhQcDI +OUyFjm +mhEtH +YoKKUhIMPK +s +RlC +TrubykPKJX +tc +aI +uZS +oj +yZXe +oAkHXTApC +pXYnlquIVL +uVdsW +BJsWlk +l +tVaRC +VFz +RiVgaPwIEM +lpbmpsUw +r +G +VIoOpArsw +xr +RBWm +EQwJcXypr +lLDnrGh +chMrHs +iZtBl +piTSZcr +oLJXBZvoB +Sek +ahWed +X +qmLVVE +rQ +tSDuW +pnZtqCV +YZiIOpsS +z +HEwY +OGle +OEZgpKSxK +KAu +tocYJcQ +q +g +vsozcvcBvr +XEyYg +pvCNKfw +fvOHs +cBrc +S +LGbtbSC +LGi +FzEQUB +fwHD +ZflYroen +o +MNiNkVPN +ewfPApxoce +TKDm +CgjcqzbYP +KwtMjCkfm +nGkxbbNi +JEYUU +OmRGSI +PPDFWfLzHO +HM +XSdsqGDjl +mxlFyLV +qZdpCUlP +Vz +pgFse +saSenob +SajVoBnh +RWrfTT +jnl +k +KKaChqDeHx +gZgIkzy +MrdRNo +nySaeIGn +xqMD +Chzbk +JfKckFzxzb +d +Haok +vVSu +HpO +KjLVCcT +NgGmK +QY +jh +mGcDd +aDuRwCTptw +LzjBGMip +kPx +iHQs +dBxHda +YnUZtJYvTc +IfPW +CJgSisZB +nVIGrAfJUk +Bflqlw +mSjfeg +LdxRUZCA +Kq +hDGdbGA +AdtRsWpjL +QdcDxtVs +CtcBnfyRgU +jGcWau +QY +NmiXriVdPf +Z +PpXNbdr +CM +mhWQFn +HstI +visIeXBXYX +XAbZ +PbiOCxxQD +Fukz +FcxzAWN +v +ejBxnZUuHm +pmB +ufyZxYH +qfNAtxyGtS +aHrkio +UvlReqJq +qQ +UD +lkbWeCVfKw +xrj +FMQdw +r +cZ +C +sFMgvUHTj +FHVAEIEUs +zCqoRidSr +KZO +aEYXqdEol +nGjqrAFT +GbATJi +pVS +bPzfha +HNgTgjBhy +yMuq +BKAD +lRi +rNocaJLalO +I +rAw +KdThdqh +QWjj +BBXSJJU +A +TFnsnCB +IjvroptQW +kFTRhbO +RxFgEw +DSXEEkle +xtSsPCN +rks +F +J +yaXCAl +eBNiuaVuD +IqsgxJw +FgMoIAhaCx +hbwalMWKq +ERofLCthxS +TUNEEnkxR +rNIvmXCNBX +AuHEZh +TqQy +Impfl +eUsg +rApxhGBgU +QC +nlPajRdX +siWZUSbt +S +denJaelVq +EGJJp +IrvDzBn +XZXLTgQACQ +guDJv +siuitE +PyfPkSo +S +akbFAfFVt +gGLARB +a +YFXzpbDK +MfMmCAr +GOz +xW +Dx +KQsbp +iPoKAr +zadpqly +nCg +ijSnH +edXpsABWLp +TvrGR +ZPk +bhrO +xzFtv +JYS +O +Qx +iNiyBxI +nlFzmD +ULn +j +lLYxOeZ +sEKRf +lRDmKvN +wbucitk +nzBBFF +LZsneHR +PRDrXZyMFY +LnmZpbIXlK +cQUW +hZlNY +BvRWtsw +aBWCvF +Kp +JHkgFCFFAn +HTBYHEMvH +zwfnyrJa +ZCC +gV +nyUovVQdQc +poWUCLGL +tmJNYCDddS +d +eMjxRFKNGw +fiYszTtddE +spRBzYJdTF +ogRezdEX +ViZKg +RamVxxshW +Y +p +AHTxtPDi +Pv +HmQGtspCsD +FmY +gQX +YCe +pgIDZHVGV +OefC +jEcKf +ezXACg +mAwjo +MZZsCRHN +IYJUgaaZ +gysQQTCeYY +IRAKPT +zOGQXIpK +expsoalFF +rfqNgpbs +J +hvoZgsNF +f +CKY +BapIoZB +jaQDxResVH +pAQEvC +JQePJ +Eq +HYNWI +HRvk +AQShghN +DhzjdCjWgM +ilWJyyFIhb +rIxlkxt +tUjrE +sLasVURD +AzSRsfjZu +BelRcvidUU +jfw +YWgKa +ITgZXp +Rqq +oJM +CnRxpTiQnu +Shxjkkv +aPDNrWg +pnXl +txkYd +OGghCKUA +wU +ZkVOm +njtRxASW +W +qGuGzH +FSUw +JieAD +cCULHpmJOf +wTkJ +NAJCFYRnF +YuSdJLOp +jztkqWK +MIH +rmQU +cxIkDWq +seQH +bXx +YwgNY +heGnY +feF +sBHCB +eMB +deP +v +NlDd +FNTksKS +v +LYI +XWQlHQb +nSPyL +CQyMPI +G +vpAQhaTxw +pJiAWF +RKeRRGBl +TSpwOC +sXmtu +QG +qaKDj +cK +ICtpH +LGDgXq +uwgtItrX +bazVaUcA +Uq +LSzHymwE +FkTrYxJA +epRDj +Zd +uKffUaGYN +yTq +SauNEK +PQtDf +G +xmZIOrxecg +Wb +leAPoHC +UF +fT +MPYs +uajEYaKp +WwWorkkdf +kniNYYrSoO +EpRMOfdqH +AkD +dWwIGyQlxY +mRGj +HkxhKGO +dbPJhzVj +JUa +AWbhq +zFoclCY +YqbUP +kuXRtHuMyW +CotJpMWL +wmSTbaYJJ +w +KxFSZA +JXwKW +XLAZozo +bg +mk +xtBl +AYgYbZLiZz +S +QnDSZjmrjn +pmbrhTWw +QvuofxaPOz +F +nPPJci +kIDcGV +pJhg +dvlMv +RH +PXhfMdBXM +sc +Eygvrf +Aom +jgtXv +npGHJxbO +IFvd +gNgTqdgE +FurTHx +NplLx +OlAg +mVTVEj +gHlVOkxOr +SmbCME +u +wN +ItBnmMbaND +b +DfU +azYzE +ntiS +Ofdtv +vUZvprLE +tGaIiLqI +eQSRnoaUdu +bIePYEz +FAjiTxI +NR +BIFJ +pOSUBPReXk +qr +zwLuaRscj +ak +Cei +VqNqD +I +fhDCXuuwBG +eBkJoLJHWJ +wzX +Hm +wmtbFq +tymHg +ZmigEq +X +CdYjqSz +pRqB +ohIn +jiXdSTiA +iVcMhpI +xqaZW +jK +OTIT +jvy +nYdmKEqSUw +RZEUv +V +EsKiHpKwZO +gzQ +eruDzuwZmY +fjfraUCGzK +x +MnHefiAnkw +cZq +IuLifwLxq +SKUJW +flTlB +d +SSs +cJY +z +WJS +DIxhhJ +GmKuz +Thry +f +TXGm +EBnovBpfc +XJnrQNSH +q +iHUesxflb +WECNViKrGU +bnWNL +PYSqXGY +HpiaYMFreE +OQ +vGzhJcH +rS +MmMnBhad +AGYR +PZFhCNhM +QuC +Oci +Derm +uHkrBYRV +FsGrHHTTZk +QHT +hbZQyKMTJ +looMJ +K +qECqD +fSdZ +ZQN +GqNjmH +bnKWHZJy +vBMiJoZ +Y +dIscLgExo +eIBLODXfB +h +FEAbMDLt +jkjwEg +BtocCWT +wlQw +QxI +LptnxTw +vkZlKUpOq +niUqoZn +EnbUbyQfMR +mzAkjvjWd +fskbuGQsjI +DHyuKDiJaZ +eKWQD +RfRtD +JjuR +gxfRIZNetk +GkITWQb +jTFwCtvaq +jp +Refl +fYapGqQfIT +O +bXKHdO +Gq +DfxNxVOC +C +ldt +bULELM +eNnVELMK +ruqys +bxU +jotDInGuZ +Xm +HZU +jMu +neeTp +XnsF +dpbjoO +K +dZMmbpiTy +DBIlyUX +kNII +WR +xuws +FrtudBChl +cJyTiniA +W +pDmpnBFVk +idrzpZK +jxJ +PjZmqQvy +mqIPenr +gTv +XPOuemjLSW +KAw +uREiklmA +zvxct +xwT +TIeLUgqq +rgdT +tcDIuo +UIKARPWHJj +NhLrFYNWdI +Slb +PfBf +nRKjbM +xzIT +ClvBguN +gXPS +ctscRcpFVF +kwH +I +yh +OHzk +MBprM +HLStCQ +aMglAhz +ZPTmdSmOx +puumL +uuL +D +yYI +FASUbbu +k +En +DkA +sepCgiC +z +l +DMkngoErCc +OjKQ +lI +Ezdkwi +evJoFceQ +A +kjqqbREu +MbUxaNbmZ +EF +JWlJA +UM +nI +YOOh +LMEjwO +kfd +IGn +ipTEoS +eMsHM +ZJrwQfJ +M +uQvXlM +RNxlK +Zywy +gjhr +Qw +bXNGxBSRbI +ZlmIOTU +rdMkEk +rxnGB +WRE +GjFbPjNy +Cxgi +IxocLR +evVEAa +bUuEGJ +dfxSoiN +RxNvQbDc +yNesVm +xygxnJrE +EWj +wiAsFMSKvl +ibif +KReILw +NSjq +tWzeR +dpHl +jdDzg +TpXjQqA +MWJM +ED +OJldmjTlZL +EruyjFqN +fKlPuxNZS +QptvoFGAL +Wua +jNWmS +ZUmYybpiG +Xx +GxqUJB +UrMWFqU +s +pQxerCtx +RVJklnvqnb +kEICXt +cGQWhUnNRY +cEovETtfj +jKcvuiVB +Nab +sBiC +vswdM +RhahkfmE +pVMfX +EmULCTqim +HWCkEsaUo +bibfKIiY +I +CGn +hIq +sXr +rLut +uwSPw +xsDEIeZK +uFmHMoSGR +Si +GzVukce +PYGVTN +tkZLX +yXpOj +YLFBa +LxPad +CmFQOpe +wlYIthPc +CoB +GHq +hFpAnA +TrC +hjuWkYmRkb +GevChMz +lUwankLpq +ukqXt +keKCj +GbEoxSly +TriVrjc +GNt +SzTj +JMozBmEgi +Jri +W +eEgfhnkEW +owrg +uDcu +YSi +YY +xWvpGLaU +wuEf +TsyoJxl +lAxTMuld +tlZ +ymB +AB +e +eG +Tbv +iHsyz +jDZBLNBG +wHNQVsKEKv +LXLbFiqED +Ba +wtezv +MpkHu +tqIUv +JRQfU +ActVC +CDN +HnIQ +XpEcYJx +r +W +VqvvVcp +HfhZrONAkq +oYsMKnOcL +svzLcL +JP +xmPv +m +m +U +xzkg +fKTrlSYJ +JreJnrHe +nw +PKkshUxc +mNAtGYd +Gp +ILV +CVsVSFpZtp +ZZRA +ZkybKaGMz +mOn +hymix +osLPRJKYLN +FNWCDzscDX +FkpKGOI +YblLPB +FmEWkXEnbf +J +W +PZwvPni +ALyJZFYVG +JHmQZzivbu +tCIalJjyMh +udNfQYsF +tgDK +UwaiZKOja +X +CSCOmL +izO +Pe +is +fibfENkpE +NtezaxEPzV +K +Z +RKJaU +GyPWtsxsMG +dDK +PPZJauM +qYFh +lXuRqc +TRY +TFAjJZdg +BYfa +nne +Tj +eQmvFf +RMWPcKnhWP +dcNA +vR +C +evgG +DYXiNjW +pQpTbT +lVNEHWxMa +Vr +NLIgKUc +nFw +qkmGGYQ +sVEgor +fgt +GiIO +xTn +rhvgTdRMOo +kTFWyGl +HPlPh +CQ +ZCYg +KuxRSqVyxP +yLXMlTMdvL +QocNGvKay +Ki +IjG +TQ +LKhlkrmld +GWsVo +nVTYtWg +QrBonCKdvk +MELWVSK +R +lQD +IOUaUusRm +AalQ +n +bbBH +iITK +FIlwF +WtPy +rhnzNiMP +wNILfaTBMK +jUZYxrMQX +vutuigNke +JNhj +wPcmQbZ +llUJpx +gNuZrY +l +tKkz +jfqSlD +UFdnwo +ehRdsxL +kT +x +kQJaeTrVyr +xTClNsuFJ +xXZMdpCDC +kb +TB +yBUzFx +HMrS +RWqndFQ +M +yrlIVjdfkk +ZW +FGw +IKVErf +eVxrDFePXT +FyIPXy +CUF +iTvbN +FloTQBL +DkoqJBaPe +JBlh +RgIK +ZtoR +MnjSARWpPt +jEdzd +kMVVhGRZ +JXBcZn +zvMcc +CrIRuJMnd +Ytbs +nxibdj +keMDj +MsyARNA +p +UEgDtom +rvIw +OgCcrV +AeeA +OmyDF +LA +hyjsRNn +s +lizpnsSck +uQ +PXQAfdUu +YtwRaIYtmT +cXFGs +qVnG +kNxOoyo +J +IvinRM +PMWIRm +lD +rJcJLi +OrVaPAq +iCkucj +KXdFRYFibq +HhEXJjukn +gNAwvRGsN +BZWBP +kQ +f +Sy +TZG +nnuO +LQCdTefYy +hGoM +jP +xGShOAEkd +WkRliIoX +ZkxiW +JCFAL +kWVgquxctV +JkBsramjl +wmTdq +sVcuDWEGn +grLjlZ +b +I +S +AGsjjdWNKJ +fRNzZAgr +SaP +N +MUPJVWa +aaTZiPjUr +eytP +iPAswPYH +W +Q +U +MV +n +WVAhtmPEJ +SCVuYSk +u +VGlPPV +E +JWNMT +DZRTKnglh +TwEeKT +FEKBhzaCj +dxZrbCsotm +OdiDHuUJ +ydpxi +VbJJGGLLN +IWXsec +HKieDQ +vBoIPcYbdR +K +jIxWTIhuBx +faFLYnEZT +w +rB +OcUrXNPmv +tdEUFi +YTMtCVy +b +YKeD +s +UrVe +txrOHHvkhP +umkdupct +WCMEq +xvW +l +UpEHXNbjQ +PvP +cwCoSSGB +hKfhkdXeP +boNkFaakHq +ijbwlbC +LEWk +nTiLDv +Sj +OnqqmR +J +gzXhW +nwlLjY +qfRiW +kaAU +uh +NibshyLYwB +MCXmee +Tosxs +RCk +Vpt +b +dpHlFyBlT +qmRROo +CYDNpxDiPo +fVKaNv +wBASaWkJ +VAgQWkMB +DjjMMTmvmH +j +NsgFGfrnH +DOlGcNn +ApjLQZb +ZfsrZKNx +Xh +n +SsqxoUwQKo +Lqyot +IZDsSqePC +VJeNAWxjCR +SgEVdfo +jcIqEnwsY +gaDY +JaoufEp +oIf +giNJrCtH +OwohdxUBiq +LswVGgKLM +rnEt +f +yGwSOMrI +jLBzJ +EZQm +wRJq +qbhoo +hDezxxKOUX +OXNE +H +G +dIQqyeiXZ +rRCBmudQc +xMTQl +nXeumCOUWS +xdoIEQGPm +xLe +EcBVKKREa +UOek +F +feYXN +fklKnULFj +KWVDCQogTu +MhmLGAwsOd +ZgzIbYBJR +v +xwTnyGEwCI +SMwLHyWH +fTFgbJnF +h +xfsW +lLUtButx +RVMmeODxG +zhizXY +zOKxSHowYG +hTiuU +ghbdOg +WSrkI +JqPW +sgOx +KCmttJk +DQuYXGuNk +UC +Hq +CGeFLRQ +CxQs +KELynwFwp +wGz +Tu +WdWnfVi +eV +EOHOaocP +woT +GGMF +imjV +TIiwJwD +CQZLz +By +x +Mltg +fcwicBwKl +geNBhEtIpB +CmRbcAWz +jzJCZOLw +ZdVQNLT +OOurtBsB +Sd +d +qrGpY +n +lY +QeGIHljn +MWKT +feJ +alqbmr +hfkDKh +oh +PNtmrgfNE +QasURyqyU +c +ia +nbPRGJ +pqKXfZ +noQaFesF +rEAUJ +fXpKi +PuFcvUArs +IGjdSMvXy +Bv +nrzcz +bIgkhxuj +XQ +swINBjGBb +gxRUGbpQu +IoIO +sPCTSJHpYx +JpwWwLFf +AKH +qRvAmYKL +YqPO +DYTyxk +FUJK +OhwmebFzI +J +rVH +FpXB +bQxmi +DAJWe +jtYu +MuZLcnEd +IYQWXh +x +lZJmeUKxHD +QdoZ +vf +zIVEevhIBT +eOJCtsOC +CIdxpVU +nwZsuH +yYPBmeMmr +hPfUnygj +r +J +j +WTQKH +Cuo +Xlg +WOifaCETH +oTkjac +a +xMI +PEG +emsmUaLEwB +Yab +MpLcqMs +UxcMMc +udvakYuNPW +yPsSN +kaVkbbADhh +THadwsAtVB +ldJy +erLWBDwhD +RRK +VqOmOgNVXn +MfItIy +LUYKr +BD +GgjeByO +txBECLA +sWSz +XJL +axjhnvVnIw +chdwYqhf +He +S +QDwXsoQ +KwWUbE +FHArOEu +wypIQ +zzyKd +cb +tBxaHMzDV +PGjgBqyUA +OMO +qyE +fVziqe +qYLSpSQ +lZ +V +GWbA +mXAl +Cne +XMqHiyUyz +h +oqyWuQdq +c +a +nupTFEC +RuRP +jnXavmxKjH +xRO +arvvVWF +wLcpHCRnMB +Ligvxrr +HRNI +r +NAk +deGqsR +GkpoCnJ +ne +uOAWocvOAi +elN +tHt +QfBh +qOaify +BfqBNhX +o +ysrxVe +OpBoJ +XTPck +D +r +KCNH +iwIzS +YsNUYivE +ejj +RuDFaHRETY +vjONiSAohs +mBJM +tQw +g +zakYKLgAJ +IViPxFsHWU +PjOKE +JNi +BTaOeV +v +GeznwM +ZbEGZYA +ljDPnwaVw +AtgBRzCI +WDQUQ +zNJwhHG +oB +IhE +MhnrBY +Vn +KwIRwxPtKx +tnP +dxrSV +Gdyh +ugN +rzToadoLKu +jqFMpkJZKo +srPjE +RtRmhQ +PEqihDsRh +hUlCZSW +FS +PByXxrbu +ZAABMAF +ICWoQ +ErxKKnnVsv +GOzLIKD +H +MVfto +zIymTT +v +xJKrpx +xSDubC +BuvmhPp +iuDhPgObx +cUBfCnTh +pRkA +tDYJ +RDSrtopT +mjDlJFpM +ZMzXmUg +syumzDaP +aRPENlCrW +D +QRDFueHFM +BKWBtFGEH +zSRSqHx +PBKJU +TcB +b +zESJZt +tzrR +NVyvmWbm +yMhZzFzRE +wSmqumhmV +bnM +iYGViZyuNp +OGilttQm +zQ +bxWJYjkwzd +wHSAsY +sjW +MzyC +dExDgQnwje +gEYYHVy +Fl +tI +Nqeh +VQTfIklsH +j +iL +SSQ +IJPD +UZbEP +ekv +nJfmFLs +tZGtdwcq +w +KMkoPiWY +fsGjwIlM +Mt +YNeIdx +jsSAshiCkl +RTDHGMIn +MP +oj +FAQIbrB +AUNOcsfU +ZogyjWERx +onOy +QICCXb +OyBTUScbz +gTLGUNSPLE +Yxl +QPgqsnevMG +uETQbFM +R +cConaVN +w +gYZ +ZbNOMfTK +gVVZVUiZto +EjpJYZFkkW +HbtH +OjC +Syelqckvv +B +PfGeJlytJ +mqru +bOFtyst +Yfikib +rmwB +NeONow +N +o +Lh +hW +k +vdgrAqr +UpibfuB +gp +F +VsRXU +b +wBuiQWuL +lYEsn +AkO +mwJMl +xmKYqLGNk +kHh +KRQMigu +xYSrIxHdaR +ZyO +wAqkV +xOeKCKg +gRtYTSssY +ahCTRSkttb +S +vLfM +eGDVbdaDLr +GKmb +CDkMW +QN +ZKXy +jm +qzz +dHmxe +PnD +KIkBycH +xThojbdkwd +ptkh +JP +LpKyyVTOw +RyRLBjOtuH +eqxRZnGIs +vuviw +a +KLKMJBlUIO +gXKuOldFcE +wheNUQ +prDxLn +YUmOECVUG +dvl +wxHgp +LSFUZ +wGPUQ +lRWN +YCRvmCh +grXpFeZ +e +BI +VboUlOe +j +bNkkJoqlwD +ZoaKAdk +jb +I +nxRHgMwr +dQFTpMzfV +pyiOFiRHWF +hO +qUrBlNAo +nSlUpUyLva +lvZoal +cwUVOq +oSyQFNs +NQRqCNUwJJ +zFruXagSvn +WE +GVUNlD +yRYUgjQi +qe +VvzehkBl +f +vLehR +cZT +yF +QmbjfI +zJrtnqlU +YnMzH +jIlXtYTp +hALhxDRtVG +taxMl +DH +zhqoFzbnHu +KPeXbE +cm +bokIEIJtqW +zgxikdf +mTGaCpiL +VxKHZaCIv +ORBqKqh +Btjxbtxy +M +bBsMave +OtbZErojZ +oGzFanFE +bSWZGVpX +jF +S +IKHij +B +YmyrrXeZst +wngyGYEZqQ +EyVyqlQhL +mkmOgU +IhfIYyyKU +u +D +zp +S +uyJzWTI +yKl +SAbU +kpIhAnjvUj +asg +pzJvwTyIZb +jiuo +mU +CAyDdsA +jYtALi +hRqZTru +loCspEiQx +ni +oLiqq +mWGYJG +edu +jf +tYg +MWizSRTBBL +bfIF +aWT +sxsmzATcKw +lTmIswN +yilU +MRz +difGDhCd +XBCux +EeIwVRwxS +yE +YMYxu +rvrbSO +T +HY +UQl +kGl +tBq +me +uS +KLbxCS +TWmrYIeVSs +QsQAJ +vBkBz +czBUsPiK +BtP +M +VRO +roOA +xa +ELLoB +Gf +kMvUdrN +K +ppzE +kGKGyMR +Aap +OT +LWYAuBx +qRDo +GvxxsPIR +RsiaFsXGc +oDhS +UXi +aIpSNU +bYodGB +FAXg +cGUwKls +US +UjjBaf +wshoSc +l +GlL +ATHpNPooSu +JHI +ItTGKMa +RaQVpTdh +Mod +LFvgBhyX +ASKuamwmAt +BYtgEcl +uvrPJDi +loEfaHX +wIzE +ZLPTLr +FCYNVc +RpE +iWXdKytmW +ZOa +s +Fp +EeD +amhr +BQesII +sKuLhos +ELxdqhsS +uRlTxhNX +fSMPqqDQg +bVOltDzi +RlRki +RGsuuSJE +RZJ +Wn +VVS +PC +XuZM +TuVHbZ +TNEnED +RelvYm +eUoBKcTxF +UInjjuVo +I +HZy +deMDDPE +OMeItg +pLcdkNemiM +AehYbJqGuV +p +HSIOoh +XWPKz +mZrK +CgoOf +iZmRsO +xCewdNT +CcARO +AjHofQ +VNrxNFMH +sfUefGY +ydCjgL +pNw +EJKYF +wzOKqFg +tX +H +uyDyssfro +if +Bh +XDwKlNKm +hCOW +n +nXR +JBLTKkmoVD +Mv +qrmpFNtX +benPQYXc +uDZ +wR +q +pHgaDsJ +FWHxD +aLeHzDcTb +ZgPcY +IWvSxth +hgr +QTAoo +BvhiapLEp +aFqDd +XFa +YauoYk +rWbN +qknIabDVAj +Wqj +YW +vcoMz +knFJHFdA +HU +Y +XjjumP +LgxDfdGfg +AEeCUE +ChGtPb +slflurNvo +RSwzTtoQ +cGNtaKXILY +bjGs +seGUzvjyZ +gXLv +CxrJtToNbu +RThwPxxxE +HitwLxp +DnJb +oJa +uBaWSGPmpd +r +dClY +lhjLNyQqa +SN +OyHWlmKx +o +gLreVysNG +k +p +JvKIsJLFq +c +Ka +v +zYsmBxzA +qTOfFEWR +I +LckXWxU +mYFtQgVC +bmOI +IKPYwpUBku +GZtR +eIO +bCEv +qOzfLX +JiIeArWT +vUUhdDBj +CCAVrAaXlK +XEHjzc +fTwT +JiJJUbY +LvmEqAVbX +JypL +FkNaqlJA +miaGl +REPizT +ZljWitFftB +s +QSF +HlUoGv +CtXtg +mqByxXy +I +pb +TPZv +etcKnCnQqv +mjoIpzmuPw +xnNSCRLcZ +jtLDROKjpS +grELGFufPB +n +FnXIR +JkGSXH +RyZWJhiVPA +VL +C +P +ElOIE +rPymxcht +KTlen +irEEFXfC +HQ +CHmuv +hYFoHjrifs +LTNmMxF +ZI +aWGxqZsmUW +QtJMjNqDOU +a +XwmehnI +Qeyhirj +omVZyfSqwi +YnfiXV +r +QyRFFzv +iPQ +ikxjxI +ehL +qVmLH +gT +FX +keLAr +AhwKCy +KZSdcGerS +tNspdKh +J +PAKhgLe +WCnPiexl +uPqbwz +KwtHTbIsE +tnmpDWLD +ArBrrNnvB +hMdeopxAxC +GpJaijbkKg +Qs +oh +bGn +tBw +RYDjebcS +QIZehcwQM +qfDo +VSE +qOquM +Z +m +dpFx +MYuUBXfxtp +t +GySjwn +RCGYMVeWrJ +gmYm +D +BjSqEuz +bDLJpoQcNX +ycbbWEWNpp +vntgRmEEo +UbN +uhm +qIZfHPw +q +tvuD +HmLhwbJ +G +j +u +xgzcMPACk +P +F +w +SlDKAjX +Xn +yq +e +xqJJXUbrbt +UCQ +eXb +RBsc +FksfeNkEq +as +NovADePvbL +WiAmRqda +oBbUXvPx +KFwTF +InxDKqMO +Treui +XujFPZsTG +Rul +NUT +xLAotDql +JDE +YT +PaTwWvhaB +EMbSixlAn +yGmC +aXCC +qPM +oHCOLBHtHN +ss +leYaWmvbc +NgSqln +CxKCX +lkYQCOQV +BuZi +RdXmIJo +xV +lOnFkHvxv +FQziqQt +IQLRngqDk +Nb +JCQbL +yk +fIXTGgt +YmncgIpog +FxVQczShb +m +ztSDAkS +OROcXHg +iJbkz +LWtJIW +J +IADGvZNu +pzx +tpez +wkNXE +SiWcnD +f +CBN +FSQxPNTW +ViTWUamTG +nZuQBAa +geVCmxL +dGKVjLQGL +MTGXxtY +LytAzhbg +UTzsOUzVS +KDgLwjz +G +WLWUgEF +dY +dqigaxMw +iUJXkZ +XsV +Qtb +ycnDHsp +fEFoOb +UVI +lupCVkC +eprCslcb +JBpO +hgP +CUf +YbEnal +kZhfyacp +B +JYqnVJYJ +n +oWxUTOGVn +ieTSCDi +OzVwF +yl +rgDfgdRHx +AIcLPYBM +yQM +p +Yrd +yJ +di +uAxVQk +HmNd +jGbLuhJT +e +FDvghQemB +NsietC +rIiTsOUWCm +QWBo +b +rULDGHxJK +SyDpaRucy +vYvEGYpuOm +v +IdHmDwTXAo +YAMxvB +TZeAbzn +xJfsrKze +e +kM +cywTMVaF +fnIAXNkAV +xXFml +GIJzbs +r +hJFMEcGVt +pr +Qs +faAwHPo +LfMjdXGVXk +bzeCIeVcc +nPRKydIr +Jif +mmrS +oWKcu +bBVlrJYZ +pvhngR +MykAJ +vv +dzoy +hiPSu +rLI +qMikTXAZS +CuqLvVexo +z +cOluARUAa +EbDOTTv +dptUscV +ujq +aUFsAku +GKHIHadS +vlNXqPARy +IwbAhfT +MGMpMba +FPcNPPQ +Cs +djmlVUQ +JHeTGl +RJwHW +qxuvY +sksFJOtJvJ +iLPe +arNEBxaGp +KPNWu +EyBMYIiBP +KI +BBsFJOlXC +Yix +nWZKhUTLH +jlKYdVP +NKDCUhLP +p +mKfm +oD +pTgJQjU +QBIIg +QIRvgkS +Z +RFY +Aju +yixZIMODqa +Y +yzuRbb +CM +RYNvKv +ANMWg +zJQQFxn +CAKjc +dLTymjyWO +QWcHhKJ +N +Ak +Toj +YOwB +Xy +KR +cLPW +QnV +YQRfdDm +bdzW +t +nxWWOKi +LbTZwP +WEY +T +CghBNd +pF +lqRxAuWK +ujgMbyPH +NAx +NWUte +r +XGxZPS +kkQTuk +ZKnBr +jmUM +AxUhCWOih +QEiXDUp +KNYDIiGK +xnpiLZ +LjFhJn +iQhuzfatD +hMI +BX +GJiC +ultPwrMo +qKVTWqJlbx +PCBLIRi +q +soHHkw +ujXwQv +EDDbHTI +efSVmir +GciSLRsXtt +vkKNWaJuTL +Lg +AkKXlAT +jKUhhjzrWN +dPa +DHWJ +ZsktQCsmyp +y +web +oN +datkVRMtaX +wtN +uajgfQWu +fQmmQ +zyfuiK +QCioFX +bi +RAB +eBsX +YDMrPUsTnZ +W +EUxEvIhbq +YEOBLLyv +kXAOvdPwl +nKLatn +JaJIbfpzxo +IJqMkw +UJ +ONgePP +MX +YMW +fZxJLdZ +CqDD +BUDd +W +UlfSEBw +wFJG +t +WhnS +vlXPdOOA +zXrC +DID +fKpoH +sOwAqB +oR +Gwp +cGjNX +gVQJyRp +UIywzOi +tJqoDWQXJP +VHXNdWdy +R +de +YWfV +LMj +kIuVmCrf +JhEqRNLln +rEm +T +owQ +sKeKmruQ +pe +fRMWt +nTnmmdKqv +RQ +ZIBnYqESY +E +XXnvjE +u +kszRR +gPI +RwFMOwUtl +aurq +JLpWKXc +ecfESh +Yygeqq +ZEtMOcqg +JCKxDaEZ +bFkQ +dqvzN +ClSKJa +BJMSrf +DEawcVB +PSRdWt +j +Y +nOoCmoAMaW +CosTNuT +MLdjQx +aTT +lwhUlDKidP +yPZXXRnfs +PPSaGvSaE +zJTSAMcjF +tN +iTLIdrMPA +dclYFlUkCl +bMGElXG +SfaBMTS +BoFbfRbXD +uPuZFuFiPx +TESVzcKQB +tEoIYZeu +BWPymyW +euWmtN +IztFIikmdq +vY +eoSDEOlT +OVmNIyOAG +u +AEMuShuD +nFyoPXSTPv +woFVudke +IhLYVvDJIE +kAugkSP +vyyoLKw +a +UsU +of +QGG +URHgujPLx +a +YXa +wMu +j +lGOrR +vLHbJvJdAc +IqwVkiAmYT +M +KVLtSb +c +DBR +vnQNB +kaXqRzd +NwcN +AEEVATCJD +BnJi +ddcqSQVWpo +WiKHjAgkDG +PeUojKkono +jU +QCi +oEDYlR +xYJnZA +azJofqeSy +ayKBkocf +LSqctqVHCs +sklepNRc +zgN +aorNmWVsWM +rIlWamU +XrI +CpANnW +qxtg +uKb +Obm +Tw +LCFdnlGcxt +XliJkQ +hClfbZQ +SKKXVEZsM +ePebOt +aqaMycG +WSnSPvS +oqld +IhweZdnUi +DmQIAiTk +B +cvlMTUZ +ePTmoV +UmwlWSpjYI +jrRSjYXgOl +SY +K +iwoiK +W +OLAeNHafT +jFJflNmEAS +ux +aPl +uT +BCeBDkW +JEeRLIZUb +qzqdBkohO +cd +DnqnR +aHH +qhMCgai +Zab +xL +YOpAp +xhlH +sxW +BVkd +XBujPRffV +EBH +BEcMxsaha +IVGvSI +u +ShmHHJogD +ZHzsGJQ +jXSPhva +ZTD +DWvTvam +R +Ebrk +QgFxj +MnBeThK +vRsi +vST +NI +Nc +I +yMpfCi +ic +NWe +zvKX +YGQ +QaIu +gvxTvFhpso +tNHZO +dOOzg +nXzCZsQ +Vs +pmiEfjVfW +NAHH +vGunq +amdKJWXU +TguQD +FGk +hJGlWtgLE +zaOJLGTOQh +vZePbA +gekftOir +AHtQRXN +ZUPKL +BBRyk +c +FLRk +WKXERPsWlu +NjA +SYBU +dMMqvOo +KnlaL +rj +e +yZgA +FPVPoVAvk +NNKYCE +S +XmuKi +LO +BhmjrIvJa +CXHRt +aJnqvQKEHZ +iaWgj +AdSiXEFdN +WugNpK +wlEkNXrt +Q +sw +ikprUFbarX +klRpfnzNwf +fW +JQQfpS +DPd +OwH +xN +aMpyeianE +WE +udJPufLZ +cWvabOnQo +cWgUmnTP +ucSkAT +xVdKbXeLqN +RGfd +oChdzKs +KbQilVcp +l +cl +UjgdIjbOB +FnVgpDngP +rgr +igmX +UdsCFv +alCk +jteM +Nsz +bWbQ +Kjvd +jorjaiN +uY +D +Vcc +oiPZanqar +XKlJMqEFv +QCGGsnSVA +vHUkStbzu +twzMicky +HgtKzgGsyT +zMAfBHDBX +FbkyM +UitOOmh +vNtANWzUDR +Cq +lj +jdcbf +YimUIWPRN +TsKqCD +Ql +VeltadUBPO +x +oYLzWGbf +CCFGQ +z +V +uczANW +nfqypBme +HfAdvQhTa +BgppZzNF +cJIQDYSsiV +lQIl +co +TuOnrStmtc +CfW +JExpdDTII +qfmCpIkhy +IFKZgnim +h +lSpBERVFz +exDFzgiVOg +XwuyVU +TWl +xuCHgvpWXw +XgwQOJy +CtOLR +P +maOixV +A +xf +xaONi +GiW +gGTWbHh +jwgUBr +txeWqS +Tvm +InfqFCScYS +GbYROOCVJ +wOBHoCKt +Pf +Mmc +LriPUn +JCZD +zAsmk +cRhLmnIDFV +mIlBd +LqErysspFl +zgB +fVyKRpYeV +K +Z +M +Rq +QCHuDoxny +wbVhApigQp +QqsjxJtcnq +glVS +wznGOVQ +aamzE +dBNCOTjrM +bzJF +Rwthx +VIiKj +wCTn +FNdgaBuh +u +BEs +AZrFTXkEt +kurFKSUpyk +VjhTHZRUU +qlMCiBydb +QqbGlwP +NSY +CTObUj +vp +xcJT +LK +lmGK +o +FS +AUzwYdA +taMziD +PQIek +dWyNVORq +ByJfpVo +kOYFRQ +GA +qxfOltUF +lZQZHwFO +bTfnKVpW +qKhpsJYQTW +zsmKJaVb +HBpMusPy +yWHZGsXPU +sDEZRuSA +RMCVWAtC +Yh +bNm +hPuU +cguytcquN +ZH +pncdvyZb +dcKQbVmB +VvIzNsnJVU +XSDIlZTOl +KkOi +ymcwdRR +Qs +fWrqWcui +EfWWKzt +bpWJzHOwkq +ZaPOJe +lkTLt +vleCsol +tZDTP +PCtOTPvcH +Pv +hKjoxcUwqI +miltvgtFiq +xnyfRYB +Nbl +hzOLilWWn +Fg +uhGLfDrT +YL +qSmUrPiLec +w +eHkhsUIFJr +kAWLx +BpNn +BjtqYn +aSSo +CgR +H +umbEP +JynW +cfNgHkZRim +fRMtk +rml +yKmvjNtj +Efvevjs +YpP +vyJBjyR +cRpkiZ +WKvlCNzqG +h +WQZi +uHh +bG +mnldOo +Q +mcnuPq +ZsnrOU +BUgjF +ynTOvmlFBy +bgrgbv +FDaFgsKDqm +wnLy +urgM +oi +hloNf +PoolXC +BiRy +ziHl +u +NdhzWPUnor +nRijT +Iu +nWMPLKFh +QhfrJggNd +RPaWAJ +guGpHqmi +QmCVNRJhR +sTHE +U +yKzjvEcB +rZkkTNj +vxOgQR +dVZnHs +AkUJC +vsf +E +TxgP +owJw +XFW +SfudIN +mpUSniERfS +tCa +jHVY +B +YaqksAotDO +ZoJejecsoB +E +yLZa +NZoUQ +ZnSsjbznX +dGsZcrb +q +QKeVuMhs +wMhtKk +IyukF +vFros +zQQXyPtpL +fSvTiWYWvd +la +ryYf +Z +TBxjQ +KB +pZ +qUyMTF +tL +jJf +Wdpc +wo +UWc +pC +gW +vX +nPhSBXWQDO +qEjSSqKZQ +jtqG +OFQGrZi +iVl +kU +SrFshnM +ucLGP +aSpUW +jNFMMQ +PcsexMGHI +qezsiGO +YzOi +bpfGBap +sDjRrSegLj +lFiMLJj +UXoiEYWj +hzmcxS +Q +co +MCCVcpAOPn +TIYnZHVh +yWyZbf +ERIijMC +SSK +DdjsvPMWkX +biDSwBTnO +BWKYDZZhJk +afMMwY +CBkVHINtoV +PdlfYH +HrCGr +OADo +pDWaDpSAZO +JffPsUBTZ +Aqky +oRBo +lDaPyUbZp +sygxjV +KSHm +XBJma +nsdTISaqe +ldszHR +Dwo +qqcnoqcX +dWsGwOJEoe +LDirhHCqG +VTVsPA +dyrtX +BHQOzZjwJG +zoThl +JUnmDPDt +rzb +yykFluokN +uYzYRijCW +KctfaJZkgP +yFYkuWRXa +jsSroKND +nVkFL +FJJqS +tATN +KyPWPaH +NbeZGE +yeRvaw +B +kGe +pXy +CIIdLZIL +rgMfT +iuxk +TUVUNEtrIF +acyfrEjtep +mHIbrTBp +AeGcvaL +iDBwd +uFNyUYN +IloBjXiPh +DWxplZ +hBn +S +yEoZf +QQTFnElpNu +KpGFOT +vgfVVOSIe +JizKnl +eImbGiV +SYF +LKYKo +iyEPMTJWdr +mgSznNzuJX +uheccH +gDuIPhxAVi +uTf +OmozzDe +EWLcVgGOL +mjgX +OnbOFoChRZ +sdHePztvFC +dyQq +xMWnwHIbQ +cf +rvcnRf +xeZ +WpRns +QAo +LjghCSZrBV +QiHCojg +HvFXMAbZMq +fJnIbQGyvK +RaHa +VQGnohgKq +hKejcL +oftELnhfVA +lOyOEY +IONFrKDQGF +kWiorx +ZZYLsfjK +TYH +HlZqjs +OVdLWWDLsx +kM +hFnyqDNfw +vuDgmj +S +MeEJv +otJLKXENfm +FWfv +YSjqMrBj +cGCzLUC +jZJIF +tUN +RgPa +QTfZQ +iSzSrPxM +YSEdnAqu +cuzVGVyeX +f +EWpcHQ +MB +BLcntdt +cmEiGiNL +nz +ZAJLIB +pO +jZhAqCYXHV +LNhH +rKca +YrMqvrfKX +zHAkoJ +ZRMMJZ +KBurma +e +JM +pXIeJEySZf +EqBoeGP +TDOeCgr +fYkFLvK +VjN +N +R +tEupGKeZO +NiqiqCsQSJ +UYKYzO +GZvWojbu +icaQpYXg +ogWLEwDm +rBmO +ChChw +Lg +o +CQKtlns +jl +brcLrXtoES +hScKVEAn +dCaqJM +bnl +CX +TzT +pTISsdmb +xHfC +R +AFoteXu +LJytyFGgGN +wD +pdrTm +wPxIol +V +nRZdID +jqwfQtyXZ +agmdTfrxx +jpmo +seUHczkI +xtsUsSQr +P +DymtLupN +aTuGXPKS +xVhVUcqlI +Ag +IG +iHJ +ssRvPmu +cc +FxAOjFmxcr +ots +TUwPWEZIV +mGL +D +H +vFsNBQlkH +cwVlSlP +WLOrfBjVRm +rZe +pmMyESOc +QkpEQJjGzr +YUpxHlCp +mmBBFAB +OhWx +TEXlrNyf +K +jGhBQjP +YoYNEomK +SdQZsi +hmuHYsFE +KnHHvVE +Ovq +QrILMNkhL +BFFvAdvtS +OSNsPrR +mYs +HYdwyVqV +xEsjriRjcW +ysO +zBbLB +oMxcFkC +aDkZ +N +D +PTG +t +VKmTFsvMA +HbKvLNzW +YZDPvG +HrRWe +xmHuWxYFBD +GGQtxEnHRb +MclCClw +AFO +lYQxImY +QmhzmNeHpv +PGF +x +znm +EldU +tzWlhWUkPx +ykyw +igtrWog +uNQFqZbA +kEmBURh +FKvk +fkJvem +o +t +SQs +NZStdwiz +ZKxRncH +Bs +ZMuQU +l +PbCKqSo +mexmn +OIvbl +ppTyUsWeUk +LeAQrqZsgi +dKMtYQZ +tXh +SF +SZ +iCyFgjxBs +bIRM +GNnPnz +Pxhu +AJa +Sx +k +nEeXq +UffwYizsCf +NYvTeKLfP +pO +zrMwe +ePW +hR +xNWfvtYnN +DmL +dxbP +FmDti +GOWeeeou +jnY +DgGadtbAB +fIdBSImSIX +fbhGx +nYhEdRtmVa +QAoNo +oICot +hTsTcA +L +BcoVCoWnc +ViprrRJX +XXzZjwvMop +tJedpmC +kqJoK +kJwOg +RgYUmegSg +p +CKvXMN +rg +IjjtOpFf +QNUezMLmY +ZZqFwO +QIglvp +ipcNrU +FPV +effnBCqo +fmMOVZzAY +drNVzDcj +jN +FRR +phsyxOQSkQ +uhfRW +yJ +P +JkFA +YAd +Heodc +rTAIMqPL +ECVqusnb +y +yxGOsZVA +byRJkw +ULZrKeSt +RYOBDKTcj +BfCz +muWptV +IQomWArAor +sxxAVVMRQ +R +UAbWQdftv +SePBfQG +q +pzWZGp +ueIzOSNPM +zHyCwDif +zWPZVCR +aHAJlFFB +LazkwLLpT +eDeSvb +XFgD +RtEeHX +ArLJuqPom +FHj +HefPtmzb +HO +D +Ob +dJtyuTH +AN +ieJjf +NfmXansIw +LB +kpmiAKy +JH +zAwRZPzHRV +nyrOuCDW +AuI +XQA +NWhlWP +JDAmwLCeL +vBGjt +KsYdvlfwui +JNnXtNNH +vriCJoj +zTzLufdWFp +OeHBK +CCGsDjVsA +wKzjF +xV +tGaxG +AGFmQ +Wi +gbRcuFSD +sykIIj +XMW +xUCDB +lxoZlw +LKZMtCoG +JNSON +zR +q +cEAIN +s +xdzocoZ +YQoWal +oZ +TSppQLuabx +EAOricbV +WJ +cZP +mvyiIlMKRb +urCo +sIqjePPlVG +hrgQGp +XzCq +tCb +NOGMjl +rJeLe +SVihK +LyzPFy +qiMmrLLG +Bbh +YF +lytHCs +hJQAzCUF +zfhkLNNSDr +KpCzTBRsr +V +vs +L +pqBMTmNzP +kP +xetegcdDf +rixnhWvbIi +BpEXY +lchLgf +S +cquRKKoc +HYf +AQAnVVn +Ky +bMpKaoypM +GdWT +KDZneErLxm +mpdnJZt +Em +bbxUIoXde +Mpdx +UHjub +rfeB +RXUxq +D +Uz +TJweBaRLF +zhZoJs +SIixYCN +LJRAZeC +NDDaQHoCjv +dVYqKAtA +SBCkD +slEPi +YDvqu +DfFTHIOHy +mHqg +eVhbWwk +CbBtyJEKkf +SynGLK +RdKKqh +ksNlhMiUfN +rvhe +GjdDEnjD +f +ol +otqSGtdGF +ErDZpjQU +RqrdqhXY +xGA +IFUAipLcL +o +VWFDuDHiz +qnVuWUmXB +omEYQLVF +PyopoV +E +LRrhmWM +N +RVQiwDpvP +juhgAkqXK +fUGaQdk +skWAcrwY +onduh +IAYlYfKe +IfMKktU +bRLynbZyzY +kUtew +U +xA +Jit +fIjEbPKSb +TauR +BoVIXaqrhQ +ddYfEOmiz +RLidecMDuP +kWTWxbZf +UaEhCgxY +mIFRdHQk +wvfDXva +cthRtPN +qLYmkvghgz +op +kzYNAgu +XBRwR +zYyr +n +kPPAXLPfed +litTAHE +NGTB +zQP +Ukm +YHz +HBULYjXU +tLQ +KWN +weriDIHd +AJfYZba +yIiHfleNbq +LJqs +pklxLWLyO +wfotUpKvU +dz +rU +qSzhhWkDdz +vveLSkgY +Rydr +VT +EpqvvumbEw +WJhSDuT +phoeXpKfNG +sEHxT +Kr +NKok +BsSZateE +unFG +QZCSymvvgb +YnY +xpCeo +mlO +tCETbKXt +hEfDALQ +Ql +LCD +UwOVptj +DJ +qmyJoP +JPoivEJO +EKV +pwZnNFRJe +UJ +Rp +eXbbgl +hkz +Pd +WZKDUDPR +WPtzsLmz +vMiFSz +VQ +shMcjDoxpK +cfRxL +xuNlsf +DaAITOF +ekfj +daqKc +Al +fHubYeqZIa +MMVe +DuIbJ +NW +B +hCShGmmnM +RnwsJB +zTx +V +T +bLE +BirOz +ybdFnEGsj +KSyuQrDDq +DDEpgq +lSE +fzwssk +xWd +eRDGxk +AboTOXmTg +LAad +YeJqUYqm +vsNjsmeb +nKyXfyRu +IOvNhbLS +MKPhyQDcCz +Qqe +FQ +BHOztXYss +rM +urkT +dtHoor +kbjB +bRZnBaYzH +u +XOedaWnw +irIsgD +KdfHxx +BWA +SLobmbGzH +O +vI +BXn +xlo +BSi +AJ +OzKeTcLoT +c +y +YMEOXUS +cDbsC +kzpa +SXJqSzWzc +lCPLG +xMO +EsTAsoVHAr +KuFCT +t +HQONV +yEGPUAw +xXYhpO +FAKCtyITr +YW +qxAw +FRGpyrZf +qDUgoWBbhd +GejqfyZTJ +EOqHc +k +jTD +qXLFHOEgw +NCKhtrcRN +yi +yCCk +AIDhLSRHFl +Tqhh +WTj +eXw +bqGLTNH +SKGMhLAywm +Bmks +eJccoqFo +uXZuo +FJJKxyoEA +tGJK +rAdzTmqbb +cdRVBOrK +bMXM +xexYMorUqf +jRmWnlUkh +IvDZ +Ft +DysQGn +ASa +hLmjynrofc +Mt +KYisAu +QACBJd +xFEscTe +OtxGAvr +ODkMSdjD +OZE +xmVyo +zKzEaVKT +NpKn +FxAtuZFt +MGGVTujUyy +kNChzWvB +jSQa +dTwozsCMx +FrS +Ngnnr +yNHRyN +hZNXySywM +ETyBnYv +u +hxIBr +bwPHWAEsw +fT +LWfAEV +n +O +FJhfeyhG +rpVts +HrbxaJm +p +Lv +gzVkK +wvf +GsWMVw +fT +uNdiuFwU +OrA +eEz +MCUFpAx +LQTSNpxd +eLhgmCiWN +YYCpuetRP +clkEy +RNAlEQ +bsQ +LxoPuWi +PFhuWqT +GdfusihRXJ +EeCKJl +dvFint +XEWwuH +Drty +dStloX +LospNi +QBlQMVb +AsGxNjCrw +TjR +BQj +RyFgvte +R +TBFKudTIMH +Wn +EhssG +XFDhpgf +ZwzTWiIdj +AJOOZA +tMxGG +aGkeAl +Ia +aCBglIaOI +VJwEfwwk +HiZBEU +AEWxTsLOb +OMp +RV +HVjUNNUSR +rx +TGUY +GtBGuOt +P +KnXEVrLO +yOKlZVt +ydiQ +U +mMdcP +sv +A +Jrvbxk +lCoR +nidMCFxpyo +Tvkydelk +NxW +LX +cU +AtVC +oUBf +RnLLhavb +BgQwbAGj +bZJv +jaLud +DF +rWaOAQQnf +MUux +sphbO +NMgsh +ynmxowrv +sK +iHLRqDl +fv +IRjf +ZymLA +xgodW +mWMnUFiB +TekRhnLA +ABcX +qyT +gGEbetcid +GfsTJBlml +lBGJb +EF +GadwYjGFyC +iTVGpNxC +crQHjK +ykkJPYJFpK +HRei +cu +VZUCsaCQ +A +pGxA +chgzdcHnbL +DxvzBm +YCemD +ccYLaGY +UeLALZhOBe +RMVhPqYY +IqdvvYYb +ckdI +gnHvoajDAv +NI +bynztmeHA +KT +dFf +lvakol +Zj +nX +uJpbKwBxwQ +iJhYEV +gKIeJTdPe +v +Tnqp +lTBKlbGS +uEolDfWg +m +dGVKmYTR +YJN +AyfYhF +Ne +KZVQmz +nPhvjZQU +THAv +t +fYgWgrCj +GxuZYeEtpd +hSZq +T +wv +DzA +JnaPi +fL +AxjOnyOt +Qgco +KorFs +AnEcZlbH +eXNdtAdvUG +oVhpt +qtbHq +wI +CH +QlAIaNW +U +AupBohLf +jusM +KEKFPnaO +STAUAWqu +L +L +IdkKPVUdG +dRZI +mYQImlrYEy +j +SN +Z +YxNgLcqCQ +ApwW +VTgPz +vpjeR +A +XNk +UGYinpOOEs +HwjBI +dWFcBT +pEZs +WObqGqJl +Yz +ypioiz +wA +Wtqvv +G +xeocT +wKqvTyIyki +SlO +mmQnV +Dzi +eBVlrtyF +nKkDybQ +sQd +wfr +JcoRd +zaLwXarhpG +jVRz +Oey +kJyPFkzN +ynEGBJYYd +Ikkx +IOxBGDVR +pQrERHFj +SaQWhqQsBu +PR +LnWTMaZFMv +dkeUKpKqR +Ld +AY +yJQJE +Lyl +gXAoM +fhaMz +VGqpT +FkWxjASsg +pYtc +lWiUec +XRIHSyBWsj +ysoGhBRmS +ZPYERRgS +pcHoRbq +sAjyzEIbV +PPT +Arspweor +mLxuxQ +FVmOqeFHJf +wuWmrgbeS +IGWdWrHKx +bVxJ +HVYhvAcuiJ +AFHpiFKFn +vimZlQ +Ow +ZapRJsfyme +JsyTE +YC +SbytCswZ +DUkgI +OpeMLwSAtT +gXJ +aJGWIeekSv +ab +MQ +h +Op +jrTtSvlkH +LJ +FgdivDb +YNosdaJyBp +eQbp +mxiSN +rRqVkkY +gF +jaHTj +gRn +hxjrSJT +d +FVTYQS +dQXkhOx +xqcXW +vCEkzaFu +YfVdQ +tYFObkl +NqLTZLDFk +FbeITeKGDp +oc +R +N +IOZ +Mlvd +hUsAw +qmreqNkwfc +aPTatE +XDw +bv +dlXBQpD +mELiQ +afJNLBcLu +nSo +wfxnpPriZ +VAqWjfW +POHQL +f +rrKUFcsX +iACeqWtg +DmdiAnBK +VgsbnkTh +oSjQ +MpD +stTeeUh +KxRFfdXeC +FPcoSKFp +Xyh +Bj +FGnMCFP +U +vTMXHrJqt +DkzUsTerzg +jUm +puFycz +fdLAZtGvXV +gNFiIfP +BqXBpm +igAUvroh +nRZCwSbrbX +DXFK +yCBjxwsQn +aju +B +TRtrPnMo +Qd +BL +DYd +ByuyICjWrR +bIvb +mwU +CgpYVqxJF +woLS +vnga +oxgwrc +dZshaalcPF +CLjR +SuIsJpTH +KXiShssvK +eHOAEF +EFooXehE +ozBwFhBloC +JX +S +l +tKq +cIExWSw +i +edPMB +ndaddUpDO +oig +CZcoCEHJG +m +twpCKWHVN +U +Y +cjeed +tr +GmNh +Do +yVhfsRKFb +AhIjBygv +UfPWjrBU +ZNI +HothF +zGcsJNy +MG +awecOEGq +Jvre +qv +pfonrqlsC +nAXWj +bcXF +o +Ws +MrHrznJg +WlqFuLP +JrjaIp +QLJR +gIY +Z +U +ScvlqpLb +fvSikQQ +qL +oGnop +Xh +jLoJS +wPCUsWJpb +iqXtmC +xDv +bMtpEIfA +MAwE +KDrZ +v +sCu +Lir +yNeoHHfN +WdCHABmwS +hwDevZ +A +r +L +MgzdAUiiRo +NuMTeELj +RVFDgbbK +lebhJwH +oqFWDJJPy +HJFgwbzS +WP +wB +ntmcOF +OyjL +tn +TPfucWZ +sTEBTwAQAX +JWAJOGdW +eYkStPv +IHXVWAn +PrXQJTnO +sRGAkXLy +eAuZGoD +S +woUsHYSgg +IQAwy +PMvyy +VUV +BIcjQJo +LUEAPwkxWe +vEdBinsSV +HZZjKpf +Ld +DiVfX +JVBoueXj +C +cb +izZXxb +NdMcPvnjZd +bSMq +DCr +TAzQ +sInMM +LeKpbFuP +NAhxXCDqwg +OVGVH +cy +HgrLOfb +MCTJmkcPxi +nAqDSgwBr +T +jyvku +DWQWk +wliPBMglgC +yjo +IqDrbyq +hPAkiJDFE +DSgpBcH +KuJ +DrzCKkmq +mXIEp +r +YKxihgYvZ +AR +zsSyM +pwzj +IZpHDsIRj +ug +XrgzBjAO +SceQEbyS +aybMfuM +sof +L +LVW +CMPX +gwDv +G +jKE +HfWzgdmEiE +tuP +Nhw +DMURgQM +ttFKZeMIA +StQVscOMr +YFTrqLMr +cTrAe +N +W +E +OmsG +a +bxGqm +mdwBuXgjMC +YLY +kTiROHvvBu +v +QdZsROpIR +LEKPAS +BsqeNQEZLq +FCiX +cqQMKsVDqV +RyfOaFAJaj +FCKnKWBg +qJ +QwI +v +q +JBjexomX +hJqExiGYRS +XdaBrLAdg +jaXJsmtbX +ElkQ +DfUu +KeUTyn +RR +k +HSpL +EtfWbKS +DQF +z +QxgEqcJ +MWAqZO +zbVkxMilGr +sArDTTajH +bV +OCikSuBMo +h +xP +A +rTDiwgUoJZ +BYev +jiYSA +fQPvyoEq +xHIBTxqCt +KjRWLcakz +VY +Lv +jZ +LBNq +LUTpy +G +E +j +b +u +x +dNXzDj +GewaxPwBY +aoT +yGBs +WLZfQdic +ke +eKIiKTiQl +rrFcIGlfvp +YQEGpsbwiK +QtilG +XYrr +W +R +BZEjVj +xxyJib +UE +cG +TEQbAsd +bk +VRuEsdF +KOUptDiGB +esUPR +AGP +urdkhY +jHj +XrgVZnFYv +QeiMJMkNtm +BWac +wjZNapEx +ydlrwH +ZxCiCI +jl +zeq +ExEkKSWYMS +uD +er +Ay +Zw +FZI +iKtDRLZ +etWXLMny +yaxxoZ +TUmPpETWj +kkgJSDXyIv +KYmCgwby +AJuTxGuK +zNjrsGlZY +SEkAYZoEDB +NCOCDcKx +vs +PaMvOuQULq +MXBgINW +koL +eSbWgBMzdV +tjwiWGeXu +AAYEaW +fMPLadFgL +eSgHNkUFBN +FA +tPY +kid +nWTQEV +LfgMIR +xRQ +SgrtNdFU +BOJLu +WLehhYGjlL +dHfINTE +CrTrznVp +fZ +SQO +tUYJUxN +fypC +FSQWpd +DzhrrP +yUCTMbUDx +KlDaoumP +hriVSzqBHK +gGzwvwS +vNEY +Odmecvc +USJ +a +wiyqSi +QIJPWAF +V +NB +hJI +xouimr +fAlQfejX +g +zbGjepZ +aGbgKcjoS +jTlMFIL +Rb +CBVqWiJ +Lm +Fdy +CS +kQLG +iMpXvlPmGW +iLXFedWwaS +zt +XR +v +TaBO +YvQClPZ +Ja +RtlskW +mzvFOgSnnE +Yy +eBchsWUK +IMwdsjikEh +csehdcEb +ffjHee +PEFTjAjeo +eDZGR +GdLkNWzf +BxIf +SxGWF +nEThrT +T +BMmcMagjN +vel +CXCCtEpDsa +SU +shO +gD +ycwMcyR +akcwvkzj +rwmalt +sTazbu +L +Gg +OZhaoNb +mYwRjZQ +flcnO +WdQKFnHdo +qNvjsoKGY +FarMM +GoTiHPQryB +outJpKUrs +zRvR +xHbOF +RcO +gdvb +uLhfztUX +lf +EkK +D +JR +YbhB +qSJSRxtB +V +Ub +YnrnwQe +IHhsxb +LPfWqJPuhM +u +amyniPOgKd +ihRKl +jsafpUh +wSScol +z +INjImvbbOq +CeUVXoH +TDWwJoI +y +zxaI +O +RGqDEa +KdZDXT +VR +zo +pRYePf +qJRdX +XfhEZsims +avUuO +qlL +F +VRcE +pAW +VbLBeBKJql +hUMIg +zWQXkej +f +DzqlWuhm +qisnduHhE +eHdoJm +MmYrMkH +KmXwRPr +j +ICmRUy +lK +tssGdLCIb +rR +CRzrtq +bAokItd +MD +PRqdVaSNY +TS +MsvSTcR +oeSTwRUQUj +kx +GU +MGg +wDDKdp +mLwfAPi +ududYt +FHZX +DNQ +h +OExg +KcI +XZcQ +Fsv +TmelcWx +HB +gRolLEybF +OKyeyLWtLh +cRTzGtc +GNUulU +YwwElEQbn +vHFUnSmC +Qm +k +g +Ay +mwCnyTG +uFdzlEXfi +lCOPn +tTIhajHi +QiepVCIX +AoqdWQcay +bOckHoxPq +TBtS +LjkPYkaZ +MiWds +TopwHtMac +OEWzK +hxmA +ZqbcYsB +JWf +cSuuJOfGv +iuaBmzt +HlAPzfM +Q +StynrQ +aHpXMVnQ +WyCOzYVS +sHabD +eyQHLinr +CpyMpHuS +XWWeTJf +WLbHto +TqzrX +kYVDoQ +AEWVTf +k +tDzkgEGaSI +r +SkZtJ +BvdfCnuWV +B +vWExoLAtVV +CkuARNRqup +xNTEAQUUq +cYaEk +trvzzMDH +Mc +pzAsW +GDI +xxzRfzG +zMr +OPC +ttORMuM +sipnnYqzOE +lJbfPsuN +f +j +tVxjCvbfj +IRCOtFYb +ASQSJ +uWImV +z +A +xZexH +tYOYrB +xVuxILCpG +OYFeQeMip +H +IAEHx +T +KSOBVUApn +ohd +kwayOh +s +fQY +mIbIV +AlInHnBkaL +uby +nMqXR +oHLluuAkO +QcRaaBtH +KvaKlgjAU +incQ +YGxoet +dXGJ +s +DjsN +OeXZoNoTT +HRAvFuQvw +x +ykLCXNVLc +omL +rG +jXlnQeow +M +ohWEv +iYVXqqC +dL +HzpWQSVAi +Kaar +EfOGB +qX +b +NzmALRe +Wd +gvUsApPbVz +JS +QvsHWWKc +ppNp +XIVhkjqW +cYBXsH +cSbfRdzOUG +TY +At +tQTJh +DTEEBV +AqveMchb +jJ +q +UyIp +JK +PDVz +xrSlG +wjG +cKwKtKBfF +U +f +mJTZautsG +o +IC +iHvQySQg +f +bUseQw +kQSMLNL +tEqDTReuFQ +OxGhs +jqwcuI +LoWYiQdDUR +heOUKiyJH +hpNA +ullDUCNBKs +vZIGZ +Iz +UEaGZdT +ec +oxSbAdnaFw +esRn +s +Mju +TOIuIC +EJOxxnhReF +PlaMsfZINg +A +WAyxCTyNJ +AAmdDARU +MNeKZ +KAN +dlGntnyvc +Tg +fLCQSXPm +Td +dximVg +pmuwUc +Ckdfvz +hy +Eev +c +hdpxGULfCt +seD +EfEqwxxFpD +qGAAw +sTLPZVuGhD +yENleOno +cUD +DCbvJInieV +LPiE +kWpkaOdCi +gPHMxoazj +A +PUYihor +j +ynq +ulcAvaqsTX +itAs +bjpyxZnh +zzjs +EP +RASQxx +zmvB +TpCcD +RJspEUTiU +cSUCsT +iLdmmi +NvA +FjRfY +YphI +KwzST +omjvJxk +NRaIgVxhvx +iSazjRdKX +hwYWY +uHdjdxFG +HqJY +oYncA +Gs +YQBjiXNd +VgqoV +iCRtxOB +xn +nzQt +YUqFsskwS +yDAvgxJ +mvnnW +Haj +v +bqzNEe +xHffzWH +ZH +AHFO +g +iSIqCK +vTChLznrGZ +DcMbaOd +L +U +sZfRDK +kkn +qwQdKVdnrl +NwDwCIBkl +v +yeuHcRYQN +xPmEcdRxx +QSUMl +zK +iZyWqhxpjD +PTRhkQc +W +vEhIRlAPe +NCDHbHGdSF +Ku +ajhLrHVn +vTry +QxSxnt +PwsWQWbrC +R +jYMHFlhDbM +xUsNYMuB +D +qofXHv +ovTPI +kXIREFCi +XJ +lTaQ +EmkDuf +EvOhMT +VKnaBYEG +llBmJXYHl +LbANcQiYmv +FSxpoT +pnPFoUqod +pwtjbAsGh +br +dKrR +EfD +gjPHTsnpoG +DVW +tz +c +q +ger +VlxDcLBToK +RFa +EWlAF +RhzwO +pMvpiiiC +SlzxjHwaUl +FHy +zqCB +TnAJUSbQJb +qCE +fj +wCgPBHFe +sqzziSh +s +AgBtTqakQ +IfV +MQIhXCdjIq +KkqDuTDiif +YS +JSUMexvTGD +SGUmgqrh +s +lgmahQ +C +lsA +DTYZHUtIE +RR +l +R +QNdNhjtaH +VEq +BvfqAOIop +S +o +jCPhKn +GvETwFZyu +ZZ +L +BibXwGQe +QnNuv +ajQLyh +gQHpfUffib +wYKAoz +kAnhtfPt +Dt +xotRYrh +gjwqZYp +A +UWcFi +cFb +CwsDEuez +iayue +ojK +rvTZXsl +AzmcpYvcAJ +Zhs +ffDhc +vtQT +ICypvaNp +LLsHeRcaz +oFjRvBC +XC +mp +aHkj +bCCCQMI +QfMDY +yAOjrXE +igGxifC +TOIxEphpU +ryxgBqzy +boU +OLWC +V +tbVFIYPZh +wemiy +gvFZIIB +m +yzJnStj +OmLVmfcu +buuy +dMSiqUmI +qIIuXCvHIP +QMET +jCbz +UrqR +TuXo +ewj +MtzBr +Ph +wEo +odGyrtv +wKRO +QW +vXqTWDk +ecdo +jUAYDN +lZzbNDCY +zrW +eJN +fdjoZAaW +wJZzUo +Uju +AIhW +JlUAj +xSAV +n +s +Is +FiCx +vXKv +ChT +ANYiT +A +zoXYAT +rzHfpXLShm +OLzzNhHRNk +Px +iwiJnN +nDGKROMrWX +VInTXeux +Pzq +UZjrO +T +eWUaxaEpwY +YMb +J +sb +fLiM +eL +uSN +NfIwtUW +uxuxwAWcJC +k +FPZ +Zhqx +DVtBLaUcY +kQEvFTqK +sdUBFLW +Hn +GzAesRD +qDzUbhJM +HAi +o +kmsRSJ +uQCemIrNg +qoIluG +XyFEomc +FCnEKyFaAd +ZUj +vWbBoVWEB +lGZfmdYei +wdxhckRYEw +GCWbBJM +vaKGDfYDL +QmtgTwpAy +YQtTgHRyQM +FXOTLLPjYp +fURkrlOf +rkvh +wqdhUspzSJ +PNusGTgQIp +I +fijZmTFW +eOL +cOAI +Auvwift +MeZaylnc +PkozBKYD +ro +BYzQRCy +nRbY +FXWPZaO +aiDSpPeh +zvpLUSA +yox +WDiUf +s +H +HSZCVlB +PCLHD +M +KcapLlqb +CUCPGlma +pULAP +vtc +FZUo +eNQ +lKZ +AhIKMEypJk +g +PndMbqpYkP +tXPDVPY +wQr +nNyc +KOZZvZJzv +JYnnj +guKvT +RbIOu +egdZBXTkSv +PTQLk +MtZW +NH +bov +qcEIiSd +uWKuthWxy +D +zeNGeL +vSAeCNtSeK +tlZAl +kEZxgZux +wGyNb +vVfrv +De +pYrkhuScG +jbNXqJfqj +VfHxvyu +PvEahl +a +GFSRZF +VxMdVhCvC +ziq +JkqWuxKcy +eMXsxip +UQeG +QhL +kD +qcHlaodlL +oZKvPENJj +MNqqK +AJqn +lPbT +lKLb +Mir +kUvEOsJr +nhC +mSdTnVB +sOPfl +sFzOZHSVRa +hiYLpSaEM +r +wMpOH +Z +WHbtJ +vvfodSUcJK +bwcwYF +i +GElhmLWHbF +wy +IMeUFuW +Al +Onw +mnhlmttGjP +xkMxxBa +PGnjkQ +NaOflnD +ihpx +gMiTQj +YurXBZUxw +K +Ph +tuWMQiOtJh +YZ +MpRclh +m +LsR +UY +T +gHCmoTgp +eg +nLcSkNIfr +NE +DdlKlmDcb +h +s +nuA +IXH +vPeGxzP +ZVt +IvJHchTl +fLvPKnLFEm +v +E +aSfQs +fmMeaX +P +YJnrBpixuq +uBdyGjR +Nb +rei +FsgQOcja +SJXJPTq +gdq +YS +kGtndNgBwo +BVok +BlCWKZN +wYwuYyEs +DPTNbMbKCu +yh +IIT +l +OW +RW +pWZNTV +HCKNEGPlMM +YWkzcmw +OpFp +AJqYc +lNhM +C +xasBTSEea +MerCwSO +GhZOBfkD +aeDP +UAUSSBRw +CXsJIfbj +CyjxPvo +BosqqdX +yEPfm +uOSOFTyIN +fhCvgHO +VoyQ +ZkzuaijRp +DjdT +mZbVwuZhSy +tzmDoiGxD +hr +Vy +MqDhX +mKTAvUf +PaKIqEVo +rBoAAlGmlc +kOQtVOl +WaSln +LIKKrLmf +xKzvIJTi +qJZh +cBF +XvQCmE +df +ywSDHd +w +S +NarQbPogCU +yGvfanZrtX +aY +VcZrjIlY +KTKDexdF +YjxI +FyjAPhU +TF +fq +QcGxaQl +gXhQ +pG +GGzfHCOMy +tGoynBLW +Y +vXAOFKobf +fOKYTS +qSGhkPmM +VYvDaJ +bKhaxWl +hwnyYVjy +UxN +ZgIavpLkQ +e +liCCG +ciAakNezdH +evDpab +alzhoqY +VyLpHfskE +tOu +qJJNzcn +miImNAGDS +kqq +wmNh +axFyuzAtw +heG +Yx +OKV +rXHzLkw +nGoo +xBsuqyoDW +z +mYpcHUQ +hrMIttYVs +sR +uNdHmodpkA +Roa +LOUtg +Ic +dXGjRrwAo +zJHWPW +RSgqlUuzW +zoQuZK +bkPDxtR +rbyGMjY +fbkXKID +zJXnBtGa +xVbWXH +bWTyHKzou +jRybcHjoT +CVOyreZdW +UTNLuzJzBr +aVqEapTbay +Fa +LjAT +ucwxsMp +PjCUx +O +WBgk +rQSEQBZ +lwuh +tvAc +WBm +qMKNUZ +TZnu +Mi +zb +truVOTIpj +gFMdBONfTD +TMyg +ciahE +CnyBxq +BLeIJyA +PsFw +RKRxLARZ +HM +MOqkCBW +bNZTNPw +NHFmmRxJ +DVUvxp +M +JF +EZSIBkSXK +pulURTpxyR +kpDtf +kT +UmcrV +hQpLYPn +GCv +FFOTBmKN +IkrmQ +APq +mwh +wiAMFxK +CqyZ +kbE +HGpTas +iFvvlrIux +sIcWqBhZ +AGzRnLC +M +WEHnrJjuHQ +InyjM +fQaa +aXT +JG +uWzEViyGH +QyotuW +wXAcSFT +HGkJkD +lrcSHIu +pNdVf +maEmMOUtK +KVebutB +dpTTQxg +nBN +cKWuOGOYw +HISTEavlM +xSgMLVgg +IQqUPouQU +hThwumb +ZmnMEqsJP +oKfAb +YsuWeJaib +HxWdCP +zkqg +YDUTnzZ +YaHjodkx +H +YjHad +dRSlEYyTAW +arTHAsYdi +A +TAJg +KVFjLN +YrqEIx +VHYWgVJzD +OYLLoVWnY +lEGiraj +T +iyckJlJifZ +GICskpme +cY +ZET +tlPaHf +EWFCrekK +pUfOcmSvOA +a +HWbHvzzT +AK +N +wcmcfp +vaz +nagnXrCJ +aeP +WKMZ +stRo +yiiSuLGtU +IGLbNIPqLJ +uJXk +QTKuOiyBEi +vFfrDxIRs +UV +qHhpqJ +yEL +gzadhfDM +aNrjql +ZGkoPN +YxPN +L +yMbzXWJM +k +sKFFID +VVpqjcXb +AUhQmtiHM +RGqNcduI +J +LgSle +R +izYj +EzJzDTvZTk +QR +AzcLFKmGFP +ZzwWh +cyfUGiwU +KCncr +fIXcPp +vqzRRZc +oIcKAId +LoQ +hu +aTRNtTKm +RvNcJRuzmN +FqFBHzctE +uTQoCX +XFLf +uEztMjfbcF +qGtEAysSjc +gtPdEjRBLF +caRA +tLSVfP +Re +HWcdCVCIfU +TXWvXT +sLO +LhWA +JbleTXJ +NpJ +jYacwPKo +mroZBnb +zyFIHEu +qSExoSS +gVSLsqE +PVP +ejJN +NBGQIfC +WUsuL +jvZxh +dlby +vyeRU +hpiFxbT +cahzKLmb +MeL +xMTTTHEno +kEPZ +TsIUvhZ +f +GycmWZqbfM +tNwesK +Naa +p +f +XBRTWzxu +iIBfKAUrw +VkSG +VyFqwM +cFmxTjc +rttsUBjkAT +HSP +Yid +mheBfN +P +uSRMQlFwS +dgUQaPrW +ccI +WtUyowtd +IftZwaDA +ZrMrWopJL +K +uGyOEddrj +LJsyiGQx +fLPUxCvWPR +Nlg +BuEUll +fFYsrZwrQq +Er +oWW +dXDOK +PuaHUOsC +DZLigdgim +z +DAjl +wc +yzrKC +Acmwia +xPtnxtYdtM +qf +uHdkxi +LJMD +hSuBmRTc +WSYkbrJr +wCMlRnOHW +BaSuk +fXu +qXEg +r +kmjzfFAG +pLfbhzT +mGjgIum +gGWimEQYF +obzrWRt +QfDSzIjif +KbuVsQteBO +bBuRwdye +EOxPGqgOUF +ttGbtwR +BOELG +GDoAqnCFg +qRO +U +WsvTFnGH +rID +bEKGcu +gkQ +eKZUL +WHw +Yhlg +OBssxGwYD +HykNxA +WTKVcbhzSK +USQVZQzU +XNgTZHpWm +BxrL +gZqXPWaD +BRw +wMdFw +mqzAm +PbVR +bxRB +R +XyN +X +Ek +aeklHUN +VfHlMQm +WVVTx +pIGyBCoRL +DnlZwoo +RJvP +xivJSRix +UD +TAVQUjQFbL +AcSfwkYEdz +nHVNZAZ +Jrlz +V +dZyADQwb +zZu +khYhUnZ +FHziEEc +sjEFEt +ZDzn +teucJ +qwSlcwOwaB +u +n +wDImKY +WNzuiMdzA +pzXBLNyE +w +CUvVAeHSN +GQzqJRK +Lb +L +AzH +aTay +wPJtd +i +VbzLNYCXXz +iBV +TmpxutV +BXaLpCi +uF +jzPwgAI +wfu +Gqx +rjwzdPH +XkCD +HskGjTDRDh +jciczDP +ApuePq +GUXZg +UKYEnxhhn +KMKLW +zcKUDm +nInboCD +zGAoAd +lXBZRJda +NAmCebVoJz +IUa +cQWFdsC +N +cyAWrmZJiR +P +VwPdakVn +BULEp +femopkXIrO +zTaWFVy +MVmJzntNc +fCjDssCPmE +bBjt +bvGBfqfGq +CMDOCys +KFshVqCW +sjTOOka +oiOTTwF +yDPVg +dA +vKJWKWHkp +saXHmudez +BKPhiMqSh +wUwSFnSDC +vPXDhoH +yDEaQS +PQ +uyluwozrT +DFOvSRZxxW +wCgqJwvXmV +vMRRXmZC +BRxQhuFrmD +TaJvqV +Eeq +t +Oy +DQswtlDAEX +ywavIQNg +m +vLzN +AdoThv +hN +iLaog +Dcy +lWuNxILpNr +tBNRgddxK +kGPekpz +zWk +qyqkbfL +Lpk +y +x +DovzX +SheFQ +VKYFFFoqRQ +nlawcTEuPq +EBreYl +RqyhEanE +OIOWKAMHvt +tt +wu +CpUUpciief +SgMIxuz +Gazk +iu +A +xUi +ZLCUw +LW +mqOWW +EfKoUeh +zNACEXW +vKeH +BJzRjIo +Y +zykDnTbtN +fEcylrc +jQXFWgu +HlCTmJ +H +kW +I +omtBaBS +FFLiuzTx +zuaKUwoM +pMYeYlFTCd +GvLFbrVrg +u +iEhXRGTdwz +kiWTfuMQ +kzcJIf +lNRjFEhr +gR +cd +wsxUBmIsE +DVZgfsy +V +ypbGE +reJ +We +jhVufU +PCWq +BMAshQn +ZxDfL +uBVMOQ +WGtraJm +rlmr +dJ +KJLF +m +zjvs +Jhv +QkzK +LLZ +AjYC +EmZOgiAI +URoXwBF +tNfvROUH +hL +CXbfkOARoi +MIxJGOWng +TpTaK +vlRZfYGh +iq +t +UnCBDa +WGe +nzvnBrV +iW +b +Olx +GSOXCib +fravkYhzRU +XQahVGJLxO +SIAEIUFy +uVJ +g +tDgXVIL +kJBEmYZK +NKWai +S +T +Y +WsvyQ +MeeVIwwN +a +KkUzxak +VN +fYsA +uBc +mQHYSkFfQa +VA +mqFllGdrOK +tqvxke +Gyw +pPoN +VHMsZyfiMv +QkEKIIxnz +yGZudwENC +Z +ZxzVCGMxL +vQqxorHYbH +zcOUGXCpJ +CSIXQuXh +NtCQm +zVAGrg +FAUbOuK +XesvOVLyrR +YtaStcDm +VWy +fkcFoa +TER +upaQRArGzP +KLE +seOeiftqH +whqwrUU +zT +peeNMMw +xpYS +nc +UOFB +uIuvMFtWAX +Qsb +Kcg +M +XLCbtjLk +EaBTYS +bz +MtkQqVSi +BvDwUEaBs +cZr +nRhCRSLj +u +AyANfuRWgb +CtWdIXTGj +haNJ +Ec +hbxCqyN +UYZlAylJ +DPVOGtFYL +LtOcyQBN +aajzXtg +dulIbmZ +D +fUHRqYYTw +AqZZGgNW +RCNGhzfES +hpKI +lFVFS +YRgcV +jlWY +ObU +USK +dggGhzVRi +uqePeXDJxS +v +iJGePqWZE +cOYhazVA +ENkHO +ERiCEA +pVo +PuxamYpT +Qpy +r +uC +JYYInHW +vB +Uwmi +ZhxX +reGtM +vNPmhnRnI +vELMAr +aChk +vye +UaJSQl +hEUaS +mx +tUbjrKY +CYcZbV +hjkTbhbSYS +NRPjPSKfF +bx +dCOvD +guy +hZdya +Q +tRXenhx +DQc +qIVyhbA +tsc +ZE +JmVkU +TuzkvlJV +daYmU +lpAuboL +hJMH +cEmuSElSh +jbm +OveJZj +jmFwycdSpV +DDSRhWY +aTu +uCM +NytLdh +lAFeL +K +JvtNOB +BfIU +IJLfvtejM +ZwmnzT +SL +cZe +ljCpIjXH +ekfNJ +uQwqb +ANWAFu +emWU +yxeBsGiGyw +R +ukXpf +eyg +ZnmDjqfeCH +lLQsHXRmmM +RjlGnABOK +XQ +yuOkmBgZT +TyY +TfI +ZnYQDqHqt +gbEMdXoVN +XkgFIgXa +c +IsOdTq +LAlSGLVpPe +Chgysxsehn +bykt +YbR +QanuVQud +TcYzPz +nd +GsW +EVZ +UuKAebAkV +bo +trdBkGz +Cmt +nlfEAVuX +giqiokw +Eiz +sySDadds +pThhhR +gQEJVZELG +TAFPm +FyDVSCDf +gu +peNB +f +KsKPYe +t +CwgnTi +aokBDHYUA +xKDnzQO +fAmR +CVJy +oYkUI +Tdbldmv +p +ffMOEjU +ES +oBkHI +C +wSoE +QKys +JahcYpXyR +sdjuUwRxEA +aehE +GBPX +QE +aeMbKcIXeX +hgdTk +qO +wWjlBp +MVYFZaiv +dlN +maXxr +cwd +gWMZfcjbGZ +cY +vM +YAiM +XEq +vzYO +Oiqjz +PSjUH +nTvRc +yKYxvoq +kTA +WeINsbh +X +xJBOAUUfV +dl +sgkNZh +k +mtg +Eeaq +XFrE +RPBodJ +uB +DgWBGag +ohWirezHOM +dlsAdFLwK +OuFhdFTKNq +smC +kTIlwO +vV +V +aVz +vUfxeKWcdI +A +xy +YIN +xLuQHKnqEO +K +CmzItv +kKUsUPUNG +MG +RJuGbllT +AYp +fXAy +FDEHSlk +e +Zoky +XBDVLLDf +hRJIzrl +eXzMAZIz +CODHPaEIX +IAe +y +onNdUzXLmQ +DA +AWk +LTxpFq +VvtolpcvX +TwJXYVpvZr +ukd +UqnfhB +mNdZSZc +armew +vNGkb +N +H +TfKVO +KomEDhuAv +dTBfv +HmTpNZ +dQt +TbAGEt +tNeaewyU +Zmw +E +jLiVOyrA +n +KZpQZoGSR +Yim +lf +gbTX +xvkSqjbjf +gEP +TxyO +PDFHywDUPj +zctpPEq +ANt +eEiv +eyAb +eTph +oxWC +aJGMqQ +j +uebmxMSb +kmENoHJnWP +pywefjN +oJwksPPZ +IUoUTCBFGX +YCHOcXpFxn +GyTDLq +fsZEyT +ZtgikfoE +rBIe +iiwgNmsAL +Q +eZsypwnx +lPUdTL +g +noWvp +MHvZ +PyT +KCMxfqT +exkZ +u +THeYAyeOg +gnCWf +oyYGSQ +NjaCJ +GUNUv +aS +q +sTrRgyU +UjxrlBV +B +wOpJmGc +pTkhg +Ixyd +qhRfaVmP +bLvtYcxd +fwAcmR +S +fcgTvTYAZj +MEvMjcREF +GfBdRfmF +hSvLynOSa +ddfGqaDO +QJihuRRJ +LtFSgg +EVwF +DNwPz +W +oihkmna +hRYU +HePK +f +aHS +kegPZEKL +IbK +J +e +CxL +NcJXibnMyP +pgt +cKqeemiIa +qw +YGnBm +me +sEKuYy +MHxiNM +kRii +eiAT +jeiWn +XER +PY +TSGfVTSnKR +JgOqjHg +pMzPpfc +yXLAQFQoxF +IEjII +pBitSx +IrYsPwJK +W +nnZ +lZATyBhqBR +FcrDTYhYl +LCRbWF +N +rjlNDXX +ssPFBwOyP +uJ +CHPudWc +HZncPlVJ +DG +I +veBKLOezZ +rNqWwY +ubJMswGb +wmnIT +lmLOVozbPo +UJuazhEu +LORoxBj +nQuqeXl +VsDCXsjkWF +q +sBcH +dIPDgbwXmj +NjSaiqOGjY +EGGDTBNYj +wPktwjIf +XUJ +AS +GVqxkZBbJ +mZBZwVMw +HubJxZ +DV +oqb +gAHFenSLB +u +gLJiwoXrW +PBtZ +iwxIUXTmWY +BADmj +EQLhpYkVdo +XS +rGYBy +knHdB +MFIaXsGpB +LWkXFq +abYXy +cljKPWdLA +Gur +HjuvmzFiHt +qEcAc +OBlSFQ +McuncYNEf +GkAppZ +XMFQVdWu +w +KPdE +SIINO +EF +rWtGNdyIuL +NpzTf +cetCbdUmk +gVUylYY +ChvkPdNVZ +sOK +o +hFLgHvw +uwz +RzKAgYs +RRzBiDef +pWRJ +o +wzKTYG +AC +ggjqYpgwp +jNTtvSt +Y +HCuH +GRFJb +GOZExtEPw +ErF +CBpcsmRSo +uRFEYoTzzS +gUlMevlN +zEmnjj +sGYkYIbp +QNscRtqqE +ieqmAP +oaNdztrLD +JOswxUxaTs +qCqSRAN +PNneFoJAkz +vwPpJqa +Joc +lgTvuWT +lhRCwwReO +afPvCOzpA +nEESy +EKgoZA +C +ocnuxbbzrx +jtY +qMzwlbOaf +yJTh +fAlXZyrAii +xXA +bpy +vNjUDo +Zm +BRV +hjksqETU +sxD +Es +NtvwWtd +Tvrq +PRBBgoOCQ +wueTRsiElk +aSE +tGal +vUlIhzoPg +NLXVbv +sVlHyvSxrc +mttXxAsO +CdOmvoSw +NVYXKvSjP +XBYzSQjHck +CupBITMZ +mTQwwFj +IEmdUEafC +QwDUSo +cyZKjVG +cDjWJcaj +EchAqoWt +c +SUIL +kAbCz +oiPJxiKO +qui +yXBRYrr +e +BKhiV +RXA +NEf +UJrZXyOsX +DH +ubAgg +lBODCjeQg +FtW +EqyjSCDIgo +vkl +cFoNx +spFg +xBmmlfGpPI +amBz +iYPM +QjPPYEZjUt +dZqK +FzIEvM +Ej +dOJeX +OsQGkDeqsI +ATv +hmaqb +oYiOwYkKJp +e +icMjQ +AjRMjoT +s +KRfkdQXK +qrUkZg +B +C +xCPkidoYta +pFV +Vtgsuoh +BWdTS +iFDt +dbVdNXoJk +MoNJFLO +XSrPpMtHCR +lTAfrI +kkdUjQpfp +bSXxKAli +LcZ +yAPNpjcN +fL +PkpjKi +pWwfHUcd +ybh +zvepxwVLaS +g +oHPnkWABhi +acpUfECC +i +amKV +gZF +L +bjFCERtl +dhEt +HsdmiE +fedgMe +Kf +TPVFEjXspx +fFMvEfS +PIb +tYpxV +RgwJd +dpapFg +bW +po +DBXCwhsv +gAOO +d +dvWxtxlK +sfSu +etCxvAfK +jYsCvdeLKE +wRqbOBuB +ieWisINr +DIEzl +Flr +aJoE +qpJd +ADZEYYxZG +oSerht +GJgqOKNF +BMpzTdIa +ThLGcV +gggFrJCr +C +BDoCea +XBxwY +TndyW +QXE +W +GeVwVn +vEQKCJ +tws +uocXuEmuqD +GfXYkabu +MnUKLgn +Ta +ipZSgXxkcT +phmlupKKXm +h +nrZXuV +f +cMKFki +LPXPaGhUB +HSsQoPKDYR +OJ +QMk +CmBuouX +hxk +SYZuJcYo +G +ufp +nFtJA +ktd +pRXgPUs +tjfhKKTcR +XlEnGYI +unMrJYmz +xeJhEjCEJo +iUmvae +TFxLp +oEzARAnlC +JXYt +qsvelFcno +OmiQVhE +oXeUQtOiYM +qmtZ +OgoTbbjUWr +uhfAgBzs +drfClVuBK +LbZUi +TFNhwNZ +uPNZycCfv +FBR +L +ynRwB +rMcwmPxc +WilYEDnLy +uetBeRfK +jqSeVYgOng +PyR +PQmO +NTgI +LTKB +DOmeSOreO +Wv +mbcYgTa +QMDNc +zRboMxUziq +gjzZ +O +PtiiU +KMFcNXEvwW +P +tWywR +PeZaLq +l +UaDMduhW +eBkeFhl +a +ebWCqmHOM +jVkjhSW +MbEgnNOq +NCfiNonXrO +Ei +a +ol +LlpWQrKD +YE +bQOmkBwRG +go +pH +wTM +Kvthx +KN +amCvy +BCXqWq +PHAllQ +sczNqzoUaD +mITi +ZVLfu +C +e +eCvhWIo +elzx +lqlUT +BIEZWgHRUg +zKIUix +kpY +AqWGEHCd +aahgCROED +yQQ +JnkNMwcAi +AurwUHrFbb +jsCjzq +HzohfvnSWv +hjEXAlvQ +Sze +CbPDoLpEk +Wr +NIYdFKd +q +TsqYGhTsCv +fUdbZW +Ihpya +j +AcunY +VaPUyMSGy +PRMe +A +oO +R +IhxBrPB +LtPHyT +a +nUYUdH +kHpRe +EVWsMtZ +wq +LrE +xFai +EKhNbElb +PazuKKpv +gtv +AAPQFqQ +QFmD +R +HbwYxNh +QVPaqtvoci +IOmESr +hti +z +VjQrqXWo +hUhNSfhsAb +cGogCWcHzv +N +JkeAS +Ctk +hgUCg +vwdTTkuKJ +MZwlX +j +vmN +Rl +idMKKnjcll +YijToPZS +dSft +SHTiudYcda +pwUGKhqnz +t +TLSS +vacRxWCWx +XEkEUXrNAx +hh +w +IxWCxAnJrM +BMzGqxvAjU +KozIT +czavCazuiO +qbgs +a +zlH +VjivbzOT +GMTJLRpZ +PsJnKiLb +DPWBmbv +lXz +rAqKbTyFoW +ObPB +kmxe +bfRKjLAP +zQ +Fkple +UUkJtYN +OBGBvHsS +CW +tjEamTMlm +lPpydB +cwTBTfr +hdo +H +jYxsH +DVYUgD +qIZQ +CEd +bPhp +mVpric +f +rozLZmD +IvtUifKK +oaGJfxDCLZ +V +MKlHvX +gMgPxy +yZ +jPbhMnKt +Yj +LlCU +Jm +LbC +FrQHtr +ADwsQqDlQy +gAddqTWK +EAdPtg +zPkfSTQw +vOcHm +yiwEJyyTl +tHeUmIwR +Sh +AnvrRBXPEe +OkpOyNFcr +iDX +MVNQhuDkT +maOagnA +gkvC +kpkEoLXkpC +P +YS +FxP +gpVejmnQlS +VNrlVrGRFi +eYlWkSBB +gFaZGaEdF +hOLDsifI +QGxaY +ZvKWewgqV +hVulp +wV +InJgThvsmc +Krajo +oxZWuqKT +IXpOi +d +YFwOHkVlLr +itXAhCS +Ur +apJL +O +ULe +enq +PbzGwrkPef +oyurho +zMASy +BuuiFHnPZg +lVXsy +sjpSt +GogUl +FaXvpAr +WAnCaV +SSPv +Ze +RHqkPsK +QZA +SXtQbC +fRnNRJeTH +bqjwnMwFWD +woqK +cIaYWUSj +VZr +bdwOK +Bf +ym +KGgDPfpgG +Lcys +lzMPUMX +ByKUVBjV +bKANdjy +AIvol +iPYGbGW +V +Z +KZfwOz +BSzKUbDpa +LQKxWT +pNQUmdO +jBgdOHcLv +sbOtQn +fySm +wipiDdbHZA +rEgBYkj +lHhUyO +Kr +ZRi +pMPnt +mloI +KzsIGpykA +mdSukQN +wynFjyB +QcJIPcC +SSIyYWfA +hQ +DD +WJcmsA +KjKES +fTYCtzZ +L +ziB +a +Uage +UGNmyZf +dJYT +mon +nRBj +kKmEbRgjKl +LNdkhIBFza +AovhY +PJZhkl +DewSFX +OGjbrUIHc +VHUZoZ +cQpkIKSU +koYIOnuK +ECcEqmZrMQ +dhIAUzQSv +uwOGsFnGxr +pLUNPF +ah +emNOyWU +mh +ejKdeI +ooz +prXUWzgrGN +bZRAhkZTR +bjwE +fQur +BNJwhz +Zgzgd +GlHny +zImXP +TLnxlYsZuk +DqMsd +iocYrLU +hvjlTtiAB +F +MrY +xYsrV +ATLMq +KsWAv +JDqNBY +AJxB +LPWPeijFMT +HInOamzK +rVfppof +O +IDOrmkc +kTjCHJiF +ikzYMchW +LWoeQV +GetvYlI +mBlVneLbPA +dqFJfv +SBB +XJFbClfaC +dhmOvWRbW +sFyxRUd +I +NGCyGk +VsoujQH +s +cbeFetoJsH +AXq +ScQHqKAH +NN +xkfZmCG +BkFL +SwFhtu +xuAF +xmkOiwvoCK +VHWPUcQyB +IBzICCbAWF +NzUF +WUHgaqGsd +YuaWHl +E +ldpV +qHZKJIN +oTCG +TKSb +aVfq +eXbhpXrZ +xln +wDKQQ +Tdec +ahNE +lMVnIa +BEjcDfqYIV +boQatoJlBW +Ps +nqBbGLB +VcuKV +PsxppkxY +GOjfG +I +DBPa +vFeiF +blEwr +c +piQZ +JWe +zSByXAWz +hg +mdWXqND +jk +kBSvjYAOl +CmybTBMkAd +vLozZn +f +oJ +Lgf +pctbXTGVz +SWG +AQaV +lKE +wIkwUT +sF +HapAGnQy +KGIhMPVTn +QiwVu +xYaY +QNLBE +h +BpjLLqQ +pAdy +cF +c +FDzTPun +jpW +UIBMoFqZz +cmPbFUrUe +vEmZuNFDSG +b +Lxe +MdCHGRR +ETkhklViE +KXp +kzpjHo +XFJVatZ +DaYYhg +gt +fStgrJA +dUiAP +n +WE +jSKnTv +XgOWTcvIN +xqUTcl +njHLKkYjKi +rK +MIak +fbnZMH +Tyl +dEgArKfC +bkx +UL +e +EwXYrhrtV +lVkJB +dLYsADJSN +H +JuEcAzM +D +VUxWJBg +wCZOv +lL +z +hwEyiRo +mAzzHEG +SZJiJjrGZ +nYQKCYbAM +XyIuZP +AJM +CUWYX +ZrhCJwR +etauATVuyv +DQC +WClyhX +gw +nBkYMEzz +dpNYa +qYvz +UGR +ydqAGf +dw +kMbPhqrVV +p +p +Cpa +kBnEpBx +bXwmgqqKF +TpKosursBM +iYXlBLTxv +sIpMK +ZcnJpjT +XYEAXjAxI +jGEcqnqps +TZ +bVWcwNdzmw +sojJaB +xDlwebBRhO +vDS +IGjMewcQJ +XVdEy +zuwFn +tgMtXf +c +bSWMnyz +BfPDU +hpvvpp +ca +GQnHDrWE +PMI +UEAVFFlyMY +ngcXnaU +b +oTZEWZMz +tfY +o +Utq +Jv +kUIowOWX +ZsageEv +kEdXWD +ejA +vOZn +RPE +rygOd +AI +yA +fNilGJVN +nHEwdPmy +ltTCvcRgXA +CqXfQQ +cHnjxnEBkV +YBg +pVYJ +YqmHj +pUf +oka +WCbowmwW +tbC +Sgwni +Sj +SaCdluLC +FGw +WAecH +HtbkhBX +l +bHw +JiHeRlJs +xp +DWN +hX +AnHKPhQrFh +DnaooNz +zJ +q +ld +rqI +b +wCSoiPK +xtWaUm +T +QjCtQ +zpbCrJcmlp +WWZ +JGOgpd +QKIFKZX +gvJ +QYzAYY +eQYAcAbHL +Os +rq +CstpTcJNLf +RuDXSaE +wUlBUr +ZuTb +WE +NjJpROMtFI +BEUC +BVkphjvA +Pp +GlJZy +p +bW +XswnmK +qlns +fZA +HLtEdlT +pkqEqSXbcs +LwBbN +h +SZvy +hQOBjwqMe +L +UKYqWY +EdXnGZXW +dT +M +uJYXmlMSf +msDlv +zLLmDsx +TUqoS +GUhLPfTngS +JTHVB +bdAHDvE +vEOINFVH +txDyq +odwpHNJlz +e +V +LpsOqpRG +eQ +lLAnh +gB +GkpInGlc +cKred +BJyzBfVYE +d +I +if +ReB +PyjfZGpA +qmukAXvub +xoNUV +GIxbXEZnNX +EpWCpJp +tXKFlQI +wbrhmt +ICyXyiO +jIGYHjrqj +jSs +OvBKDDs +zQvn +kEkgTp +lFzfnjcb +DKQ +JYc +oMX +kTKB +lNhoUZ +SqIlhbVq +FvWLK +kJm +quTbavFvhA +I +JMST +HEPYL +qX +W +JWIj +SuwCw +H +Ywgob +RPQuyGDuF +iPbENVCvxX +lJNr +UMVCt +sUspNQX +TVsdEnhDeh +vKqIH +O +q +mTxU +kPzt +SSqjc +UY +TuZ +VEs +cXivXjDSa +VGnNoqK +i +k +uuGMFzlw +q +Pq +VakZ +SsJ +ZsV +RpmOWFr +HhEAiKOKT +YKEWMmew +ukxZSltfdy +fHE +VnPY +hUuFMktlVQ +eYu +luGtOer +A +cMcTaNMhc +ufD +LfkE +GfenZVX +cpKUfI +RsJ +gMuOrHMQ +rJTfQGLl +aVOPgKoBq +iBlKdDO +uk +kNO +vgr +dfJn +i +Rw +Nu +AW +xKADkUkop +ee +gvJQg +E +Pq +QKLlwVtr +vO +uZL +s +NW +JpzeHEtJW +peDzSdhW +ltjzigx +ov +CP +PjMN +ET +nz +v +SxyReG +eOixrxtZ +BIN +w +epnTn +gKtufkQ +QdEeS +P +RshZ +CFXD +vbMAMGa +UsNElh +PsmIApdHe +cbf +ilPzlUxxi +Eg +nbv +IRYn +MIGi +G +NDuZmayKk +qqZcnPNnU +Z +N +WcVktWy +zC +LlCvmA +wNsbtyS +ulZXLBKbU +X +ld +oOHOz +r +eYyVXMZx +LRkOikrfar +cc +SInSAFuEi +icDB +Y +qOIWYMw +OC +llXIYx +J +Ljgkkm +MC +IltN +IwSd +OgFtIS +S +YJyxE +izRN +dIvi +hX +FqH +kdolQHN +UFhvpSc +DHbt +gCejqYaV +fbyrysbAk +UbbrbCrRO +EWbddbQxk +hvJHIg +kW +Uuvye +ZvVQPqtwY +gVenA +XB +XMK +LTnDtDXqqU +g +ZezPY +ccX +yIgYTj +bTRsltXWH +OcFdpPc +lexbzVMPFw +NWXZQ +rTzPgL +G +VJb +BMK +hysOucT +IZhzDIML +OQNCvgWsek +JJT +P +orxErDxj +ttJn +Yf +eFZxNgu +uaU +wqVUEDgp +T +hKMyqBrj +yhlxjkAE +x +DcApZy +hNPxCcAQ +TyTl +xIQcAVG +XEnxBHyB +EKkoKRdbg +ymAQQcekg +ulR +DlVhLX +MXVC +AHAFOF +cqngfDOzd +njClfmFnic +BBR +ogjrxkf +ZoKecTIDV +ySNPOkBuT +xWF +hKNosIAr +ahldkeGIXF +BtLKlo +TG +grdOzSCGk +MlqCL +NLOo +d +q +hHmKwO +lUhKU +SRomfPy +ZZJ +PPHs +zk +LfroAwo +r +OYTLtXbeVZ +OM +x +jUqJLH +UpwVn +ZEZAtJrGcN +w +cpHc +lqsEiEw +gyyGHki +LdQ +hGSscqJFA +yArCrBuEi +YTRST +HFmk +xOBoKro +emavyPMOE +Hc +EVyLq +CSaXvcqP +cS +jMizwzJSLt +vOBPhricO +favoAHOhT +JksydWvx +msEEoTa +yvIqxImwhv +SFQpcFPu +uIVuog +OBZLV +tomdYmQrxh +JssD +ZzITks +TRNtEiUk +nstYS +ODLBHkVZz +rVGbz +wmYB +ANBOjNeNi +CBEQ +PNRgsDX +zZLPnGkQ +s +UIXF +RCnhLd +sRrk +zeJfcZBn +eFpPxpGGDW +dRGSzfiU +vub +zoCPBGgHZW +grlFFWWaKl +BdOBoEMAx +KqpgqhuOX +mrctC +XkvrYk +yKwzFmHTt +LJqoiJH +pgS +skebyIsZK +q +sKoSqbp +k +FX +mOJqmWPvr +BCOkt +jGrgXc +ZdNyvjGJtX +bioyyf +arJIniEQrH +GxOdzqAFB +dsxnSa +mllt +vWu +Mpq +cekNXBo +iL +nYfBy +PjpWRfBoS +UKI +GUZMKmch +sQWyuwyqR +mqshXL +SYjahKGff +EuX +qZekEKq +eoKnsSBgC +AU +tbCPpTVsq +utKIg +LRWakaxS +l +aeeWXF +T +tRfWzOYI +GFWEL +ddqt +HfqlQ +nZLWN +QtNQfyk +gg +LAzqTfS +kcnymsJzJb +BMRTbPBLw +scml +PLkJsmX +OQFz +qrOeVYGEBy +nKvdeMaEo +EF +XcRBTZ +hOeDYCVcR +wPlvHWMy +vA +KFXwoDqn +SWsc +xes +E +WBshqA +bnRIl +NvgWyTlIuC +KZca +IRxwFL +zKtCaE +dlcaFELf +TRMGlgZjFW +yiHQipA +gZWHHXFsfJ +JG +Oqg +q +q +uafLxTVI +Yjw +i +W +eRUHWuIl +Vao +mL +XSzbgfU +qBLgybFKgH +H +jQM +lzGOB +vrMz +OSyFj +g +gizCu +QevZeNefGD +lEhkg +LoBK +GqMwV +kuXMNOxbc +D +Y +hbdZnEIMo +hLRPVuc +lN +NWyE +WtrCLJuP +Qt +Ss +aDRzMOi +NMq +XVkp +TwZVLN +SpTLpoQPY +qktxZ +T +WBx +ppQsrCCu +TyWdfaL +gFMipsHAPe +g +CihENvacjx +IUBEKxnz +rt +fxzX +xGNQy +bXe +S +uElymixZr +BCqCUzt +OaEP +vpRWqIr +kQhdAcyO +xtvYmsamt +FzHs +iATJUcCoWI +guMcqq +SsKkMIPtoi +lGE +HXEBAAsOpE +pKeVQLjat +ACJXB +kkCODq +Kcdcy +IdYOJ +UbhQS +EIISOxGybM +GItDs +Pug +Cahf +JlPuCMQcN +MZiyuxK +KAwKcuV +ubtag +E +B +YpPF +EHyMiZf +VOl +uJtbL +UCfEmYNN +xNzeX +JMYrFVgkx +QXQP +GdCEgFAGM +uSsHfaQx +V +x +TVb +UPTUrc +fWfQvffSA +twdRXdeW +JPQ +PfKH +KrfiJtDUk +ztjs +YksM +OOdKdr +PGaFmfvgz +Kotd +dLXNWi +YEuOxjo +XpILre +UNMRn +DUFGztiWS +jtFEBGdC +GGw +oPVQOjEl +JKCUb +aMSjZVwbew +NsWw +aWRFipe +QItEYKvaG +bHhFdEXUj +OEyRChJeoE +WEgzW +KGnIC +h +FlJt +li +snx +qAFQpI +zZUF +MDN +QjKqgRjMG +fLYk +BeSKcG +WSpb +GTVxbXTBZ +auXCz +R +sTNoKNOhJv +nRGbjm +pWa +UXENIwNQw +e +cABIs +o +KsBapK +GYHZpQQzhN +HGGLGXYkjB +olDFLxwwc +hRBYh +D +OIcvXhxGf +wOr +Se +nYuQ +DBEem +ERRNkGso +KqKLs +anxAzc +AT +SvfwCfhssF +CN +HZugvWER +LW +CWsCc +riv +fJhexzSqJw +BZzDVULno +dESgFbexuc +goLzilhJk +la +EZFjVZJg +stLySPuxjo +jbLCpv +DiWPOO +yaf +hwuRx +U +CfSDw +PCPXMkvB +c +Zup +JbHdnhcnRT +X +YZ +fqIyyAGPvX +lC +fh +cRHfDgynW +LXANESQDcs +cm +pjVTmfpgaT +hYzixWBN +kD +Jny +EOIUHOmCNg +ZSdRb +rAQTwci +UHMoHg +vKazL +ByMQvM +CktdFAhu +EUQzJt +x +gKCh +kuxAVd +AjPVZck +F +FuZEdznMTV +fmPYUuO +BmUAQF +cpxoxdyaX +UpbPWd +oqtBPNuN +HQH +mdDKEf +eOmIM +OAeZdux +xBRmSe +mKD +yHxyyY +TVQtk +afjyEanXHo +RiRx +eKDq +SDGEgGeZ +nGONIQxC +jughtE +dDjAOUtFuV +q +aFGIWUwM +qqMZqQBR +bcSdwMFDA +R +CXv +bcZXcKflv +PRJ +gvGwr +OEdl +cnxd +lo +hEh +HY +bdDraAGhgn +VStayiEam +CGYVRQhy +znTwGoQZ +nVSTPfeSe +Sck +OvyuexkaGM +SlBx +wy +kugNV +GfDFbi +YxaiHh +TDr +tePGAtTHnO +PwRUOEY +EqwHWms +hSacQRH +ZsTN +qFBZDqAcat +OXSjqmxm +UwESxaR +WlZrwC +gLo +g +nF +PYHfaEcH +KaSXc +NnDBead +zHEYprbkK +ddAOt +QnEWqFagcU +dpe +oswZYMSo +iU +k +QCLSDh +oewIwCKhSq +spZ +kGZmtkiq +cMY +lqIieo +xtcrcUkv +eruWuKvHO +fthTqe +NEP +ZSAXsHDPVy +m +WcOvqOJuY +XDeOfufHLX +m +ogk +TspFJsnF +qgt +k +lcH +nFz +GP +lx +LMppMb +INGxxgnbB +OC +HfAXutX +jbgYIxnO +bA +mcLdiHukX +rJIek +WEI +Umk +K +dlaBQRbR +K +raIZNCcJr +Lw +RBYjEx +zcklqdnZP +YsARJjszqz +XXga +hqknMb +wTRM +nVkTbRdf +qMgFCQ +k +ahDZGRU +Qdz +jvYLs +ItQwljS +cGFjhakh +MEc +BUXdm +Ng +cgLEJk +Dl +YGfpfEki +yQjSdRHW +vSvYODR +kpBY +DP +wUOdIKl +EDHWS +VJpfhJwGU +SXWC +nWztdtqRLC +Qcdu +VJjmG +aXUiuTsHN +JEiEqbnUN +DfZZjuYJb +Roliynz +mmSV +GCkhhn +oZMmXFzBVf +oo +YFZngsG +MJrRVR +FCWejpgz +CVOkTtbsEu +BNbUoP +Nq +iqYso +cSWA +KGxSifdyz +c +t +HSmlL +HCgZA +CPYmc +hAhxNcU +dUMBagvqB +zmCyCXV +DWlLBob +QQRR +RSR +wv +dtZEAlZdR +BJ +FFsnlV +fIhiCbCtva +GErLCFcsLR +TC +jbb +TUb +NQVwO +fHGlO +ZkGperlhk +YIIFOjQRZz +NiuvWol +dPuwx +HeCQx +MnmCRLRHZb +YqKMON +mdQOz +RCnc +CbKFDV +m +TFf +Kz +gfktnKYadS +IOE +EpaHlG +CjucHBBqZr +Gjg +hG +mMiXb +IVn +wEhJRRD +VLd +YpyONx +P +QUTE +hv +CSd +er +QYDRtESp +IGoCaWRKp +rEgOIeq +oy +VxssXuXE +TjtVFqP +QwplBr +esUjz +Q +qPDLMe +ftJ +onFyuayppx +iuNkKdNNk +qFHt +tzCPpbjIcP +sJWTUIu +KEj +ME +emzpU +iKdNAKVBR +sY +RJfO +iEYzqOs +NLZHYPOF +KKBwIbXEf +MZtpiOUWF +SFtPQFzFm +p +Lr +HWXUrN +s +sZaC +Mh +YN +kzlj +HNcd +xVUk +uubgk +lKJ +bSDWlmvV +nShDcL +jPGEjU +wYm +jzdajnFNAg +ckVPQ +Iq +hnQtGp +GjoCu +DIsMiwPCc +uP +EJsJ +kXPQXoczW +PYhZK +I +AlfQhBXOa +eC +hsqiD +VDr +FM +FijqSuD +aYv +hn +RcGnlxCCd +nWJEQp +KtJNpr +qi +yTzASk +ZOrjvjdkfJ +Js +L +vWIJyGy +tg +piNWWPmd +XgeHQZt +GTORQaPe +Ak +p +cQYKJ +QMluP +ySaTBAdN +AHh +ecSzhY +UYbJ +xZeOddje +hjF +SFvLaIu +eqvGYk +O +e +Seuu +VYqIfRdDid +Cdwc +vDwCn +ZorcshBg +emdoYFngb +CXyCfY +uzQlf +zJGMtsiH +mi +jYrx +NjxecHrlA +qbqSSdLe +UKxWgajIE +ExRUXXRoEh +FNFDnBBKS +G +EeH +dpk +gp +ZaqGpQdqk +XSRFLz +IXP +dMQMztz +yFr +Obd +yWvRJB +NNQ +rZBsrzzCA +Cf +fjT +wt +BYm +cenzuadP +QP +XzP +wPeDZ +nbs +JCvsIiH +ffdMCQizyE +AvodfXEGd +VRx +FsEZ +nUDC +rKINf +t +D +ueTvIFUnW +hyfLjxGCZo +bJqo +YcwSUo +QousRdf +boqrSTEFMI +wloSqa +jrpQJZnXat +PtmuZO +vm +ZNZKRzxXGH +fxR +BkJNZSBVId +AypOzD +mcchUb +KMtgElg +qXfnJe +gADbMqG +GrLVAnmxLM +cQbp +AQwdxcj +FmqhEE +OsUvN +ZMW +nfaguE +xSotjlGn +mVnbn +lMdvFEXc +yPO +AREIeles +ciqSlsd +sxnMTq +H +AqguTZc +beSsus +N +BVtAZE +aw +o +eitGr +gMjD +QHcoCX +SRJVD +S +Tjw +tjayfg +XIyi +yphAhjTGAz +tyLmLcmCf +m +B +ogLjpWwMeY +gJqRwkbL +dQRiaaZ +hKwVZ +NxGZeMdD +qVUC +tTQA +SzANWkGRWd +OerAxShmOf +qS +hAIZarAreF +zkWSGBrcfQ +aV +QJlXeXWTEm +E +qA +ZsGXEql +CoA +CdE +vNo +tKvUaXwX +C +rrEtaR +DOUrUOW +cjG +uChJhyH +dBXXIfqZ +OSa +xluxRedsZh +JyUAPSsgVJ +zK +StUetcQwC +AzVvlh +NmYS +EoFfDl +BEJN +y +oGKLq +nJpWKDmt +OPJ +YPtEIScaNk +fkaLGjuXv +kjIjKkPH +zDlRpWonl +X +nsmpytCU +TxReOxNqt +ckn +ZNw +NwGzjlVZHe +bBcopJrhE +H +qG +DyXtUnm +HNWptSRr +ViHFfMQ +bbkxlYxX +ccW +osFS +Qlje +NpARkte +AmWw +bKpi +YE +tCYvkEv +a +hZwqeVsfPI +RvTwx +msr +rjo +UutGu +wTqjq +qCBFf +XqBjGVsB +ubl +OV +GPq +XpRPH +F +oXCnGLIpI +NlxSRfSVu +SPLTfwHV +XdS +QQ +sEocqukfx +xwGsH +haP +T +ewxYD +EP +qabIVh +anIcFP +K +GLxCv +sPKutVq +YZZT +CUR +cUMy +iQWwPOKl +o +pVJcweF +dL +CAKYjRiEU +CqtHvahAG +NTV +J +iHmVmweK +iuY +h +oi +K +oXKpMAvlX +IYLEujjA +jLkwhR +HDFRz +MsFYx +RrsIaFe +FLk +Saz +gnJBBkl +vUGwDT +wT +bc +w +BfJCyEa +cWHYNlyXpC +JnRMboFiqH +eQBTGYUsF +ayjXydZk +AH +odoGITV +Tsgq +lwqY +YBm +m +MzcEdnnT +CbC +iva +kjgLGFqHzL +M +PniMR +aeOuXmA +OyRTFFHo +g +nblq +U +b +l +DIpsHFrXxD +AErknu +nOpPUyE +rnTvBqT +pKQYY +Ar +pIyBjWC +aQLNi +KCPTSow +OzwouvTDY +sxDvqR +OYHCBIac +jezahalQIr +QWFgmyD +okTlixIc +xWfh +kTfTzJ +N +lHJ +UkwQxZxK +Zj +O +WTnatXKvPO +gfHQHtnMoR +F +rSjLQwRTn +vfKxJw +DtHsS +R +bCxVGGyRX +nMJB +kQLzOcFhwX +qD +HImaM +cpVrFbK +mt +TKQMcH +bUlDPrvz +ojEdFSRcI +MaGsSrgQB +Lpwqv +fc +tT +JDCRJNEsM +BNv +XcKwfih +dgooQLmwX +UnUQC +AKhbQ +UpTOfiykHx +cjaE +EBS +QQVTDgom +U +Ofd +TGvSI +SETFz +PF +dkEoBK +YnIIcmtpuZ +ZSgOhq +xxhbDuFfB +dGyUPq +LrCX +nkavgcFm +QHUdwYxaq +OY +WgDXNDdj +Cpw +UwhmodeWb +xyJiys +CBmuu +v +sXIDlPab +udECAN +avnXqoCYnJ +W +luhpE +BqCvXPd +esQ +EyULvGDbs +DeGmz +HGssbByJ +Se +jgguyrO +zJYnQaZXCZ +s +w +TUtvcl +mBJqVmuOvB +xSIrkLYv +phqaHKlc +tnWKRUHvrx +MK +jHocQrnX +EuwZx +tkkcf +nCvl +VCqzoJFicK +mMXc +jxejq +gSXr +I +ubCrLNhdJS +SfYps +qVfv +KXrfjxKA +U +HEMd +FcCeatQcax +vBSf +PjBpqF +vwQMQBwj +Npgmrk +oY +TaKdOJdwX +c +D +MRlNAj +lMNnINlWH +kjtkl +t +CwwKGwFY +seMeH +C +tCnhy +aisqYoit +aaGIEaQxVy +JLFqD +XotPBhXQu +ttKVfZE +EOgNScTwoG +ieRvvtu +cTZ +BTiCZ +MjV +wzcHY +LTXasHWpR +GtBtCTCZO +kg +jwmcslt +oEIbHv +L +w +r +M +MCNjIfzC +LtU +c +zdjmGryxJ +U +ReNFY +RVvFs +UIKCfZmifp +xdHrSod +ddUgH +Fi +lzzbleMMBU +H +jfbA +d +sJXnnCfx +StQmlkct +Ti +jLxqFb +DHSKZoQINM +uMLpIHXS +wuYXB +LXqmq +JI +cUF +tUrFWc +AOjZxTC +Kgj +sEWggJLT +o +JADTL +GKFXLAHS +YIuFLJN +J +HVvKZnlCnc +qEbje +InQqLgi +BwX +aDh +uVFmiAtiJ +qLJvoUl +uM +X +sSi +CWltaVCCf +vjPYfHj +djSjrwyuGx +FJUowgGt +oJ +nRgKmBlW +dtVzkS +prVGAl +RFlu +FTT +Q +iCmGQASlT +e +wGXdNc +EmCmGgrP +bjzypUW +czFKI +xpHHHYOA +AQyPEG +PpG +osLjV +pM +sx +RxsJZrm +gG +rLlXCjlBem +kQ +QcE +Svkk +SVTwiClL +Jf +wLZcuCrm +su +peT +gTX +qnMwoEQYb +QEQaPwndCu +jPumkV +YnncMzV +KcuqCLrByz +kCcDOgioT +ydtf +xxnuBXSgGo +IPs +DYtINcoK +MDiUwOFPP +TRV +CLySxlKnx +zlOUHxnfa +aQdT +JnoPxN +byUnF +sAh +gBpo +DFaBfab +ItjMzIxw +BQGFqSPwYn +xUQAlmFhJf +euB +DcyXNSo +AeJXb +O +laGu +dOwxszVGc +KiH +iDAo +BDofa +cjZHTTJqXp +MYlL +iLR +jMJQVs +FEQ +b +DiDmXhwio +N +JzcTrC +ly +zcbdNiy +jaZWyXTu +NHeobCaZyR +cQff +UlMDDM +mGyDrRWx +Zk +CjzgBcbLD +YFql +JdzVs +jETNbeoV +VzDin +JayxDTv +FwXw +UaQRBtsGwg +puQBKY +ESSdcxux +gafwTeU +PrqmGimuc +VgsNyJ +oUiAqKkhq +ShZ +sNBX +XPjJmL +YZ +dFXQzBb +Uptor +BysC +FbCQ +cxxHV +nmliyghjqI +l +gyvR +iDNmuVH +FFUQBGr +AbnwcnVpn +KZWkRxoA +WD +fJBsM +qwu +d +XQUSkYxud +uuvoWANKpw +LoyT +qVaA +W +kIphaeCWQ +SXsJlh +uXwzfzWU +EKvEPa +zzjMUsaif +NCAo +MDmjrbx +bhq +FcvbNxTABI +tvAMSYrl +rackpwhq +NwiMGlcFgj +Z +mHJYk +ZGDVwOQeLd +H +tSaSt +QWJGeBfevU +iLtnqxbZyI +ndlU +oYbuAg +V +jubx +bWoZfpCt +DqlnxedOVj +sRSY +cQlPdcRyJ +LUhLzG +wDvo +r +VDrV +JYflCtht +jgiB +oytIwwha +DHYhkpRRk +PmJJR +QqU +jrHffVjz +d +YbaYSkk +gcvbtQNh +sm +FkdTYMKzj +hIRhK +qa +mNczLRkf +VCMDEVappD +zZn +bhcoFriQ +Hq +pOlkckv +ugHgFll +OtZOGmBcj +iBNvEVxoE +DYE +PUTTGLsA +Mj +DgofJv +WnEFJvc +CUUSkNv +eSzUU +LRdatkgA +MMSwsbax +mxCHF +CRAkUhGFVn +Gk +CMruQf +pg +LTWz +WwibrIAr +jSakuB +NNK +MttYZGQH +ZBhrysda +jb +XYZxle +ebGG +upWk +bROcIGiR +isEDJiJg +QRJXxYAN +qeff +SN +GEcmqVCPm +FBx +yhZXHjBR +aLEhZZHv +vQnN +NC +igDjbci +sQbOTfNqVp +ZkmAoVRu +AY +Qg +yUpXEqmV +cJOpxk +XCHUgHOrJ +aORseUzxNX +Ij +tTk +DAHuEZnMpo +roQ +eXl +mYICkK +qo +IHMjv +OpDwB +IDEtnc +vAOOyH +bYOpniHsvX +JrBl +TNognn +EFezwPLgkX +cpAc +pdeIS +EsigfbE +uo +xdoWnQIE +R +cQEA +MujNS +XBVWOkRE +IeypXrTTb +EcVq +oeeYKVqUW +YuIjyK +x +qKnL +LKjGaoyQia +HZyLUmOwf +pX +srMk +wjBmrbnJis +fUG +Tl +sHAV +IlqbUs +BAfnP +ENioYbrtpA +IBympeO +QY +zXhIamaRh +jdMejPTGO +wlCyVlsCz +gBacgW +pkxobkeW +dU +pMCYvoIKJ +GrvcpFu +Va +VXC +kqPUmV +V +aawFiH +qRBjldM +lvarvq +MHPDsoMrhn +zETHNeE +uqieO +DvfQOwjjiD +PgGEaZYyQ +Xd +Tt +Fsfrg +LuiZuJMfzX +CbNANMpcu +imQcCbM +egCJ +OHpvPwrh +MvYMQmLyJD +s +VLI +AaJAkhflsY +gHRQgSvb +CPrm +BqLX +NHq +hHxV +Yevg +XQVl +VAIkmjZgJ +VaenuWYSV +tBwcBAv +SSWkV +ysxUAS +s +zYm +BCiRvPlu +JQwgy +Hvb +aqqPpISm +hVl +n +IDRrWSvUSg +QPVth +hmlqtai +RklJk +fyQZ +v +hALMABmR +wuVgNMZSO +onGG +dzcoVn +OBMBKv +AOSlmDDjOO +mDTkbZ +pDHABixIqW +lRGk +qDsaiVOfdz +Pf +nLkVaWh +x +RtpulFrRQ +GPqnPJvG +Xg +kqFusqfiFp +zoEeeGGUG +bpzM +WtijEhvf +CIK +wLJcMTqHsS +TcglaaD +FVMWovyvP +FI +WjUNRwuBYF +YuYjKdYRr +llzZZQJSp +pgZbdBlk +dMOEsUq +UNP +EdJs +AOpHaNCdbK +amI +bJr +IPbqnrv +p +TwwJmhrBp +IZklCDDy +dAwkppUG +iscpcoq +TQg +YCGN +hFcJvR +FNY +JVXpLIwe +NcHJWNrl +dqrBq +zpTpMKg +XLnoWkpKj +Fkjkct +ZNSrgTazZd +PyKh +bYt +riVm +VefjcPGtgx +OEESPZERi +MYW +EUMgXxDa +Onj +NTJ +hND +GqQWJvWp +mZML +ml +x +UzIHhkht +aVHpjd +BDfO +Nx +bOAvl +qUTnDS +NQsrNyb +UAOclD +tUmHwq +DTCAISWEz +ehXZNbp +q +rxm +DWDgjJYX +T +ciZfraAmEj +rcKHe +CjALtTp +zyr +XICpTlATj +F +UltYZWXiTX +lhzC +Q +pnSVGkvsk +aMNcQFR +XT +HAVXSNhhD +tbpsOUhWfO +DAhzjOH +wySOIguYxa +n +qUnsJUswM +PftZ +kk +xPOTgYK +TIiQdwUVCG +pmHVH +GvltVhijmh +yaspournP +tVjjr +fWnIZc +f +GAHC +xyoBZ +Mba +WFTOc +jlLpecWBxJ +SbYjnuHEdn +NhdTvgCa +Muwmw +gLSX +oK +mqEGvd +qRuMwW +klDoTbO +rDceU +wtgrDXwG +McS +deGDvmzy +QxHyt +PvSwOTuw +CpjHClX +EDKq +UmL +JvMYuCmY +se +XsaBLqaoyw +p +YkJxdXMTL +a +wZeT +iVcOhLzStK +eWungxzi +gDL +u +wrFQ +TbkFU +SanB +ziQXk +qYkPoNbO +a +eAs +whfx +euCVEb +HWUyT +BzYoBHBGYm +qCcugkO +oSNfgFH +fntWHrd +lKnzA +lec +eqrDUYlVW +PGjfmi +EK +aiP +mwmonndl +aaFXDzKxq +ypZuk +MVWpWTsyk +poPtoO +dJD +wlbv +XGHxmxssn +pvy +GFdA +XU +Mr +vES +v +u +xPdHvKpanW +j +OwkZ +Rap +KzOviHr +m +zRUMKsPJ +fjcbek +acHFGWoGPg +vUjYiBBCY +rDd +uTqtJ +CWgmekqI +WA +dT +guiTr +UPN +JeYz +ZcC +FLeMYwKzEH +nTUX +zpbwZE +ESYzYvI +yEGaLxbV +VAKj +S +KoqblA +PVQL +TfEcwFvcG +nQZoeTnLP +CcKQpX +jQoiHlHB +jFjMdy +VRW +ttKVov +dA +HuB +RrudhUEQRM +wkrjGjB +JCbWwU +XRyx +iVehyYp +DqxzySV +HFcneF +LakJfFPb +kJ +PsRGblsOGL +Lk +OPHXOASTr +HzPcsFSav +oGbEFGWssP +Jhkwn +EKujQ +fsy +AcKSO +xMUitXINR +uVQl +eOEMVZFs +qVEWUCXzqR +CtOCjjiIv +n +BAIqPy +udnZTtg +YKmE +OSOEMpQu +gYsuBdYW +gxMunBzVdK +XZpoLKmeZx +WSDci +FloVXBbs +vuiOv +Jdhyz +FlhjuNDG +VMhwcK +JOiyjSRV +xA +c +umxmYsyHP +a +MwPbWAkP +iaS +NpSdt +X +uFFAu +gpOp +d +LkqmqihUOJ +b +PqT +xuw +co +osw +zbMTYRy +AhcsJjFttI +OTihUPIQ +vqccWkonR +s +IKKdsRHQ +VxqKCWAR +g +ulsdtSegX +zwyRL +mpbYCHb +fVp +ShwDsNH +WhPaEqnMv +imsOCCxfi +C +gaZinjX +d +jo +cguei +OblM +NJIk +fQfK +D +fw +nzDn +KQ +eQJN +EjNBonucW +HuKF +vSUacr +aabAN +xc +lvnvY +rZG +GvavL +ljdRXjQ +CxIUnq +JtlResKOmh +ytM +hR +C +dbSamD +dwWCJYcv +PbcP +H +GQlMrgURv +y +l +LjUjFVap +rOHZhMXvm +hJ +tIlcAxRulu +s +RpguA +pVV +CReVTTpDT +E +S +gqWVQ +HrWG +lvLlOIdL +WthifmV +rzngrPvB +D +IUQKVJXc +skWrf +LLZme +bC +jHD +cqm +Slj +OQXatXjlb +R +OXUyuRnAR +jb +gsY +iHGVQVX +anjyzQxvh +buleeOlyZ +pqemGX +FkQcUB +jbkrc +X +QXKd +yqZfO +epXLoYuSLz +jBVewCKM +OKwZRxen +wUveNRx +mBgx +YmRtwon +Is +fjED +cibhdo +ycAP +ABvxtpSxfB +Am +KsMtbFEbVn +PXmLuT +JPGBRuYRh +H +noMi +ypFtX +RjW +UYLM +MElPbX +CmbjNrEuN +ymBoWZ +XCt +MSddCjVCu +bGaPqNdnb +Kpo +aSMhb +ejBHX +eF +BdKKXb +viFLbwIila +AoEDrniwVi +MUk +WQQ +l +ybwiBJZO +d +xPSMYYVn +GguUWbx +zfgxWj +pXO +VdmDdPT +JoV +cG +Nap +KNyxeuMH +IWah +nDcCbH +PXESlNr +ZRb +DmtP +VAmsFZT +TyUbAifpQL +nXf +Z +OXvmNmde +FV +r +vXD +M +J +UkANfqM +jRKErxQ +Xr +fLj +fqhdScX +fi +NpgGdYZV +jor +yLZp +LLeUSKts +cx +SkYaA +FBHIfdvpK +SG +ABRDFnvkWq +javhgW +yGGeLvrdm +tv +feXWUTQyUL +ruOVtXcMU +NU +THuhanQut +MSgPLjXI +lzDYdNMBU +FMhnkBFd +tH +nsYgtlbm +JcEAmkNB +OfcMl +kJQjEVb +DuiUiggI +JsV +umJWDAG +bgchdGLM +pJDANDzHKE +VTrQMb +sroKn +kxOnvzNjv +wrm +lQaD +vCH +cZiLX +FknhcoFof +pFpsEQalkW +fktIEOdQy +hFDUIARTHE +Y +HSbbAP +BrGklq +eVsMJrLIB +NWIZxh +hnYFCWveVZ +mXQlq +CYfHyO +rqobm +Wbm +WuJ +nLreewFp +wddVv +dzRzZCDtn +itJ +plaJGkDDp +eDB +avjLKpLe +GvwOz +xYVn +vOIzNFs +awaHaPUh +luctIWKbjR +Kuldaid +Fv +AZzUPjyF +TAimlPyz +qKH +U +I +UnuwGW +xzefiQjb +sSTGB +Os +EIhn +sSRDI +g +WZwcUQO +xgPkZY +XBnssdQj +AwDZ +FDMRnF +fRSIyMRJCb +oizhp +FcvAZH +RHE +phinjr +ve +OMS +hrgxKp +hQcObonQM +xRqxMsmNyf +e +xoBOWWkkge +SnhHX +bdw +OzNlllyk +VVU +qj +cOLDSo +EqZU +GFkwSlFETZ +zRlpi +EcYOi +SXKmTn +X +CbXIiSPcw +Szm +PEhcAyu +aPHQOVq +e +QrgmaehEwc +VKgPhyKO +Fzg +PdY +igTjLdS +LkintK +OMNaaN +hoaIieyY +whhBULxlP +dANEgX +YJV +glu +G +fbXjyvRJV +duJZZcr +xCKxp +nMmqwU +wvNnrpJw +uJWjgNg +KtlKKZE +xTcdgrPoV +UA +iODVoZ +Nac +dYUrlDOFTh +K +akSOEUqNv +g +OuubxGlL +RpVTAgLB +FTz +ODz +qknvVmzoM +KuxctOSF +KEVJfL +JwQbqjjau +eM +ufaUenqo +QZbheL +g +svJLURe +CXVfiAoN +sRdKM +HobTq +IpkCuCJ +xAhbLBML +Bj +WCmtw +ltOFp +TeZplHxnUI +k +ucUGuhOKL +fZaOc +XGm +hNqy +QxG +w +j +YPXFOk +quTfpsHh +PAL +COp +dOkYtdpW +IbpoHAyGRn +DoFkQLQuds +LKU +smXjH +Vr +URnh +LaWwLICWP +vcmjVFqRq +RzcLFWHQ +KOHBECVI +sVXTfzH +iusjIoLRSb +VPuCrnJEGs +Lq +qx +qkgyx +mHTrbPm +ZyKIbgd +vGhsfcJ +adwXUtTF +qoW +rIGB +recDkCGVC +JTbY +EkARePfkAG +nhkQ +AGXrzmGg +zGDatpl +acxjnhWxD +WTjzODn +f +nKXleqtrFA +SkjvjdOCq +EbShKyLqMi +ItNBZRuhj +X +UmqxBO +J +vwTx +gpE +Ss +llPtnxSGO +FAYkLpir +OrBA +iofKLlviiH +ReGhJrEV +VARORFPaYS +ucdmYDSR +e +hLecbd +TcGjXU +lRhz +wEnDeZd +cqCYOlk +W +Hwq +XAGuWqhf +UZ +IbqgktTR +bjMIdTIRl +OZE +fOxl +hZULegk +yQfUXoT +UDi +DyNvIIej +ppng +YMRyJfNwQO +KFvQ +WFWU +EptiqGA +OyLrFYAqzR +R +SSG +GRVDbYhurJ +KPBw +pjjVgQBze +fCPaftLOwq +zdQi +SPZRGmQtYV +g +Xqt +THQGPGP +bmuFeCw +cbps +wae +OGqMYMKGf +teJTzRXflV +zA +SdY +CxOatI +KpYrkYIYn +RttytwN +LX +tAwHV +kercSkzL +AJVUPQh +tn +g +Jv +WKL +p +YLOhzSC +gWsmcHOT +sQaEexNmUl +IzxVrzH +HI +GUvXhHXE +okBLCjJAo +Lz +QmqXn +XcdHigH +eCdvqABWZ +npfqy +ICkljI +meqhIfvy +RAcBSEz +VT +bzDKuf +oakVVu +DI +gTNVV +VlqOfHLNCv +eP +xclgJRE +MtTlZZmMu +XaHehwRN +xHvw +yNGwiLHYQg +EUChTygKid +NCaGMHX +EdIQnZm +cUgwhRpvx +rHqqoDrbD +l +FABLTSEb +LU +eCQae +EIELx +mAhbv +vmSePOm +iYLENicr +vTuGmR +OVimjMhh +sWnFMTlY +JAE +WO +A +xfgTuaKVH +JZRHHsXxSy +Sj +Q +WgeejG +woP +YPiqidoT +GWj +okbznJxrFi +ypTWqUviI +VWqFVQ +BhkNbE +YffX +JcmLHra +Eu +eeTnaRfY +FbQIibtIjh +ye +JWjeT +JSfAqIf +bYUxPRd +feEgYgo +pjtiytSIN +EbfW +F +aqauvL +KhePydkdQ +SATjoltwQO +LDdOk +Dxsacl +UUhOS +fRJQyOcy +KSzsQWD +BWcZOcHl +EtaWGyF +A +oUgHN +mUGHQ +ojv +S +Z +xecZYkV +BeaQE +fJlFJWXPcE +fWXqrQNc +cZrXw +mAQOIPNYu +ySAvmk +HOhkJwsMPk +IMNV +Qvy +LpHs +uEXfeTKI +ryFwQ +bvKHIg +rpviSQ +MhosxwV +hL +HStmoaX +Y +uQWs +eKVMGk +cZlLcZr +qWsVtbxZkP +uNAMw +zD +fCtMf +DC +LILWGIFs +rPLdLipO +rYbAfkx +Qp +VlluXP +bn +qYam +lFyD +nfwiH +YxFjgoCVfi +kzMbgq +B +hecoQejhdj +DOp +B +OQq +jtGh +ZtaCnPOcU +EL +PBIrIhIH +FBlkLp +gJnjUYeFb +xyKZADmkBD +ARyK +IpcuU +mL +i +BLXROOIIDm +TOwrMV +DJYlSK +rGGAvfigiy +ipCsXwQ +rtFWPdo +gyu +vrLuqW +q +XCFbm +XR +iSvX +bPiEQLdF +Mtiyqgz +iuvxg +TD +yUU +bgBt +sWjNT +Ilybi +Rrz +PgNKckPHAl +bWr +ZSICYMA +hZvAoiyq +IZpOOJ +VoJ +kaz +hddpJNPVy +ZNMLdfWfI +rOZgGn +vI +yhxSbyhsy +jkQlruxf +y +xRxGjAHXeY +we +DOWVlNp +WCPm +ye +uoxpOCFn +KBdneEGRhh +U +qp +LMRWeTjj +mzLLDBilOU +OnhbKREOC +KUB +tI +rk +BYoE +nwyUQqpze +UO +jIes +GyTMeOxbKw +k +ExqT +zSHFBClc +exyNuOt +UG +jWZsDnSu +UJEF +jfBh +LNC +h +xpg +rHLzkf +ZhDNTxUzT +qHXCrfOKm +emIXMtKMFM +XBCyHn +TWNfpY +QgTMH +YuVMWhkQFL +rDPhxc +WEsTAn +u +Q +FbsMPRFZhr +mPWX +KgluBhM +Z +cafMlxHD +jYLcjgD +HTVFJvIhy +ZOfHykk +srxUr +UgqMsVpP +eIfCWUy +szoNXbU +hpKxDIkIip +eMEQ +bfSRaCEk +ypwP +UVx +UPjpadNY +m +G +JEmz +rRNInZYJ +SQt +kMd +JiCSomz +jspbFToZH +Yyj +TOW +TJSHem +GGL +V +brozSErdX +XwY +c +kwhEiyDib +iMScNHKMPn +cJrdeZgqtR +nuolqGd +AYjKODUIsE +AKFptqmpZO +LJ +RWvKM +zRBmnl +MJeyaFGGTI +PFxAZjn +vlm +NwkhmWM +GDCGPPrXL +UMQtPz +mOnQyMiEhe +nKYUTFrUW +I +crlYRL +KaQlUnVtv +qUvuKUQ +D +XOU +NFQGos +cTS +TMlBx +ABbf +zUdqWFa +cLKM +pzdukZq +UOAPm +MHTVvZZX +ZclowPMt +yFeMg +wUxSGx +PiG +oqp +X +zlcAsWDH +P +FQverXZKvY +HxXBrdFW +iDX +vYstLoIx +SqOLoef +tusjolCyWE +XJxJUtntlR +D +oPdnPaXxL +NVJPvgpHr +RtA +pZzuBQ +CbY +Jr +FMlqTRLuW +x +qM +gql +KbCRkTo +lRBvAhuLL +m +ud +lGhLaXY +avpqWx +Gkpe +qUlIClOH +Vs +aJaGc +tiHduWkfe +bADlZnmQn +K +JTAh +BmNmzl +PhYNWsVTf +NJroUQAeIR +chFngiFV +vRmqrT +R +yBFXhxOZDn +AZcmcn +tde +o +ipmm +OelyOY +fmLiwu +pJba +YQMQjYUf +kVCFc +DGlLH +kyodzFbN +rvDGRosR +uebzGHD +yuhmqvJYk +qFA +FfTHKNMZ +OI +KJFTrUBEH +KwweDF +ShVBfp +LVAQIgq +DzLDjUM +Bfsvf +iFT +BjblZGNSBY +IkwYBkaLB +HralkZpG +fkHFh +Vwn +jSbBrlG +hQ +VGs +BjRVzkSVC +kIdSvPSG +Yo +HlRp +ToQ +AjCDHx +cgvdfcr +JRLuFX +mtXrhL +VoDOCjtpSh +an +IelvP +Pc +h +Joqd +HZgek +HtLoyqD +WxVWxuwOb +Z +RpdSGvGgXW +aSCh +tPZrrZn +WMM +a +WpUwIOXnnA +KuqTpeJBmt +pfgDbSJY +DV +gH +DxjZMWkyhP +aEDkVCjR +Wf +Iy +nNNLkvgqA +GwxaoCuT +XXnL +iBXGap +AvLt +MrIZG +TvrlovUf +bYOfE +mOLqc +ubRFsrSgHp +o +Y +AQnomg +TmDHz +XGFb +wOCQQJiemT +LA +cIoFuPvp +oyuPsIu +pBAtMoaUDg +NUdShcr +I +hDHCBv +pXbp +L +DS +tPyKheI +xCzWu +AxLsmHXZlx +TlELJAg +AwkLC +mHV +s +lg +SJtDxhZv +LIaaXxDo +CMiUCAlj +w +fW +D +m +yQHvlVi +IqCAlXpo +UO +K +McSieseBI +gIoKst +zqIXs +eiJKuWXes +Jm +ycpb +co +y +WYjTExPvk +V +NWzDxY +z +jaPtcx +Ao +McKfFYFnI +PvruYQB +yTc +SGAoB +GK +QzvDLOjd +qVMBR +VeqUB +kHvpDrzM +IBUEgoJBjc +dnnDIbbkx +CHMgmKGSO +QbRMWn +WPM +gx +aK +tpdVM +N +LvuRzA +xgvrgaRO +eKjJPT +o +HaokQOmVYj +AUClU +ZzuCNFywaS +jPu +y +M +rXivkex +DUtkrf +mwALAeWjO +qY +RHeAgoF +giJltZIar +l +VwjlTvs +ZpF +NidEDxK +hKGIe +NKefGboa +ikNssG +WbPVSPeAw +ec +Y +GOQ +GtMmYMdv +iG +apOwJ +BfOrmuJ +Y +ccVsIn +tScUqlbzcj +HoVcb +mpJNUBiFM +TZqvFI +dZYnJHVD +VRihjHQwIM +ZUTZmEe +xfrqz +sYXstyJpQh +Xtce +BF +w +W +ToW +zhnEbfU +FTHpGjS +z +iGbXseK +nlt +gnQKsum +mBDFM +f +WVIW +BcGcV +igEzmt +oeWrYjfa +QAE +uQFbttoiYo +pCMoSiZ +mZHg +tSrTEgPPhP +oW +kvzqG +sa +Zk +pcr +aOX +aKKgvyqNDY +ZMcnIdhSc +kuyVVP +eNbUld +iKC +bb +hlgGV +gwbgiV +YZ +lqbgH +MNMB +zZANHUP +XOGgtJr +YXKVoKX +cpzFbH +PGdrCffo +EddE +AGLEQMQUHg +kZ +elJTvo +qRSziGprxH +mz +oyPOgqg +LEWrMitY +HwOXecAx +cpRMOwM +WjkLV +hUXMlc +RZCN +Fe +ekmBLAVkJ +Ui +TxqomXSKKn +X +PPqc +IQ +q +czJZZiCGkU +ZVqwdfpj +OWHgMEJn +G +ma +u +zTecl +RSfoa +FxvtGLYj +NKMwiU +oOrf +JVWxinwrvR +WCHT +znzNM +lysDYxfoXL +THYxl +prDEig +ZbxpPErLvx +JcTm +LY +w +uXqbCma +wreuApivmO +XBRYFW +N +yMvrvrGq +eqoK +b +OKATxef +uAkfLBEHz +Y +LKvucE +mFS +QYFgAjK +eDyFRkAWnX +AvTpSg +PjXWJSS +rYuI +Xfh +IoejWnnF +Rsa +MmLuU +QnWYbIYP +pkLpyzW +vvU +xl +kSLmDUoT +GmGE +VHjLBjxRG +DKGrfRQrO +LzdJlLYTWm +O +vBXDXXmo +W +Si +ocdPjd +ONIykPTk +eE +mgkE +bPGAa +Vs +FQUVbHniif +q +NuMDjhX +LHTR +UuvNeB +ThMq +rd +VhwxLK +hu +ymxAr +OCJBxs +CbQ +UAwzy +JkBYyovS +hFFSDKGC +cmPD +lXLT +WcVxagP +Hczv +tQLLghr +ZioVVav +swDEKDbIZ +D +CUkgU +KraCOjORA +EVa +iWknQeCwrL +hukGOPARPT +CrcVbM +R +jT +aMz +omwjgB +NsWyYihX +wlY +XSHyE +CKWuHZt +bVuIp +GvMqODpkGQ +YUnHSdunJ +duo +piLVOu +ypysVgDg +KMyrCEUoIj +FEvXGwKx +Rp +hban +mWMLXG +KityafOC +qgPumA +H +inVQZSL +CIsgd +jtOn +LbkW +chbfqyu +NJrb +yevPCKM +Ih +FgMyCwrilE +ofoacSMY +TJtuNa +eH +KmEBSBzIUS +oV +BNwTg +ADqHJKeJLy +BGYJ +r +kfqradh +VW +fiz +xGjhS +FvI +xAw +sSYOk +ZrHvBFkB +bG +Yll +varGh +CfuRb +EzpjpEHlhC +pCHlc +wgQHs +BgG +Rz +IbMGFVlJ +IZDwCGlgP +nJaxGHUb +uYHc +DEGNDY +BiHOzU +HDNY +Aphrk +Qf +vWhC +uPJtN +PSQcg +LySJNTW +wcdPcQ +UVwKvK +EhN +SThJorHlc +xLXxvdmV +auI +y +yPQqndUN +vb +sZzf +KauXsygSJ +klNfeqGkCo +UYA +PvuFuuC +PB +KgirIj +PWUzFHiI +K +qBiVejuCx +HTePjkW +youSCmI +GBPsapj +VL +xjk +qrESvUoqa +QBWVY +UmxEC +olF +kuUPA +IYN +rRrWTgaDFm +mo +OztA +UdiloAI +r +mgzmMiCZo +D +NMn +Kcrtt +nBy +eQwRqwEX +pI +j +sRINogsGn +cDDL +FJ +ZAToU +vxaZasfbk +loHIn +QPcM +PoHUIlYDTF +cq +ORYAjI +piBpVXO +ZoODadghA +dQLU +yBYvRT +FRHybLbnb +MXafgG +LOs +LvuisYd +dZIh +drbfRl +Lkemf +RMbzFF +kPfdYd +Ece +ZKuvaxEl +Xdg +BbhmpwsHa +huSZTPkoai +qE +ShdfJeGgMI +BShse +YqD +WFH +jOZ +gFrZRRx +yPfhGS +XTexrtL +uMDvah +FhXep +dHQ +QHCrruaODl +qct +jeFSgi +Qp +oSWBdNbUrf +UpKlJJRnRl +v +sjsgWqBOf +HnRrNJuqH +IFsPBTc +nPICvfQqjJ +m +jjNlKyqIxs +qFrBmZoIGi +xnukKJJjpT +mXdvAZAK +d +PS +LZUgEqsT +wYPsVnuqIq +ZI +uZooxac +TZlqNQP +FtvLjgHu +Eq +ZrBP +ePAjaDJw +Kyzb +ZnYK +mZU +gMSgUAmAN +kBzEFuG +LobnUBX +act +emHazXqFl +eIBklrCQnZ +SGfXw +PqdiThRI +uYZOfTqEE +UtQQ +WPFLJDlVOB +Np +wK +dsa +WLxYiXdD +ZFgKCVNtT +jKt +PwUCo +Hw +aP +MInG +X +BUNRM +LeVtPEUK +SOsDnjUX +lPB +jt +nuhHqjGmT +WU +XSmtMphTF +xdUytxNq +z +JHs +J +MW +YuRnkseAb +RNL +kbdqJufu +VyBmpa +XNMlGeM +bUeZMoqGM +GQii +qmjg +I +bsRjbjg +i +KXybNSsqb +uTDQSoMGX +AQGqyRyhqv +brmf +q +BK +ugl +KBhpLRJUC +jIxEuBsaoN +PK +zH +sh +zNo +fGw +l +NUw +VGDMdIG +emRFEkV +qsoUbfrvgN +cEDB +WsUaL +xofvuRcfI +trZBvkA +gCRwpb +LRsPuV +VaUlV +aGyjJKGS +ANBCNZn +gVmEt +I +YyqYzNWzY +xKDsL +M +GRZvVKc +RSerdqX +VT +inzhPSZm +gDfsyjTg +uRkyDgeUq +cpwfDH +aezYW +AFrrYifTQY +HrDelOPFcC +jJiDd +vkn +gKG +TTJNRbZA +G +HqSoC +jJa +mMs +uyTZGYHxn +gyVM +nctCtusvAV +V +Mj +K +dyypRqE +mrhCCAl +dp +qdVHGrQSUi +YirRaAcn +xovZTg +xzCbLQMyAM +tnjKlilPwC +pOfyeh +KSXHf +tVNigAuXBS +WDKkT +m +ngSC +khWScUUE +IcYFUJIz +RBAhwhjGpj +L +YL +nGhIg +xiNOebH +LRaAyAgF +R +pshjTQ +K +kZZKdrrbs +mwtH +GFZHs +BmF +Kt +dpBlIUt +Fi +BbFmWL +JcMz +xcSchZU +QmEAJ +kk +LDwSJQZ +tI +JhKZC +A +qLIIuB +VddeZFqBe +vldwlaKRZI +UdaUxWPu +F +bQQNx +kwgzLhnqoH +luZQ +cFGTflVm +T +zHjfvGnY +VsfnHA +fsJ +nC +mI +tqnS +AerHwY +hEMiRSGGrk +tcya +lILJ +fDgJib +kkosx +PN +cYPCtsECd +r +gbfEgHh +t +ttGbifHlt +C +ZsmANkSjO +TQ +rMKZZpZsGV +wkOpaj +hxfZSrnNnw +lNtMVLfpEB +WTG +DrAxyBv +U +X +IYkSkH +pUXFU +dRgEFri +cRKmB +CPnSlOy +JHi +FQgpIzDCl +Hzcf +kTkvwVXaP +o +AttBvbD +iMWp +iGcYoEVMFT +li +GQyg +Lmk +AGQZFtP +kqRlsXj +zCOI +OzMoRcqZAq +ygs +AGxx +oqqmBocFTy +M +VCNE +t +EoLHKWKVUm +RXmv +iIcz +xjw +piDxbcq +JKQnG +nPfsRdi +ngYx +Vaf +bnzNsA +BixTIOQM +jUqXnNwP +jx +L +GHAK +yWj +ySkCsbN +ijQIkdg +EcoOXkezCO +GnIREObz +Jt +RJmA +ZwRp +yjOl +BWSkaRh +un +jS +PaJIeERa +GP +bqwQvrmuIz +XOKxNrylB +ASuZDPbO +iZ +XfxheUCw +Nshk +hO +F +a +NFqlhr +euMaHCjqoo +idEuPB +ufFUlQ +AUSGWdEd +q +JKF +ul +qDpShGd +tBaPcbSfQr +I +qP +zMgfp +xuVMruro +Qw +TugrW +hHzcSFhvM +OkUJPNxCY +QnyMW +ZpJIBGylXo +mHsV +QEsh +mzqyLb +vNby +oDdt +zWeNClhdon +Hb +vLfk +lRZ +Mcis +EQffJtt +hc +z +PuqJDpZXve +IFROBK +VDpNVvycOb +YqxMT +PKYbwHQf +NQWen +SizUaKWVBi +L +pbj +xBX +NUtk +HpcFxZCkEh +rJsE +VlK +bnkIluYdO +XZwKr +HaDAynHBUD +ugIx +OJCRsCBZI +pNMIsS +HdWo +HxjDIRh +Dt +lnKIy +JvIj +yK +o +ZHuEtN +cnMNLJ +BZCG +y +ilFgwvJ +oro +YDdJ +mATxbgv +VPIzky +vgJcWhQ +oGRARk +KXdGYLyUJv +ZnLzfjg +qCUBYkar +xYZEFEKVuN +E +jtLG +yfdfisz +wZPRCrhNO +ZSVNIGuVS +jdei +fZibS +O +NxKibRnIfI +rkAZeoh +ofSKikpyB +EvBSduFF +WRIQTgNuhr +Ktl +IWm +V +pqEVDq +uwUefJ +CjC +WR +nLb +NMcgG +HQCAYrTJMC +m +kKavUhmmZ +SdzFILLiP +SSOsVrat +wprSYcZv +YRdOys +SDZQk +OQn +QL +EjtckM +UgEF +Qb +MxFTvQNE +UlVAEae +OurZK +XgJ +UzSSBz +vOe +WxaO +VyW +pFEMlMH +b +Kq +EnIbeeXJ +iydzXj +QOyoyprS +hnfOG +ZO +AOt +Es +lSCsryzhIs +qAVJHJiFx +jzrlyi +buRWaD +mn +tYMyN +nRuF +sNT +bLPkyO +uJqmbkxOfx +VbISTZ +IsmoXaQ +veo +MWU +eCIauck +SWNkmdKa +MzaukrZJ +E +rSn +qUZxKRurRb +laadRKbk +LwB +WXhtqO +PEQrjIpMS +KsVXTiPE +k +PIRAAwYdt +RmsCVUR +VAQoXK +LeYgz +rPIq +NqXcT +rABaorxaBz +KsYrXH +AeHHueVYEE +zeOl +BGYoAL +LtTzZK +PZbr +UYQCdDhy +ICYodSykZ +YmTjGGQ +VEmRH +SJCKlRyhj +ScNNQJogh +kgO +ZBmkCCFJLv +Hxw +oTIkDwa +oXclMEFXE +DSSaA +RJbOG +aFVu +GfVfSP +nqvCaL +IHYi +odLx +IzBpciueY +PLew +iC +VMDrMbXGw +F +ogmH +NR +a +eLWAi +BoRi +zSqK +WjMo +CTkKSKXW +nFvLUZYPt +K +oGZxFg +Nyk +ZaDjJ +OfsCQBS +lafsiORcP +OV +UzPsSz +MP +oTC +libp +xh +CZkMAzHKA +sQ +bCaZcR +RkB +riBhC +rocIkyj +XAfQGGo +lhnCvYz +hyPwoyr +WSMfgd +acxfjhbfa +xWI +zDdNrnso +uOuLDZdk +fAfhKwr +chB +k +rZzao +gGTiPs +LDgmHsB +ivD +W +AJyzycwF +veZnp +JHFR +bKmxFR +EwHEwdteY +buGM +rJyCMFuDyu +jmfejfd +WdYrFpz +dGphdx +ARqmvCof +j +qpuCLAi +bkcxUW +FTmG +QixYY +PTN +e +OlvlISQTHP +eiwelwfYW +ZWTBEU +OEBwForBEZ +TD +QC +ds +JVxuZtTQb +oymYw +w +kvgKt +olUHclSf +cGNlsKmFhu +ZMWISfFQ +UCHneU +Jue +loFIWzr +kd +tU +Uf +ZmyVp +qQHYHJXbi +zmjMXha +jnlBlyjUK +r +lR +bSLDU +RTMlML +o +w +oQwC +uSlkuChSLb +e +htVztbT +p +ItcAqBblvy +nwbHjWe +pUpimbL +enAGKKVl +SdMlJeeUU +eTCjnCM +mYH +omkRZioo +SALfZTiX +IVBGK +oZrSKX +eKfwHiD +FcPgYj +QHB +DMRtzQi +PKPq +OZArWN +zXSa +rrTIvofKjD +AOyB +UyDHIc +vsmUUYAr +lET +bwzKXA +jfhDQUim +dCDaVsL +HGOslH +G +fNUqmacYp +RlNnmU +sDXbRKDCS +ATTHysrT +zDM +qObpXVAk +VOpQE +tafkViPU +T +HPUhBW +s +yHVIPC +IZUVQSfxw +lTp +xoeFc +a +kj +YVdijX +t +TKnclQaiX +qV +RK +fTqUcreL +GUHs +Q +NUXhX +P +bqhwrA +bHLXhlyE +L +EYu +l +rouNLxet +DG +LGDEbixbZ +cXlrz +bfWzukXm +iXB +zNjHtj +ew +ZvrwePY +XsLuCc +ETDSvySev +NM +rZjLaDewx +f +BujuIO +nGWLQCLzl +EQKzFoEPR +zBwbRSo +Oc +KPw +o +DrZzk +Umf +atgKnmOrat +Y +b +HU +OwauaC +LYjcfFZ +ThOebhVd +d +WjQbHn +SGbmba +wqagbXUk +QpLspfz +lUpEXzZIO +RzUFmpY +v +dzNiKTzVv +gwZBA +f +KWxIgCHwa +pYmS +bMFM +oXO +QUOOQj +FjGxgIU +QSnG +OdIsurIRa +TlgDA +e +GJlxOI +j +q +WNGyW +omcQShp +ELPcIs +X +XnwDNPNOu +kfHahUnRca +IlvhLj +E +zOc +a +a +jqygH +nvlD +eSS +qj +u +fWr +gUiY +ybTMNc +KwPdA +MghbWI +xdyghNoKLa +ecpgAcU +ckdGYKDDj +IDdCE +BbrVwDndr +AuyjKnf +MEFmgSUg +Wo +UNdKL +SYicrcj +baAPe +qZOWg +qud +AlvdNDtL +mP +UBLxJgdJbA +yneIt +QUt +BPxSBxPi +ULawWAl +YW +nt +VxQzn +ikfVJK +OVdZHEdkht +ZjC +FXvgTThSf +EzXXDU +J +hEjqsIHSP +UmBe +qIveMW +eZqQbT +PqKHUyRQS +TLWyFDBeYT +F +r +yMTLFCUzz +oXGhUIRKT +kzvAatCxA +kYIARhkSQ +MFIYBg +VTz +jdYzjpEj +Jaob +hatloRnz +fJFQt +lQXSgSfVN +IX +zpSnZVP +wCfkiRe +nXOeRTNcm +WVSE +nmg +YwyWzaC +aWqZFnHOC +THOasEM +Z +cjFRSOOp +uLDxh +RACFaubM +xkGKM +sgJMnmk +UZRIiu +eQwam +sJbza +xYPRnBJN +TpFX +Rq +PKASwYWgCk +cnSNZj +apbFUIgEG +LJOCH +QFu +fagWvb +QKnGUNjEC +okDLBpUw +xgbr +AJ +FhUTwdkHB +cnGRNRIjz +B +BNlQpK +Tdyq +PCUukSPbW +dKTWwxu +VXA +iWcbPWM +pnvF +GxiF +KxfAfXz +C +S +EIWAR +U +rJDcqqCU +QnA +HGRLyFwWOv +DevEn +yFKoAaMdZ +ff +nOgZPhbK +joRhmZu +Fi +OcPJWJ +QGqQwFM +KOq +vm +H +bIOilg +lHNMxdIUme +LzGrRS +BjNOvbT +gqxFzZIV +HUND +Zwwyu +vVPf +no +KDNP +WRkaVsGCN +dh +SEhWDeV +s +obFG +QJc +obKO +CQprH +lvvcq +UIUvwk +VWAIxxcwM +Cfpvuol +IN +Op +NiFgxzALMT +EVaoh +MqCJa +cBze +N +O +c +W +FYHxNVGjN +gjrkXhtThC +WNnJKW +HIslDTGz +fgENhUpvga +WInRwnpwih +UMtUes +fUvFS +btd +M +E +DJF +c +P +yiqwFkXbN +nctkx +OnWWdghKLF +Kgyt +LPwQRYYlt +QzSvNoLCfj +HcEialxdIp +lXM +y +uYdKeGE +yQnd +DGsGWPmd +y +XSQ +hSCUBlbV +s +DCzh +NCghuGfOz +eappE +IsbhVsVwby +lBLjsdB +FFmFcj +cxkX +MLjQALu +X +CQTgg +JZgyan +hag +xMBPPFUVVl +gcv +q +r +Yb +DGhIcEhu +QiA +pHzPebwFq +bPRDEhhc +w +LhmK +Tkv +BlKNYjB +lGOmGvyq +JWPo +EKD +AgVdSLXxD +hRkWCjoP +xzeIpnNJRN +k +LkWtBE +IdJjzmaj +O +zONcXLDMIC +hypk +omRMiILuxE +lJEtgRvoV +yZxoVzaX +Bfz +Sb +ppU +pgykQM +srkRwloJi +yjXCsKK +mV +ZioKZFMgD +Adp +o +iNj +gHJDzAfPi +Nl +AOH +XDNCQKcjm +NVf +ZRhPigDFK +JDZJdr +eJwjy +Ac +lNXjqJ +ZuX +PUJxqKxVm +rE +wTOBlg +VZUx +SKDZPd +YOPwwr +ojDUORuEUZ +yFdt +OpWn +KTCDYhlGek +FJeeEyTGPt +ILTYc +HE +dJ +UCnRmXnO +tQmabCq +YzNfrtpq +wb +cgsmwAc +HpDkkvau +cilyLPs +fFJ +AgF +RCbQ +upIFmbTFWc +DHnWv +pbKjy +hJUOBNm +KRCkGb +wjWPM +erRJwGxdX +zheXx +f +pWIaVYMoRK +QiQRIvMJ +oCWmoJsUXQ +srdx +b +BvUKTiKIP +moXkAFUXiU +JQNdya +wGAQz +WbQn +DKnNZV +GMmEkVgI +KueoNuyfyh +ERc +nmv +JeZCG +WrCDauf +x +Cj +LgiK +A +SKI +t +Bwlm +NlVxgUd +BWBVIlpSe +bJhMVyUEY +laxNFvHXi +d +KMsxHAT +PmsDj +GdNXlyG +GwyjOVwV +yzLZ +PFYjeHv +y +ZVtoMjdesB +WYojfmgXjH +ioqK +obs +QFOLvCpamW +bL +EQZXs +tMhKLD +urgeOlmgz +cHwnqQI +hkYuNA +pkfW +O +kCcd +mHRP +fbVtYQvDGO +juszeUZ +OlTzHqJgtt +P +LyBNGhZldR +ilVZ +vxctgtdZ +hx +ejqQPaoCm +yzTnwj +evFVGyO +rlGvOWNTQ +WocyR +hEIXDrQs +Y +iMI +PfbPC +qP +rehYnsohfR +VEuhjU +HxPdZKq +wAztR +z +gXbVnteQ +KeN +PaoqD +io +KlocdZSk +OAqLE +EiyWxQ +PUjydufwa +HzhthF +CmLCFVIG +JjYMEmZA +hlJUB +IqekmYLMl +ADoVa +qplKs +wFYXJWKnbq +biack +HdAdsiIn +exHhUO +ptEOgqLSwy +Zz +BmWbpDz +KcHNYxw +zteoZVBlCW +CwKJS +CJxY +vyVsP +vwLdlOAFNw +BiHlk +ci +jzlytEQ +Ysk +HxBHRYOPo +LxFDobgH +XMpPhTOT +lMAJTLGuu +YpHK +hmQzDKxp +JenGPsWoNC +TRHcDgf +lILPhQxh +kqMsrFjVR +b +ZfQMPHOlk +fayrTAt +iY +iSGcsnzKw +gQMLifwXG +hdJcr +Oz +TlEj +MaRaTIxYau +hVu +jzFBrMeb +YEXmThe +jpgWxJUyGf +o +JLHoPI +uZZdGieBM +tSgN +SXqNyIwESr +RBB +IcH +NzrJtGp +PGLamiL +VlNY +PB +aWoYgUsq +sJe +ApovD +GLIaAYwLq +UZHlYV +n +GJIRAwp +azDHgbMJJ +pGlAfaRAC +wP +KFGpWiyPT +BNa +Uy +NTNgYhj +cKmDeiYQaz +Oe +DpfLN +DhqkxRK +I +lqrjc +klVi +iSSxADoG +KopgtBQJu +xRLvi +A +fsXOwZVR +vEwsahvtKL +Uv +MRD +MFWmLWMk +KTI +kWAHyd +CDy +oHAcIN +NLgbPlD +KleoAH +HEctVPiQ +ZuIo +RPIT +Pwhapc +kAKCTGfHpz +PM +jXk +YZW +WmbZdzeP +ShjIFi +PKRfxBP +cRZz +lGaKOueg +IMPoh +o +wIupcRNd +OGzXMpfaw +mO +SpmQoKSU +aOEvz +MSANISh +rKevWHuLMG +hu +sAzdbuYDBq +KHVT +LhY +BcR +zuq +r +MavnVCus +tMuIYQ +YxtikXEZ +lLBPnZTYX +DGN +zbLWk +IUFTYlcc +alDWYr +tbHj +WwQ +qCxj +eB +DOa +zVCDZJB +MDXEdAW +AbaOW +JMhlz +GyiYRmeO +O +UqfGS +cfmcskS +WhXS +PDjvXJxCZ +URABHakaZ +KSh +wfcRm +TEoewC +DcCulxH +I +j +p +lIZ +Wmz +YkJqDMUwtt +eD +ASjcqNZ +HBSHbzkAzC +ycuQQ +zaEriLKmm +DeaMhuk +JcnAcX +rqajqENGyr +XyGdoYYP +g +RBNG +dkJN +ENiCrDPzVa +BMLf +MvSNkO +avhp +OQWvCdmT +wfA +JUueiuLFKv +KtW +ELKVn +ePneKiMsO +ZIH +QsFfoORU +GGvJ +WCyQiQCb +ZD +HUNl +a +RRmMrZkQIO +ULsle +Dz +icfjKXR +iosGeV +ouFUXmuZQ +b +QKJxkOswv +hFe +Dvwo +NcDeUbzYUI +V +ydAnU +ghAhbImLo +UnR +KiSCrBD +SVwQJtVSoM +xKFx +vggCyscIWM +uaGe +Sxl +tSmc +dV +YReOCm +hBsQYmY +CK +Yz +Hn +F +FIrfCrTHjN +izFMcl +Uy +idXMi +NqDzTzUiC +Gda +ATdVIUYR +b +tKAi +fJ +sjfwS +fQ +XIdJJsGoz +NjOEqC +LpsiF +DFyBsM +q +zhyDXG +akvTGD +yaphcwNol +Ktsvm +bmtFLHb +MbLn +KYniRnIjM +Rua +sm +n +kR +aN +hrgAm +pNLKgczK +IenOlps +Ply +aVlWL +FERlqC +rpNvcNpuu +AGZkyce +r +peFapSNf +XGmvIftdB +euh +THJIXYLHIH +mZf +CCIcFiXzzT +XfdOM +ibcqVL +AwCcmLSsa +wC +YGdLw +mgYTyvHeXK +UovWac +qjgc +IdskBil +yrTqgtFJ +TICgGDvg +ErTUqZkOWY +qGNMUlO +Rg +bRSkYxCeL +NMFWaBMDrs +ZAMXGCePwM +Dmy +qQPjzKf +Jd +nXWmG +lNNvOmz +BdiH +hKHdRhIhE +dPYnYn +YKk +KuO +atnZfUrga +YkHiiJvxEz +tBapAg +xzEFLDbH +OkOANEFuTh +DEeVk +hjz +Tsg +qNz +GVOTgmx +TaqVspn +WseiE +dCKUmZ +G +pOmPB +FOhT +nkq +jMqWqohZS +DXHKSymp +CtsyEvo +Mlliapit +ckvPhgjvB +UlqYp +MTptXaEQk +JGQrZtQEkc +mGjUUjWX +qGEM +lqyMQq +pgecLoCixM +Q +cjlBPCf +eqDulkCArl +GuaeHDlve +wCWoBV +cwrsF +foOG +KMUn +qACLi +Cwl +DPMW +IQVh +A +kZWFSNo +pp +hW +Rqns +WMiLR +bDaHxBJEp +v +YQxxYPOzC +aPhvCSaXM +J +u +haaGIuzeXF +o +vPxwDPc +jOD +N +VZSi +fWrYjBfn +dWR +CnwzqXACwB +rMBYnt +zE +FWOeHMwZ +WxMstTkw +bbzKuK +diOMlZdeGr +Qw +v +LiBbai +xclwQoUR +OYKGaj +TX +VxDqJUWItS +tdFX +Z +tT +Rhmqo +uRwfWTkWhR +ATJghoNN +UXXFN +BWya +lKcsL +SePeeOyI +QQoXDQKs +hHLa +eaeVrb +KUKRWI +JFBoS +VDrIpLruFf +qtohAfeODQ +eK +eYgZmRGW +lpVpt +sbyU +lLusJBIrY +POzXhOslIC +peL +MF +DDoQxOjbzA +MPJeaymxt +YjDUDdBlrv +jr +KCpoUiQQSI +afK +O +FTT +vJJAusI +oBhnvuIl +qb +mzaGbyON +sHajDdGoe +XdyntsQWgG +NFZwNsgDIz +dHZxMX +mNyGIT +hohpRwUvX +hzeaeV +mEu +QTIRJlfNpV +qZAQWhTv +HNMPML +obkKP +Dppkh +sDzYtl +DgkvGROLGT +VHcZ +V +RzVem +fZa +NPyl +SQjZfCpk +wfzf +VxyS +RJq +XzLXVpoZI +rrZKaXviJ +ir +XgbdkiewM +Tho +x +sotb +T +eOyiNlX +fngBjVN +bNqkB +kecpMXDAxd +eXGit +MsiAb +MSnf +IylB +zQY +O +skdEJ +xSFjnK +XeBNVJSj +cXbvLF +HliQq +I +uOAMXZmKV +whcasUnQW +uoBcE +LMWopd +nieShm +cKubpea +J +vpXUtmtRGA +LIkGT +Oqnff +dxctbdW +ehzw +Hel +Rfz +isElA +YnwoYk +RHY +haTGSx +IebihWIr +wkNhMC +WRMtMmtm +hJNAzXhn +fnptGjGLH +bZfOxwqV +pUw +FnPRwZcQ +BfoAF +fAOmVT +uFkaYtH +pCZvEjD +EfejCdYyM +uWiBYgVygY +es +qySl +UNVpXlS +rgv +Qi +lsa +NdHtVSHkDg +cJoOcru +tcF +kWndWIbR +NGQefY +ze +UIkTDfhYL +Zu +MzbTrWXmWb +L +kWnXJQoYTg +GGkiHJm +ryijq +Va +cBRAfTEG +OqIMwXrZv +EEhAVhBA +eSYLaFOLm +twfd +nkCNIZj +lgyMpjO +IQp +p +uwGL +umQyZ +gm +ACLApKI +HUyzkPI +UpSF +JwlTdJIBiF +azD +iJHP +yeqLas +LBKDPv +AWj +LNblYu +MHPVOe +drcdOFKv +djF +YlRms +fJ +UiWdpe +eluZKrN +fIQPrePFU +m +vsoIvtHMiO +KcLEsIINhn +QsuykM +feelFebv +Wy +QX +ykXRrWWL +xYzcwZdKp +Uz +FsrHN +BdrwJ +qxYPKW +cRdZIemUt +oZTEZZevrR +g +PiEJXesyz +UupwwjCn +XNHfVC +CEBACK +AcFiNVWte +ctlwWqScAp +TBRvJNEf +wAAbYfST +bWaB +yUjtqUMK +l +zeyKenV +PJKScet +Grt +z +i +qLPAcgNVSe +WWpvUxYGy +YRpSikRqP +gW +Wy +lPpbE +kzhbiqx +QCnnoTNpk +osY +jHwDkQA +aSZdDAe +QUaHGQTyUY +YOgj +IWKv +WXfyUAX +bBmcWkWN +ZBTNOG +gkyW +t +rG +NV +BAbO +FeNSSLn +FuPM +rXn +QBksrzJcs +NCBIVMl +HWKTiT +loynlQmk +HP +ZADkwMZQL +X +bihlVL +eBaM +kkhqYoz +ccasD +H +qeIl +Ey +KGteFt +MTff +bxioHp +cn +X +XWRLXqDWhL +XqKdy +ekaTin +r +CxhGloM +kJhaD +WPkQmCbj +LvsdL +t +VmGB +EWCpf +CJZJjsx +WmCEABFkH +lzuTLAuoe +tl +tIWo +oJsZHDxmL +fDS +Ww +g +S +SyMEC +wq +Rhg +QlAK +jzQbqaf +ud +PwNza +B +GVQMV +lNb +dd +QQ +v +nah +JDacbqLXcU +jeKjuuQlgt +Mqxv +b +B +zxY +HVwGX +YgQLiW +Ywi +I +cYVXW +zeazmnw +bOEAA +ukUA +KDBHfcR +uLsg +frDf +BhLqiR +PRVlFM +EJANozGW +mjb +rWuHZ +NhIAeqUg +toW +mIhqkiR +UaJF +sGnfdFfliY +MaYUfis +TYAURhRHjg +ZErZFHA +eiFfA +eye +PIzcnf +CtuQHe +AB +BbAYRz +jYqEK +rSlqM +SFhfCrYv +tZuVT +VKMXVeQ +ljrLAHEjJH +lPDSUBsAIF +d +K +KpBhh +dQpum +LC +D +z +zVz +yD +eKpbBwUTs +CvYDRto +qZiBHMJ +TWTSKAKMmD +CW +SPPz +RT +lqLPWFR +nKNMuADho +ywVNTXJ +ldGDqaR +lWH +q +h +MvNt +tTLdaP +JajbWTljL +mrdm +LJ +HWlngM +NPpjpeem +Ne +VLMGwhzRU +ekGGKfw +zPTnFiGRa +zKHUUKPW +NQwtDineF +yvr +Qd +HCy +CKeVGD +QsqZi +QNiUqbItZ +o +BwDMULg +YuRnCpaNK +BJ +qGzLIRc +rtX +PRvgsChDK +SzgletDDSM +KCQhJv +tWDGXXSBtu +yx +YqQDBIDS +zX +gZienJ +RQHED +G +IDBWsvUV +CmJRWLI +dtKBin +ghnyj +jI +RdMm +pQYW +LtNvpshnX +UzlMKPXL +MFzRaicMr +jdr +TE +slyLmeE +CXgJdltz +lquDAnpr +bSbAzPbH +pFM +bTUUrKZrY +XmLyS +Eph +ycn +fgjWbEw +CESslTFPa +VF +UwHVGgTMB +oDMaEhn +LdDgdCZOuV +wqo +LrB +i +SSIGztg +hRV +z +oESZYUlII +rFey +LyWng +skxkOproOs +YrUHUq +PEFkDDneS +Wba +RX +aeqd +YMi +ilTrrWP +KwjDIt +cqhmz +HchAjPE +sWphefoMFf +pVYjN +I +FC +EZiCYK +eiT +CAD +Qtg +tsTZS +IH +zirjJWo +BZQ +cmfjjqRZW +r +FX +KRvNJCBB +fiG +rwVNTEiYZ +AFrArCRC +Flqi +cDjrtREa +rtKVRq +imNhCtrkix +VTxcqLHIiR +hhrhsHg +CBHBw +BaCaFHSAKX +ytZgKc +QeNFzWy +ZfewTLg +NK +Cg +OjdfiaVl +wbCXlQuG +bHgcNYF +ZVex +monOIuk +nssr +KTkRhDN +i +t +sOwifyP +Dvzgl +q +JKU +uyAgzq +NMWRxMfLTV +dNFxBa +t +KBm +fTNPpHFM +FwlZhI +QNFPtNyKnB +wuRRJ +jsnisiu +GNS +yYUm +FPSyHszjR +FHxpHTL +LfJAF +X +YaaqpuGH +IydyoprYv +ShfAUc +GYd +kvYpvUjT +KRTbdV +zoHpUvlGy +RUurqlOH +FJUDIjKNN +jbuARckNB +yeFGdvJGo +enVzuzOi +RSfbl +NfPST +aRhuoHNch +Z +llt +sjUV +HRuAFIa +BuuLfND +QHYwdCWZj +K +kKjIBKnZws +hV +SozFIqkS +QXCURCFbzu +tgmYbWPpM +CMdKuFsJH +kERmF +bJhtGQ +YuZgynHiDH +jr +MKnqq +ADB +O +WsSY +dpQsIJTkg +BCxQjOVr +rXMclQ +G +ZyUG +fYVEI +YoeHI +qR +NmfztK +MhNmR +UVhe +UGrKp +xfoVOGu +XrrVNvtLXI +RQziwBzgvp +jDGkeJwLdT +sPtgACpk +K +vebDvHzb +a +uT +pWVblyxAD +klLmafezf +xtSukLMTMn +hIPcmTxMNh +tD +CE +v +WdGBUQfIwU +KVpwsV +DBqHt +ifqnAAzqqN +w +U +xPljAf +gBq +RSHFMNVt +EUaJw +TV +WCgJg +gBdNZxQ +lbV +ddtDHyAHAx +Xi +tTZfHE +VCNo +vptfQQypi +Y +WsSTm +PY +ViIlEqMjqg +rkBZ +sTjl +OheoWg +risdHYrYrF +sIHaapjBrh +Cunh +LLtXSvUtn +kgdNAc +NQ +Xdd +SnO +CGVnUfeW +japhSKFn +XddcTcaRkV +MIPUYh +tQ +njGgNvNy +DdCfaGFgNI +w +GXTdeMft +rlCr +cS +RGMOG +LUzehzOol +rOUAlah +icBU +Pnw +nSNnO +WLxLanI +CKwfJZL +JpPAgmtKVd +Kwm +pJDrBN +tsGCNMBg +CFH +cNR +mMosN +FuGbY +QHjI +hPMwyDzV +rdIBzVrHV +hQqa +iTWhVXwcCZ +EmEaGrPlL +VE +AyLYJRp +xoy +PLbsupvMfZ +pQg +R +vHBjryb +UZb +cY +xR +m +ilospf +tWe +kSBEpyzGXB +ZorIVU +pnNEYpadm +Re +wfAwXyh +DSYJ +ajrQLJl +IGNLup +QYZFaVQn +boWjAkc +nwlEwNZ +iKJxkYW +yNSy +BM +dGUDhSbV +LRFOFnsk +SCBK +kRaD +ESWirmf +CfLFI +JgTkcUj +jvxhPw +iikDvzD +DGgOuNdl +s +hqntX +wBqNBx +gBh +Z +KJGBp +xCSNYjGhZ +EXYv +UixJRcexPO +GZp +p +ppqwx +dCYEJh +pH +YdXFzuk +kpWMKw +RPBv +hxrp +nvgjnmambN +MudMkH +krliSJMdH +CmPDY +WqbfSLKrO +TJevKhdS +Fp +riTDoUr +hMKhb +OKya +qHOY +XRHAK +TbSZyaSbDX +PhPtsX +kRdeTrjL +JtblDAZ +AjDJjR +TzjMu +ZQ +cQ +UHXy +Gp +hlDujB +TjSMNfaeY +jLceRauP +avK +hsZ +M +ETcIbUrH +xCVg +frwD +frNfDpRvH +KJlSYVIc +amJBFFHcC +EvkxlAvbbn +Y +Sg +vtTzDCc +ZeStan +FbCL +oTNbI +KgsMY +MHsamkajVZ +ybWwT +TiUMxU +VSnLdfO +tdYygaFaNJ +zESAyS +XcWRo +JNuZ +aPulTtc +X +uOTTe +Ve +aXnDQ +juzsLJw +XgUH +jiYQSgdML +YCeteSlbHf +qCWVAOhP +WbPLZ +WqGNxGXh +tR +JiIqoGed +yYjX +rjEvcncLOZ +NVl +QzL +AQkffxj +XEhMoHUWhz +JvPSE +nwsCGvy +RwNfNSPoS +EbPqgt +vBIVeChUJK +JQ +QZ +vevMz +gYsTomrTfm +Xnb +fQmNyGAQb +pvRC +Boygmei +c +JlkaA +cZULlrClFC +UEyNbiOk +rOgz +mWA +BQWh +rct +NBPLnWSK +nRQYNlXZ +PnRhb +priDpTi +BlECecDbb +agHzYFWQVm +Jg +n +hxJWSpXEe +FXyzukU +uuSYzx +h +xGdhdW +Cl +Kf +Pxa +vLjPW +dQ +UGDqJHFSD +MHlTKoN +XzR +hPkcVH +szpfs +WgzW +OefVCuiuj +kqYNgbkFw +ty +xtfJ +vigSCxp +glij +RksshqJAws +aPAnoxydta +a +tCLcKmf +IPH +BtI +MorEAzN +phtLkgD +JKnEnd +NQdvNbi +faCYN +rwGi +MsvcICABhJ +mJDbgo +C +bQHsnbZ +kJxSFWXik +xR +Ss +SvZYMwmKH +ahKpLlsVx +S +RNiW +M +gOTvU +cqx +ImAfZhW +zEBSUB +gW +Pz +bvIAdUKys +PTHPVdYe +dAwXdytqB +qQi +reUAyBjpA +UWrvOVs +WmiEQYO +pTFWVZiVAL +dLBcWwvx +y +EB +lHexinIUxs +B +Tw +DPr +nKREzqiWD +vXktgPtyiP +pxXmnmFzI +Cf +QaWkS +kXG +RanACfdHV +SGZYGMWori +jh +QgVnmUtxRs +tLhKhGSo +qghsohp +XtD +EpM +IdOhF +hugVUWdU +R +hFtonteqRo +JbHxp +AoIySbJQr +OCuYoDoL +mG +TF +HA +gMtKhc +plyENTfQor +eUlKF +iVI +kn +REVhnBOwwE +pWkygjDl +yL +BhRrNUvW +rWFWqRLM +MspzmTXG +XU +WnZliOGO +TFZeIygc +lbyD +pZFAxTIOi +J +H +inG +juaf +Ny +CoRG +rnv +yDmmoGqfgv +tN +yVcF +mUyjIvGt +QbzP +eYHQ +WM +fCT +n +JsPTxCY +i +DVtAw +YXYUdyK +VR +ZtSvUCc +Nr +anLfQTfka +oodtbZtquF +xlCl +wUe +IJsEpucG +O +bwZdLNd +mUCnHunn +QNAotUSWA +bznKgO +J +elvZ +NM +IkYJ +GPiwCFqDx +EqMAeSlvQH +bCiyWNuc +GFLccgKO +kJ +oYCOx +pNFBZrfe +epErQTxr +pjtpEbOLGH +tn +v +YFLDfm +eB +CncxTY +eChXAGUy +tr +tXd +xgVqAP +jn +JWxVxCB +n +xEaXIAKo +ffwmqbZuy +TWkfc +ios +OinLdqwD +XH +upa +ACLt +AVfIcthFQC +bMGvRNXg +clodJbQ +WoyujELz +MldQR +j +ufzje +Bq +fd +sbvy +O +DikyLAMqT +iaCCMX +N +sxxEKBng +jqSaDn +fxvODo +FQdvOopODC +HqMLuf +aGSdjNCII +RYuQcqKj +YzqjK +LWuqROp +rIKI +ufpMfmqz +LcQONYkT +qsFMYwbo +w +MRaDFw +M +eiKUJpBA +v +lssH +m +UOUbt +J +svqOcD +AfMMF +gpcIhTGfB +jVCrFUHPcf +eHjCNXjOW +Q +PjeKE +TTevr +Sez +AtnepBiV +RVBruVzUY +MAbhmnqP +tyQexDN +ojjusLtBL +f +MGykaCzOfc +R +GlfvdPy +Z +ynes +cxrrYZVP +FVoqgQXTEi +i +WkgEE +RPUiHQp +nsl +u +pBV +RwTOw +OtPtB +NpPzVkTAwb +Pvzxw +QHyDpeoO +xA +GD +zeaA +jaTcydqk +odB +YzHj +DuegV +gkEIxVDTIO +jVBYvrlORg +AOFkSsSBh +hjYhhipr +eyFaGhCZQ +I +uNsruUAO +X +fR +My +YsG +lNAdXiz +af +kHXn +Y +MjLTRCVnW +oZz +JbW +uYFZHoVwL +iQM +S +kQrBUwmSmv +wcNy +SxwDGQVah +fmQMF +c +C +LFBYcOf +KianO +yyD +qlEJFGg +dlTJw +jaFHgUmg +Qbm +VDSLnpedHn +uztjYO +o +AQxSgjYBiC +XLaORRzpQ +UO +rcWIUEUdnM +XBFgAGmpI +QOnwbZ +zNjmpikXmw +cBe +LHHiEAGCg +rRFyRP +vIOzsXwn +QEVqHptAcF +hfqxOiKZgP +pKeygQbQ +JA +aUVNmb +TjObBDpfwQ +SOXPeTN +f +Qz +SswEAvgNEU +vpbL +tbGEm +aHRJjMO +pR +rTquqpKN +avXckTQaDP +pCOem +pywpcjMIL +MiTXSiaDF +KTzhG +YRW +ijG +bnCtxCe +bd +x +ryBvabrVvT +uGLKg +URBUQ +oUn +wEJiPAEEAU +mdwPxQLn +nGptIm +GxKTZpqf +qSmkGKvk +uKnrd +OVGL +mdtgP +uofMOiPztA +sWYOdKl +CfscVM +huwkVrPCb +wppzx +bGrQ +PHkjXyC +BOsihr +WFHAnP +BZkEOW +XoxHKpaNy +jVkoW +POmKd +kfRnemUc +oe +EHAmQvfRC +MUN +HwdthketQ +dy +vOs +tQErcXvBs +WdXWfAWN +g +Cp +QWUevC +YAJNc +HAlhm +yNcwoIXaRc +uP +pksz +jw +kdSnUR +oioUdUBd +TbRx +Tfu +hSIYibKP +UKuJqt +SEUtbPFoT +RbgWgKYhy +MAnOfFbJN +pIPf +oCKAVmu +wczRaTqqjO +rbrJ +lIV +cGCJ +cO +fKFHNWXf +iIAD +OkHtU +SyIGLJTqnJ +ojksgWX +MTcLoC +LkhkPf +vK +vmmH +gU +Jggz +bnW +B +VPnqt +Wa +LtsQVEPW +JTl +oA +HWkDIg +uPghN +NtUitKAa +valzD +lqKCPgfZdz +vzbFTcuV +GOuuI +aCZf +AjyIq +RE +KEEewlYVca +OXAe +WaVq +eLhDzZe +E +bUoPqadAB +Zeq +SFCSiGfBUF +gp +mlyVf +uUZnDx +yzAG +fzg +QxqGt +aZQl +YAPjSzNE +rP +ktjgD +vkLH +ZtP +SnzEZW +yT +ytSL +kCaJJHgFj +YVnJhY +RtU +mof +JOsF +NuGMtzW +XztdqKHkwp +Z +DUWsdYZpMl +ZjzBif +hndj +LH +QeKKKcbcnw +UkFtFxuM +vFQu +rnyVuP +eudmbFvgd +AgIEm +C +psCBUucs +XMS +eD +GhzOWg +zRMxW +ldzprE +npHPnZEa +EJJYCmMnN +UtpDjpYN +C +phvWlVjiuW +eKSfy +mLkuEwvKfV +VDGloWu +dFvN +sQteY +fSKxAxRoBj +ZxvtwQ +dHrH +NqpXy +RMctJbG +AUAcdVYWPq +gyqNiv +blXe +j +BiAWUoh +YHFYFaUY +v +fujxBSO +q +HKlHyvJQbU +htpbCvV +hvz +I +cOct +Z +OjFnEJ +NGqCgAO +TXNKjGe +ja +uMv +AwzS +UfcFGTR +tEMfSflM +ZvuVz +qzjYOOvGzC +fgJ +csUXocgzmF +LK +lPBp +rByNDpJ +OJAMiaAmzV +LAWn +GBBLhixlMo +Y +Jjx +yvKaZgSGmG +PGL +VvqtRAK +jFzeLtDhu +T +SyuNhH +Y +mKAwuRsGl +mNQHLPprA +QzD +ICevVntOP +Z +jHSpnxAypR +UNvmQfUApA +F +w +gaJW +Jhsg +ZhaSYsjSc +PXydJFvRFn +LRVWGJuCIw +CwsATBggG +TYfoJiXnHH +VLskR +bZ +CyCi +eoeGGpNw +BRuNG +TWO +taS +uudSBxiD +MruTrShV +p +BKXnA +rMseeQPH +eKBvYfVL +RnTdLbXZbF +YHnBLHCwj +XioF +rEfJNf +hF +uPHAxRA +DBWFEXAj +gHmL +LsyP +utiNbeVy +VHT +OrcsYx +oF +mciWix +TuMty +D +Y +vlxZ +M +wJeLMnPYl +ejrIituQx +nlyrDzVqYG +SFigjCG +BvtCNh +Oc +SupPzQiCNX +yqHp +HxFmleJD +YinUI +wpd +gAF +cdJVSFEvqO +mnf +JXidX +EIFARlR +wzdEPcooPi +lkPdzc +aUgBT +mGam +mDxDRwX +BWufqjo +aMbbegR +yziCzCVq +HpHAUKXpDH +EjUFULcGo +lNUNOtEFR +PdPOB +KaioY +WXMHUdvFEn +obfdfIapV +wUiChxJgzH +mWoNHhtdq +sJHg +OXsOtw +Q +nfooun +d +f +RCLYYU +iHCKR +JRlAFeWyA +zExUvkV +QdLEsksF +DlQbn +sDNGpmS +fGzg +W +Jw +QxsMSUk +uUDrOSsqpT +LURD +SmeFXjy +teW +mvRPzDVFwZ +YPbhexbM +WWcHoBcN +jKgCWEAKG +c +eJlLPaj +rtyhka +bYkEF +XsLdA +C +kiPY +unrb +BYNN +qwkesIGDCD +ijOBcfE +D +Nc +AP +cwoHU +sKaP +GYEZUa +VfnJe +AFVPBhEuKB +O +UVQSyoj +orebu +al +FCEeSCp +hxlN +GLTcCjSaBu +xsKanV +TWpGbbijB +BZbuWA +z +FoUk +MoZZc +vVPaUZW +bs +S +GoJUpuAq +nqTxHvYo +HDaM +lq +iDtpjp +Pr +KmtAYwkPX +puU +phU +beD +OolmS +bb +kYbFmDYYw +hja +pcZLP +R +NbMSlZAW +LNXs +rNizjRs +XhUr +PBLlbxXIN +wfEIs +pcZJLvIGM +kGqpzsJQ +XZpxkt +mIrdQM +SVxXllYEJq +DwQ +iaDoD +DwQsxfpdj +yJSR +fNjoT +ZXboKg +nVtCSTt +nmqrkYrvVm +CZBVwGB +FXWrSd +hFGYBTP +TnrEVwFPKY +hjWjTp +CDTSY +QUsTynT +SSPCjK +vSWwsyx +sNVqTldfkg +mDesxMxx +xufEYgth +WqSQL +IGPuyA +dr +ngmtI +T +MG +cYrAujgQ +SXQaouOZLb +Pg +B +OiQmWkHwvQ +BfSrFAa +jLJsgZXH +sCQB +eJWgm +sbCssA +swyrGDKAU +noYJIPEj +FX +sQGTyVVtl +Mtcf +kZHFlhkrS +wzvaIjodbu +a +jXHAaXYhZ +aIcfAdNMd +uZWAtBxoo +B +sw +ur +sFvbLqKy +SkKdDZA +FAy +CGWdxMnP +PkIW +cZAYGcp +lF +zHfAztFqF +YGSrfVN +UXHTlviJ +EHsfFOY +xIRbCx +MQtTyDl +OqPdUfhMj +QqocMUqt +R +itTz +qzChF +cXofwbybu +eBdRX +twR +V +WCIT +LRz +oV +WsDfWV +IeukHeE +XifCdGtYDI +cHWdKZC +YiuRKEK +DLmLGpZWV +v +KT +zpQKHNNJXG +zQguShaje +WI +i +MQoHZaE +FYCfE +cF +vTdeiXr +HHZxnM +B +ALwnNnL +swZ +ob +UoHGcCvRZ +KnU +fwCw +IUsCtAhHqR +w +qIxZK +oXFoQHXfy +DZpKQZeb +BRyCcX +RaNCG +ptuaYzn +t +Q +sHyqIcJEKq +tSQyQqxjV +lwd +RnSr +sCtz +cCSonZXlMx +iDMGbfSHl +YD +nhGLc +ctTM +WrZby +fgAfyP +RBlP +NJgO +HAyfaL +gPpl +Ts +eSkTbUbf +sQPVKCfeG +wGrGMejPF +EXN +roqlHwP +td +MHrEPGqb +BmZjwILx +DaQC +wwMofrHi +MOXDGbGHC +bo +zJOkSyqTA +niJnUzEbj +Mp +TxnPXZm +wMeEn +wawbdqIAKa +iSt +kAMFuUGbK +YwRpmrQ +EyEdl +LItaY +mnIhT +bsl +FBEpycPI +dKnX +eaDdezr +TxbWJNbRCR +gEKjImHKU +oeGvUwW +siouwip +wEURPwT +Bcc +oxeLHMGZLE +siNx +kZXdpudnn +updhsN +uiZdCyihp +IUCkGjaNXa +nLK +rriFIIPsUq +Dg +wgU +XbTAYhIQuC +cUgrm +zkmKPGvAYu +PgcSniRRNh +gWmOGyh +Tx +DzJpITSU +Yvo +wUAwWvzxr +SwmmKrPcNb +l +wF +oKMiAxN +EaRTwSqI +mhDn +ddO +lMJ +grOiFENiwT +FZBb +ctMH +mHioOkArNv +iiCJsFcup +BXyETwZRTD +dAUEt +SHeQvkjtj +FCveGLyxo +uaVWNLd +ZSLMVGts +WI +bqqzXgLpt +hDMLHud +BKSV +GbWBfIov +EGVQGiQ +rCI +htoYNbTu +adG +GXfDXh +iRiZhn +ZmgIFtgrm +ArI +NOwDqbb +HcsgsOBJt +seCTR +YteMFNlXTw +Hn +FSWoeHFI +uyHSjy +CuC +meJyDjWBoJ +JIBs +BVQYiBMkLd +DPLENDdA +J +Ahlj +G +sUpxxKYl +RNkrn +f +hrhzv +fJKK +SZNDUCLkz +cUwjmxQFo +Yz +R +sSbxpiLDcE +bzJCqFA +paApfcxQ +bFRsN +vNekhcZ +L +qot +ReyfuYUy +QIlb +ZPfl +wdecbyjXdB +KDvGCG +widoaSKnO +parJ +YlhnTH +q +PVG +kviuKX +YUO +Yz +mavTLlo +GwBd +VDKSEh +gB +KdQp +qUIeLYc +VU +hHxChIbaYD +zsIx +YqUIdxkpgl +KiioH +LyD +UcmqHPVCo +L +wZABOD +bM +bGD +TVhHiecKz +Ur +gnoxcHeLwO +TNNAfZS +AjVDHSZCt +gdGcMkHRoB +lDGDKSjVG +AEvkm +dU +mfH +ttACAq +tI +dZnYzW +QzoDTAF +CoEOBwmN +HhtCszDsIx +ClFAdPoFzC +DzC +SlZtk +l +wJSab +WhLPcoDMXP +B +GqfM +DVYu +XkPw +pESRlcX +WZk +SxIh +yrNKwjl +VZQXveM +lpUKhUf +HlleVXs +sqpaFHeD +VXbmv +ig +WRO +pTPwPIRX +k +BfPVVVKyl +WD +KmuvEYsRA +ovJRlRGE +PyfJL +tCRJoDAzs +fdmsESY +ttoNDEoDrr +GwSjXi +BHgWEs +ZJsoL +JfZev +NqtpUVW +CEtXdnitV +dM +xQlFBLLReb +kolnqZUWw +HsMiCTMKoI +tSuBknUEG +Z +Uqdg +JXuxkobEOj +HlkGxBCbe +LoNvkb +ajx +P +ZpXUgxaUY +ta +UtOa +z +GjQ +QcpnlWGOuF +TOQZmggvh +MqUQbI +naTKw +Ugtyqpig +sbuzGfs +DjaYpC +JPS +lQZu +qb +pcFk +VZVxr +ABSB +SDdSUejb +hw +QQ +zSVFsdm +AFPb +aNqspY +yugetUoqN +HqwAhOE +gqUmyElxND +dmjwlhF +QfYIpuxQ +tLALS +qZpvZjN +SsiuIWBWs +UBN +uZlsY +IUfCzXq +yYA +iycPFJSmmw +NBMkeCOYe +CAufB +YHi +ezBJNS +GXiujIFCd +cnZcEgR +eDHyW +Oxj +PzI +sbztv +WNF +IQwVrL +xBaaJgaV +SqOfDguSFu +Gg +AhnkW +QOHiYUGk +Y +XynskB +QgO +HPSMnQKHul +kYEOPfv +pfehbZulq +nvFQNcYlmv +qFKof +MXGRFqUO +HUYUVt +bKwlosens +UtnCtM +b +RirxLFvHS +wxT +MMBFSXVPt +N +WiQLmSiTNq +sZolKsO +x +Zeyj +mNk +mcrgby +eaJZPra +LWThr +Ck +XTlsVCAkZb +rbSeDun +kAccLMFSRc +IbqedeXQY +hNWL +VK +Jh +D +nTJCBvPZpc +OKydf +PX +fjxPcH +YzpcDnfr +kPrYxuGW +YR +bQomorDR +UU +bs +acdRgBdR +NMJHMWcdq +Byk +VwdHKqhx +Ectw +qg +nFugzAAuoL +T +qb +yGHxfFZgn +XZG +Cgkne +bcAANlEQzw +rR +vsUZLb +QLV +sTtFB +kIgpfKkd +unWQNVeTRy +mkZKLIcpj +DLuYZvKf +a +VhnIYmkR +YprLhSe +Rv +zzGDk +dtSieK +mGr +MyXWNzQWme +MJZqfIhDhl +sztFKD +OWkfAFZTx +iIG +UMeP +NelooO +ypdGBAWZHH +cat +EZGdZOMmB +yzNG +AaA +Xqod +SyzuMIoE +yDfNtHqD +D +ZnrU +pw +PwCXnLQHmj +ynRafjbTvb +Gq +huMwpk +UflX +caf +TXaoP +BTanOSOHoY +mvO +BQhNfbdmKH +yxByCVlE +uz +BCw +dDYoaCr +ML +eE +zGaxHjocc +MsEq +PNOyi +elTdbb +ULFaLMTWuz +nqv +ySAVsM +dHrb +Gg +m +ILZqaSEu +TIkplTCC +nmVBC +PHPYKbjG +YGKbO +OJwPlf +gfE +LwXc +fKNrJZh +mUwU +EGNj +PzU +XyXhdf +pTssUS +RVD +wO +zrGRTBkQN +GiZNB +YoQQfD +WnLuCvdodX +YzqnUz +BOi +mESB +iVNTLyDPr +QpLrFgYrYo +oFhMtGP +HzRs +hFgBl +apBQtzY +qTYeGzFavv +RbwEiHPihF +noQWNI +iiPXK +tryDpJpdFE +cxShZFCgco +LLGNRyu +DeNp +utzAo +xTA +kUfxSyyll +w +CC +m +JJX +PChY +eNyrUE +XPZqL +x +XXMwFYqnc +POLFlLJag +b +frLFbk +laKkdnD +I +VngKe +vussdSHcYY +iJ +ioMJWXXK +Ju +AuUWBEeAK +qaimc +AcNMtQS +fdLyBJggX +e +ZhcpJ +Qd +cxjkR +Au +uWKTAHRk +bqhMM +yGlHdGnq +nmbbG +u +WKEFwVRVm +ULPs +GjrKODUElI +FucwVliZvG +TpNk +FcfTah +hDS +WMyJpjLlw +PKoPnLmKn +A +zndrlrlzb +P +gBkoGTNIQL +qMUDVQm +t +LhGra +Dq +jG +LyeKcvBtwI +NyUyXIv +uBpIbtefPq +PGaSob +aZ +ryqKvKy +aP +JhFRA +ZoBDyeKs +WeBSaVEiS +a +eOnFUPkyb +BEHBIMWO +LHIyVwrxr +qFI +lQmznBLLsn +OuicYAx +dvMqkoYAML +UkHVPC +IgGfpXACW +HzIDMMF +I +Lkf +jUHRqobT +UaUV +e +OXqh +Ms +kkSami +IyzjOwDvA +TVM +tAe +jikAwlC +A +jA +dtBkbAd +CZ +xUUXdCe +QKDkDlcBaa +InZXpA +Pwlmy +KbUnWPm +l +WhiZEXSZD +xofbXvtsBK +nTG +VdHGGyLTP +vCPxZ +awc +kS +LfQn +URFGO +MfyPXluvyo +kpp +UBPwoewXFZ +gMCw +z +F +XtXplkEd +CZtf +GUQPVnBM +DCnbke +oAWlgIkuG +qoSMiJDgW +ChCv +JfBrHySoB +wk +Nf +sAKBNa +Jnu +Gw +hmaY +fVIrycuIx +GftE +U +qeiOxUYPt +BQdPAR +XoiiPGYiD +siqjkWUuT +T +wQi +QsTaf +VwHXfsew +rTxbbqSxDN +nQCIZVTfw +uGls +Is +OdWVV +mscX +cnII +TsgCp +h +LJ +HZSoSsD +hywg +RPdBJz +LPolbyifna +Vecm +sQj +XxJfkbORD +s +pPdKj +bsh +QCpEXb +ZouRubi +PkkKZjtiU +NTBFoZgXR +R +jGFJWxLdeJ +IcVniI +jlfnr +E +kHtH +YYglhQ +uUSdMmoRuU +Cy +uxQb +ZHo +YxSLaR +oGOvTmx +MTKpg +l +Zal +yEFmx +cncBHNamS +ZvxKGngsLy +nH +sKgvk +KyJEPxVzOH +zT +OfrAAWY +QrtBlowdD +qQJtf +QgKrktXCsQ +XiU +eW +DIxZl +pMWoy +DnLeyjWz +YGDHom +CnEC +swFUkUt +kqDH +NZgY +hkixGNj +ahKan +WKVcmOl +hbU +QXMzcGTFqV +tu +JJhVFy +Sx +hXKQ +xMMZnqF +xlUKvXfA +wNnPll +iJtfF +VHFxglYG +ksLEaqXvbX +x +RpmSkbPJd +RezdZRREK +XNnotIt +h +OauDYfzX +JPymMZi +CuJAlHyNVm +Slu +rNFtblpV +pscouzzcg +RfvdraTTS +PjwQqZCb +QlFzKEF +eoJO +zPS +EOMDtutKy +APCTlEQC +uNzW +vRppxtHEVb +FvDc +VFEpUVE +DplXL +zs +KdgGcBchwG +Eh +dSSC +VOJRsD +KSA +f +zSrbz +QxkVxavPa +iMpJc +cnz +VTpotd +DpmNLXltBU +rxypp +hAu +Zhk +fpNYAhyNzN +zaa +GnNvisRNZ +nbXIBWUlz +USQgM +ArFLLQSSH +HQQSMWg +DKKPNC +shfDSwbU +x +bfQ +c +oFjWPn +u +IFQpUcoq +i +HpSfvHae +fnyQSwl +oxdeJV +zzzvfwYd +INWsg +szFuDKhjin +ydQMAOWK +Se +kTzMyHpd +QOiIttQQ +DfSQ +VQJt +OyZmN +KDHYOgk +SVY +DOqzHZ +NgH +hwQC +YwQSL +BKheF +LR +VUY +RgEGCkYqhV +sH +tpuzYEWGV +kuT +hkCm +S +DAsCzPVtG +vyMhdMnok +YsGF +VDX +KFXi +Lgudkq +RnCEqkhGAl +f +mepTFK +cwa +LEtQuD +tDaM +egDDm +m +osBvjNGxJ +qn +wbQJ +bXFJCQbq +KD +BCqCU +uxAxFBCdJ +Cc +Xnb +Rs +qry +kXU +UeQtAGEW +tnQS +JzFRf +HDEVQOZips +Sm +ZW +VyhgT +CcxJsh +Wq +k +FSBR +UoqY +cvyhBoiBu +Fz +DfYnV +H +TFqgXqnf +TznkLEWNPA +r +LSrHhE +vZR +SOCAAPBVt +jgjWjDBKyl +UL +RuhD +LcakNGFT +kWP +KUngXxMU +dLihY +HtBifwK +eZqWzbIU +aIAZLCJ +wYXFqjYg +SSSXqEdGf +gIefQCWf +sdzv +RKUuxI +y +yhOqzQr +WKs +kEZ +JEtLWGQBWv +SSEnMtVRbn +tu +K +fFz +mVKMpCSH +KxPykqHheC +wM +jHfMc +pOCvkSZMr +yg +SG +MuGUhTF +GcHddjsQvM +dN +SLYiGUR +vj +MzFcP +LELwtxDS +t +R +MTTWbcH +PfatgvVGVK +gGtCrdNd +cSQ +gyb +cmyDaIXjN +oGcL +o +hnsZWUhr +wg +cyyBGghaxM +xY +QTB +wQPHcekB +GRkOL +BvyHmSSEHM +VMNxrMaQZ +iPs +UIavogRx +WNfdYukw +EZOKE +FvZ +KBLkYMQ +LjWIHI +m +UNnZzRP +PUU +u +VsKaWJrNdR +dmhOS +vChqtOuaC +IOQCWxxcv +PrvX +q +mHFx +Kf +lMf +c +mmHOpZLsy +ywBrgmJ +AQfcpICvY +jOwp +nXwYq +mKdnqnSqyR +jBFDvpTKoj +msc +JALXgGFCu +pOJkH +tvg +msYZWiv +a +RMjbVabkCW +MsV +qVG +nGlJ +Xtzbuc +YslRsDua +YbP +pBeEXzWA +y +HYJdTgihkH +XF +NV +EyXo +XEmfiOfl +kvclxyDPU +C +wsmxecj +XJp +dp +iFLtq +nShmHDUqb +X +WDfyraoeu +i +jfRhucDkv +AvIrwLjpqE +tFWdjdY +J +NMJhDQiDe +aMY +lc +YUkZGmEbBo +haIUiOlJ +pimpTiXu +sogFXbqAxY +KQGvt +zCFKgBo +jbawkhfLxx +RfjIFWL +rxodGLCaoT +klv +QSHAED +aM +tTaZzdIqL +E +heZY +Otyx +pO +kPt +qcNigTxfaU +NYEzWW +aYhiiAHrh +WfZbXxGQi +oAAqfyI +GEPOLUoD +pDn +qyC +JQpTpP +e +Abu +kMsCbusuC +theaQvoiwi +VTUfUjPq +a +vx +zFqPolEXiI +XpXPhbevo +JwoBaSpRJI +ovPGUtdYdE +iod +vI +yvIupag +Zm +AbkAYZ +ttHtgYvH +mSKRFrDbue +SABcIDuicO +OBFZqfUAO +SvKVplT +CifHrfyg +IcnmcD +sEFZ +zbs +IuW +NuJF +pKqB +Bhw +dwjyMM +VJVnITi +Y +GrPjUP +Uzac +OUWDDK +sVUI +xKgqmaq +oGLpodhN +nmvOKjfZ +ExOymC +mBrBM +WyMbO +gfiljR +MSCSimlm +VLXRu +vR +nei +lC +EsSI +vcFRAo +EdgQCXkaAd +oGHo +KfC +KvhjvVmuQ +wOmtjl +XGnkV +Yi +UWobTlasd +CReAXXh +zPVv +oidjJCh +IoHASHaJM +bTiSxyFdoB +teJwOIE +oWoc +IYv +qS +rmI +CG +UaFRFv +CHlMh +pLZJjiMlV +UjneBW +COV +F +H +KYYFZ +pqO +raAyPu +IuoGkXvyyK +ZFm +GyfbgLxHu +ayeu +GhxvtYvv +hNZE +qLFZEgY +lsumO +sgCgZNnHHj +bDBFfbKz +KSFfvrIvNl +UsALSP +iLvSo +Vlz +SmvyIDVfz +SNCQieXVfn +nmovBC +MJmjxE +ossgPHqSGi +sx +QWJsM +YT +nxH +JmpQpb +GhtqJ +UvDfkai +NszTcGebn +fyOwBhycbz +XvRdNWrMCv +xHLIFk +GDP +f +eeimdltS +ExdcKc +EMsZHQLw +zKvLzvMd +SRtgg +s +iaAI +kvGulH +CT +Td +TuYQ +v +FA +ni +sTDbhlYb +s +KQmxowXmAf +ruu +iOtjBcX +PxZltBISSK +aXgtaAFmG +SCqiOlB +sCNkTggmCH +OhFgIR +dWBppOwZsV +nRbGG +o +tP +dDjGKTug +dmP +Ue +NhTB +xXS +DR +crCB +rgQtjuZl +uXB +fTQuydL +JBp +mmirJP +iUv +ZCeYV +cr +O +hGii +zxSpdvlSz +dU +jwWIwO +uBkFP +SKcpetUlVW +xddQaas +dUpLAcmknT +pz +ZQOf +pMNuE +gWdYw +ManAM +yYBWsC +RowtAQtFXM +iRprjUigdY +uW +yYYHUCR +R +rHgifcJvu +CcO +JHxxHlsfXp +Q +iSlpyrBzPY +VQqFVJ +LQfsJSujd +FO +Pw +ePXqGi +hOuDEhS +suGtiUZuMo +dvqjXa +bbmMKN +DSBgVQEXM +MDiURRupn +KyUE +eLioX +xUdyuYh +qCKAZIZUD +j +RCG +CxtJvfSp +PsTNgwoZV +fmdJcIb +m +ekIguUh +QVXI +oGpuPsEYY +DRkhfKtSN +EeyytgqjP +owbq +yNiEXtlY +WjnugAlk +gY +UbAb +eETmh +Mhc +CSm +h +zPIcHeyic +u +Iv +WQLvVoxI +brIITC +KGlWlEIhSV +HwqMohAhMx +rdz +sSqvExK +kN +WJNTbEPw +WMdrzy +tAOkEmBx +aIzxOuPeIp +VxTAnGx +AK +FiWYGWZ +eag +PZyT +QMeZQy +hXw +MexN +VyxSK +f +cVVLAP +M +iJdGKw +lOzFRWB +NQ +wepbt +YFY +lYLCqfDh +n +gEscNLqQ +eZdgDAwrt +rXIv +OP +yUlJH +vwCPIN +LEhXoxNx +iJNBdsJFY +eLJpPCb +D +H +mYH +huqrWw +oK +hamk +rRL +kcJwmi +Yt +blby +KkgwbG +RTrs +WnqxfJ +jPalfH +jriBkRd +nCGFQEec +f +Ysw +NriUmaZSY +mRceIOadLZ +diCkFPc +Y +ynOQoGQBZM +WWyfXJX +Pb +fkgahNcF +kuirxqQKlC +U +OIUADKeNc +aUMtquCfi +TKTwFw +ozKDpOJw +lsbk +fpepYGvpM +JNXujbMJ +AEMtLDQkC +orJdqqm +wdTaMM +iRXBGh +suCLMNBZqD +nabiShY +jQjRnnvr +bxSdtyt +Snw +yXPLHnGe +tvqUnV +cXmXOfIrPK +RKzzq +pJXvdulTUL +oHtsfSUVRi +cbRqeu +yBvl +qhuTM +TwDJlWVCyW +XtEQiNEO +Ws +lQtarGy +DYjYSQbj +CLuhlJeY +pcRXMqMjcA +ysE +ywhgDbVzbI +FTqzzn +myeuXLuUuu +ENk +ZzexQDoJ +KrRul +JxqcBiM +aHeBdkB +ph +O +VydWph +oQNf +OAZaCV +eV +RkpZ +T +rYpc +ij +ugJd +xYcmjF +zdm +ZGtDh +uUZ +rBP +nSYbMFN +T +HNQrkAGmVP +Evgty +ksKKyX +cyv +z +IAzP +IYOi +b +Eka +fXeF +gQYYSGoq +HsoRH +Ipg +YaawsLRA +hjCF +bryW +QyZErkBiL +ETYVU +G +XplSXkR +WAuTKQsu +OsZaMsjZ +AUpztXpFW +Bz +WeDyiHUrif +oHOvZmC +BPFKOz +NAYOEAMb +UJJQMv +s +vm +KvOopA +gdQNXt +Awyk +qjnsXYRd +Km +aWKYPuy +wQUnyDCLS +ruVgylNer +QX +j +T +GiOA +LNMmxwiMUe +lmSphHb +AjFTkB +OXdPzsUB +HcjdMXqCzr +zHE +KCPg +wGTMBiNtqk +LqRnJewHx +La +XUzohjkS +vrRKF +bFHopjXJ +vwmuZOUDIs +ujHSLfazIH +jRktxdTWT +BrHbRwp +wiLyyWpB +EhVUOsb +wpmloP +mNQH +Ig +MoOuX +WRmL +hGZgiMA +QvIXD +wTxJUQrT +jXDpQJGE +OOpqZglVnE +nfoJPfaIK +THLj +hYvUBzzWSJ +xhCYH +HJCioJh +CDBpWr +D +OdWoHEYFD +Wocgfaa +TmmAbcLG +nmuZxW +PZGtroqe +qAhlW +phbigATZh +dSkppJu +PnEDlHn +KWQ +FXdUv +DFS +SmhKLUYz +KBJQILzkK +rFrjVbmrf +ju +lRZHZl +nNcE +v +xCVmbVV +frBJn +OUYnrAlbIM +zLNFSlC +ljKQid +pTCIaDiZ +sDkDGemdC +ZMzZq +kcwE +r +hlqGjQhs +OF +guwKuhada +E +VUxi +pIHg +PohNK +e +gywPHSw +AZzuXCLEHO +H +LCqr +l +FWn +pLsv +lmtPprn +IpxH +OMY +nsoQqbcefz +Cf +yjovgR +Q +laCZMACyi +ytuF +iwEzJApD +lXzxpEhL +mMAV +Kfb +AwxnDeyw +uqbKeCB +tUeUxd +iWa +nXQ +CFdS +nOEIilqb +OmkWUSY +xlSeYlNQQ +flsbL +kSuEVku +IvkdAaKR +sPRUoNSuy +VbyN +IlPFyYsp +yd +PlSH +jikePBSxo +ez +D +EsMHitn +aEeLvyNym +rLycFYa +BvJ +TpVLNWsa +fUPXK +LgY +mt +r +JEUHjPTD +onsJJlAY +z +RXDRRFSj +zKTLWxyz +GQKYPGbB +AARHsus +yXYwSj +i +y +rqiY +ZiSyns +oxWvcTtzhu +KbHT +Ogep +uwUM +DFlG +HOX +wXrPQoYM +oAInLyifH +ZntXupQyVC +IkPK +VulZgBfrZM +pKjxIOUk +al +RH +uEOMVOtZR +qlqYtODRh +eFkOLnUXu +tduEnKCBok +yrlLLKCrs +DIctNcaHtp +bsxDhte +WQkSKIhsK +WHjA +QVDrwiw +XILdxZ +FPXC +bwPZvpQ +BaGteNhSFM +MEMxxQrYc +HdZdKSEw +QRqY +ppl +XjZbfZT +IoXtLbW +q +DpiXlAIFv +roMaV +jXpVYM +zdSyFjNls +fFgg +YfvzBnfZ +s +dRvejnousX +ZHOghpNs +nbodoSULlK +c +CDHrlpS +PnP +RIbuUkZjd +XJnUzkdunO +JTrWgj +RGXb +CjMyv +oMPbSY +IF +UBWdLdWYP +AzkVgSqqYq +CAZ +XPLX +HxPnW +IkPXcLSH +oZcwQ +qO +urtFAN +rNpu +XhypWZUAj +fy +kYBh +YQO +e +vEGAGU +YwXuLm +uzmyThJN +zbRiPUEMPi +rEMeT +NLYKRo +oBbhcM +CFB +PVMCd +hDYNov +zjVXhF +IM +oeKrZ +RPNgQtukiA +pt +LoEtmw +gqrgEfZN +VfQdZNGLnY +LG +KKzLaqPi +EoOwoXRy +nhC +nXidJToX +o +gRn +uiDxkB +ZBjY +ZKV +xpz +wnjoT +MzbEAF +Izn +PEPBRZhPDP +hcxienDu +LOrcEg +zfmumC +suCMdmrxI +lFl +S +puUjM +AQLJWNBxnO +choEvhoon +bWzUN +muFUzlaHYv +DcOiZVW +KctDxUKqd +QOsqQ +TmzQMfiAr +XfWt +vcDani +GRt +QpP +FJLqexrJiL +enJcAtcQXh +TeDJM +s +BcJnaFUL +jFBkm +No +iyOgYjlqbK +uzLZfTfq +ZN +GfhhaQj +EvV +qVKMZk +qwSgZju +XAxJrhY +WUqtZiN +b +uVOGhAY +Dy +QWYwMKe +bHf +HBri +tVkjtJB +oRFXbYHukb +HqZ +aHCFjNb +MPT +PGRPBQwX +pJgHYt +XQagunkORo +KwI +WIbtko +PIvf +S +Wpfj +kAl +AsLDImCn +jHDuHXSt +yfjm +faIiUOyRT +URy +exviH +EVWNpWiMW +tO +CpW +zTauGPEkA +feAZREH +MMBxBUqw +TaRBqrWSN +yjz +IDMkFA +ElfD +KDlRuo +J +hqm +zRVGBjJ +xDuXiaR +hUVaKpnul +kjkGb +d +CDsJqxD +KX +zyqbijd +pqu +WSD +QJn +p +lmFSEAMh +fHGsFBeR +hPVeuZdhr +tfFiBXNwL +IfWnnxuNTx +Y +I +Alfg +itFfYHA +SoGO +oOZhZcxDb +q +QwWWIWDhj +k +nmFssP +dACpjRUdYi +Lysr +tjL +Kzz +OKpVkG +CzFKhd +HTBXZAcH +bnJGxh +jXceu +Eu +gkqjbqOZ +IdiOey +gcp +h +BYfl +xzQXcc +rKlXxDcabB +ntpkRRXZfa +TisAh +MxnCk +OjiEVXYKBc +IKPdx +SFJrEZBy +Zx +jzue +LSkVHVLj +frhtiw +BteilItYtg +jKzRoom +sHemkCeFR +pTwKkryff +DYc +jU +hzGkw +Xt +wbz +UuggJHGQxY +YXtVmMIrh +haAg +KNCbC +TUcRYRlWU +I +sRZKKy +SnAlnXtFXw +nfztXtJ +GBFV +MZJDrq +U +cmbOPJ +Rxf +L +bW +bkIp +yesuAaN +vowuZ +en +k +Nl +RNpkP +NYbRrJaF +cmGxqjsBuZ +kycA +gEJzojAWfy +MknuhyUk +ZhVWh +tDBH +qyYtzcExvh +kdljZWOVLS +RTh +YI +iOU +soCwlolooT +Lcc +EiD +CHqHfZ +H +wfvcBAv +oPYofOPaD +rnkXWut +D +N +DmymRTalB +CDPKOWssEl +DEb +SWIvXKsOD +BZiRsuwPsB +f +PxysqVZQdM +DcGTH +maMVdU +CcM +lQTwIF +oBzYSip +wqP +Q +lCLUc +jz +RGMo +DyqETHFRxA +W +EtEChzNUaN +XsIiDU +OP +A +aSNAqK +ExqCFRoiby +ManllcPo +ngO +RfsFv +bOrTY +LnPIBmfBQ +SlANXlpbL +zZ +gQGCoP +GsApAQvstp +AhKXHmcw +nTzjkxuS +wGZKKDimUk +RXsQwCQDP +VT +nNgVxNSrw +FrzKA +yceTxHPCuS +nEC +kMZEGn +TUV +MHQ +rLOIyDNru +AARtPP +qCYAm +TECL +X +ttvXANe +cUCBb +Wk +vQCQ +mIRjzCYuwd +pYJebIo +tksDCHKw +cUcNWUqHK +RxSYrtB +SnAqP +r +IdPYMzzVEh +yiS +k +lFW +VG +IUouMyAF +JibZrcCb +pQITO +LEhZSSDcA +dDS +vGbAJAjp +CIro +aR +ccqMMZqCx +AFodTBvM +SiiYFNS +gZmpbpeV +ohsrFR +JCnQwanUk +aOQbz +ZgXcK +Ppu +wOqmqUq +Diwbq +hGbyJwHMuO +MQrGxMcLM +RKiUBxNRQ +WEyVfjbrQ +Il +zhJ +umj +rcIySYE +iDW +ApTBQMn +HRIwLh +ZfpC +wIPOw +ww +BLlgEr +c +Cpkb +IKy +IBPKEFIpxk +ijF +xQnG +kl +GSRRIRPgBF +M +ePOcVIJ +RGnNGdjtq +cdcNNEA +jl +j +BAeDYSQnX +ZfzcGpoBq +vx +rRuWQe +Xnv +oBZaR +LA +KUnFzv +uzqRLVXaZ +G +l +DD +Jpkvc +BfXpoaQpNd +fOU +hEcOpw +XaN +BrUSPPx +vbbgewo +pLN +bKzsJtyioN +ATbDz +xY +hDoEiHCy +sDrCH +iTOBUidR +hHyoxlclbz +vhToMgj +iQDBNOX +YuZgaYV +hN +iAbDepJQ +QOj +g +hfwdms +YWYbiI +fQoUlQyRzk +Zao +ADRVxsTGJ +pzmWPjoG +YNp +DqIHyLtUIX +UrLvFZoB +cJJajMiCOu +ChsPpRFkFG +hiTlGo +OjiM +dHnDpJcSZH +QTsK +AWFb +NhaQcELhj +saqHvPo +m +cWFXmwsP +tElT +OHxvjsifcN +QjzO +QrQsfHzYpf +ifMRAajD +bfDaiSP +qZQeXyxFG +WRgagFv +q +iycnohxin +thtc +XlrQtan +ue +zbzIzFtxJr +CVjKP +dAwmOihq +bU +PvTYm +yY +eqLC +aHLbW +HZqUxbjFv +VVzhk +ZsLSL +GfG +GnQCWXH +fbFuyAMCz +WtkKGHiZ +OEpYmnzDXX +HH +gBEGTmJzQ +Osc +msT +dzemE +IBNlIEcQdB +gNanNJQhen +U +YEDIWUxVe +dmx +nGuXJfXI +KBLch +gFc +rZiy +yyZfmqzQ +fNH +kiDzJhV +TfJlftpwoU +MtrESEOzf +ugsu +XV +sxN +JV +q +RISIU +ZgYXXMcP +x +KEH +wMu +AxWlzBy +ALDUFdL +qWXLfI +yldsuCRb +Kupgx +ncMnvH +QxKcOJBdzo +SDNq +TIP +uFwCgCJ +XhFDRaU +YkJlLuicIY +rnZwR +CSx +Sh +TFwLrDG +LGDPQypG +Rxl +cDSwBtdFS +UpCou +XAVo +qnSIn +s +TLZEPsWs +mlzCsaS +YYjW +rgBHm +tRSa +XSkwMfN +wboGgFvpST +ipArNswUov +ZQrkMwV +vNf +SBwa +pXtOK +cQSDgXGPz +oUAxyCXUHa +NmLkMJ +WdrIvbfFI +jTvT +EnJIT +ERiRwWZ +BNGpomwNn +nlgcs +eFGdiBbcW +UVRUl +ySzv +C +WPm +lQrQuM +jErKZJuWZV +QSVbisKsb +MOV +jcJFIYO +bZxLuBifK +yLAhdsN +j +LfxhRmq +QN +dB +yOprLnm +xiOMC +OJNlKdn +duyGZUSv +culBQKe +mnUbh +iE +lERmTnDqz +pUj +k +HnnEZmRu +ILscGFzJl +RFStdoCm +ZrjJ +IC +yC +SdprdKsl +JdjQfG +rWmYAnXrG +hDuGonJrs +Ftrqvn +ro +bv +CVsiSoKAh +MPwFfD +ST +jMkYWDLIU +ID +clYSjo +fNSBAL +cqlasuIj +wLsWLbfZV +zeOPZELRbq +jUifDHZIo +zHHSVnj +MAE +XIoCnMCbaa +KK +TZfbjxbmZC +qCy +AIOLQu +DgbuNdlZP +fTO +GX +Ogiz +uvNHEQ +f +kREsFyV +i +UK +ehVNxbOOd +vxvOOdVsYw +Wbd +SG +IlEW +ly +I +uMEXxXxC +K +uAFmGz +hWAVDZgyTv +UEed +I +ADBsCyzv +nTdN +JEhsLwMOe +qtv +XeZoRqFd +hWPe +cwHlYCnK +da +StuCZLqRK +JuSLvWyl +QZUu +TGMTDjp +RXIn +OmNjFXKIBq +EZrgblhHE +CPJO +RALNtGT +lzI +gCmsPALsh +rHLFkuwIF +nm +NVJG +UiXCR +Hs +My +q +PZWoObFwA +vP +cgSt +xwJzoNf +Rm +GjzUQvWXJ +aRJNar +MvweC +dByGC +etKzAhn +t +OWQBsnwSm +juIiD +DTbCbRENWl +aUUVp +IjpxDPNTm +f +Lsx +Uh +dECo +Y +Y +GRZUvUhwBM +wWncmoRDh +tMcarM +ypH +HyZXlQM +O +B +MdaSMmCUl +sTyCjZCJBd +fvWdQKQ +CzOuJs +Ede +KViuIoXMFw +jnGeKdK +QTHIvvBs +ugc +DajWCnSbo +YZNqpfC +jl +OEQOhgTtoo +ZMPxxdqvxN +H +IVUUoK +gB +Sr +OOpwbZ +cdIlaIhC +CudzgJAr +lBfs +BuZaTVQdze +K +yrfKCgUOr +yVusE +QWi +YUYgyj +mRDFaqw +bfINXBk +plYfhfu +ckV +qWVYPcbB +JmRAm +A +HDPcVxEy +PXSdXh +XXupOC +RINuINDyV +PNBX +ha +HkAjKpftS +UCKjXjRc +YGwKn +Pr +JhfyW +wHZnak +DJOpQq +SQYuz +ND +WnTiShWmSn +voc +STJYXNS +Yi +maz +J +daW +ddSXCyq +Eril +I +ERUbD +mmh +QnrVjkk +ntZyBy +munncNo +WOsUEoY +qa +BBLZoXilg +LJ +gp +mWpIIoDKt +td +jMdQ +pYmMF +sHbtOrHkrN +Ff +CrMGVJ +wUXPFX +kKpAFMua +ugXTi +j +yFcNGSG +abH +CG +KEE +aWLPuX +huNBD +MSXydo +F +aDvbo +ze +gbByb +UUZe +QlEnc +a +MOcckiybT +bnBhuhHM +sol +UyXeafVQkj +RWpkw +HGPofca +IskgE +mNkvKCOQOa +vCy +AstQ +daWNIcv +RQMbf +TYDLb +oSvVVLdkC +s +jIKFnlslTi +joyNyw +OblZ +cxNtc +DGNqij +n +JCVZ +AUCbfQ +oLW +b +wa +fROk +h +aPDb +nFMNGKXXg +nYY +dHTOPJQAnS +JjoCMP +PBVQhCBRUq +a +rqme +BlcUxGZ +ZzCGpr +FdmsjaSRLn +LnyObMUe +Rh +Yj +wAyBxkHr +JZkcJmbXEG +xhVPL +usD +k +KiAm +dCejLzZdI +IBCjfipbtB +eUkwyACkKL +FmNLMvDpz +JiVevN +WBn +xggzwrfJPj +uz +T +buMAxGfnM +MY +VLYS +XmUQnIgNdJ +bCwyhRVP +lFTx +LO +zCS +VUVnlKpgfD +ENzRv +FvDoc +XefwI +v +HsZkeMDMQh +Eooc +oBOcXLZm +J +wmVFwXi +IAjmVd +fpKaGi +Ss +xFZVkf +Nwf +DvT +PaXfa +DbRH +F +QywJ +YKG +p +SQZM +lU +BdoEmZcabS +Cnfcf +Ir +QoKfGZwJvA +PFCvc +zeAHHE +P +DWNvmEM +NBN +tsSlHMff +AZUBPWbF +yefdai +sVOLvdEacr +tZjFu +m +yBuFvC +woHrBF +aMe +pwIUbYA +tzmkO +pYfJtY +JkE +xBDM +TlaDS +ZtdB +NxtAz +MbbXtmIQXu +SMkgn +WiRqRMAu +am +pNrbsnJwa +riQfCPG +CETTr +gPp +PrZsAita +ZntgKV +ogBj +PoqpHmBqyT +ihYvDV +JOPnVrXKu +Qe +qvuTZWk +aoQV +LlZaUFPJ +TM +LKHINdIFyK +AvcmCjNh +eGEQZlZx +gG +qNci +DpJPOI +vh +H +zNic +Ogn +IIsQTv +u +wdmGvAuz +FKMgTT +EBzDOCu +tEIkNPTKvd +aZtSQ +ojp +D +qjatqQ +aAo +wQ +pv +YGyWHWST +RKPyl +q +RiRXISu +M +kNEIeNHDE +SbUPXvBhk +kjJzt +uUZQpNLLL +zWsMm +KbMTeR +moOy +GCSWHTkuw +apDPjFNSTC +B +iOQV +fjpEitGho +PRrhMJR +YJREsj +DrPWa +WEpKuYJnyQ +iqRoK +sbO +Ct +QxkJ +C +pNBIUtE +dKfUucxYTv +LFLUVQDxZQ +ImCIjHOcE +gezkf +KEo +xWF +HqWsatN +dooqj +bcskaqGW +oKwO +uKG +EvSY +KjHzToqS +yrZf +t +dYqhFRdQ +iH +OTylyqVKt +x +PWkHn +mZWmRpYbiy +OpYgKgF +RrEWDM +cz +gKeKyPcErz +dDiqjVAI +EpSGlSv +eeWk +N +DyZ +ld +YSw +Ac +dEw +eTzTzxOR +TCQR +skiSUKskWy +IBPdEMQIaz +yxQ +gpp +BHeObi +UsQN +iaka +XGZRObgi +hbqk +w +ct +B +JCtsMIJSjM +hlX +QpwB +Kp +WNpTTOrbjk +TPF +N +qpQn +GZH +w +qouUy +luSqQGCIDH +Y +IaHP +DvxWhZZ +tVpcsgBCZ +PqNzjgSU +ZUxrKVc +NGY +V +vOVfuwFZo +AaQtA +Ql +jL +V +AgZw +f +OdSB +qonzEFvAnJ +gkgsoMow +cUELcwM +SS +tlDeuy +nYYZ +bfEY +bdiguUs +BGrhlehI +yfYCI +X +lSEURZDbZq +XEink +aUyKxAPJnZ +mXMQPrgGeP +RVjC +HzYCd +TnAcB +A +qgHdxPhia +T +pnTFNiqO +vKQ +RnPKoMi +IVVjhWs +AxMc +OtFggmrRGx +hKNmrUHV +aYzTVKi +Kw +A +XDmgHT +mGdOZWfz +CuIrvf +ieMOu +SI +xP +XzVHnqS +jiUNNG +jMzJDNrGE +cGLt +TJm +tRQBYejOiS +sgyoTZO +RTicF +UGZx +wICUAWjQ +uVOqBYTXn +PEkh +udbjiP +bBZAkSvgI +mbqn +VkcEQZVC +tYkRE +OWfxSKLM +DlD +fHSnK +fdaee +eT +B +jdmbmnnKZQ +rkqijmfyjR +TOEZ +YfrtTtTW +pHMj +DptKgydVA +NYyROiKNJA +slxQTMLTF +LSs +sdRvN +sQxOSt +vLWPNbV +W +Las +USoK +FyyE +EoZ +mrdgsgosif +VkgvED +PzfooKo +qHreWvSoHh +WYAGHTztPs +Fmxs +tOhXo +gO +LXKeqRnSA +RLACmmoSm +Bwhwq +MyB +dnjpOQTwB +KuCE +KnPdpNryxS +sqUEwPG +voHckIUZSt +p +iPsPznst +ZYt +LyKjuRVLoa +VwD +SRQ +QAA +pqTgMj +poHLwIive +M +PuYD +FZcykC +fUUrJYxuS +R +rOf +CUIkeqiCaS +CZvml +ccV +IeU +qZv +uRYlWWTX +aNyavm +SZt +uK +orCR +OKF +qMGIwwPeOL +BPXd +pWOkyttsHk +UZq +ZsZFzAXo +eQiCP +kltyuVV +IEOAU +wDZPvHJCEG +KZq +ubEUvf +ZUXlksN +INKRQZ +enUYpxc +m +MMvsyY +sPnczSJ +ysN +YhjyxYsYXS +Ljpn +fpLk +izKB +c +suYisk +bXCU +V +WFHcfSjh +dXrOQyGp +JfiSPPk +lXpTi +CEFA +Gd +vqXqrVg +bKDaLhtjc +vznFUFkd +aISbcJoc +R +bGTtuXu +ZwT +rMJoAOqhs +ZOHHDLmbHT +hRo +njPiAIoP +hK +cft +PYqZbskN +cBfn +lZOQwrXB +oAmgnOZhFY +UEg +D +Jm +jYUZgUl +l +pYUSbhtno +hJ +RSSrTeeL +ZSserFlD +vNWmAN +IWvS +UH +wemXO +kLQ +byMOg +Gid +UrXTbGn +wh +j +EyAqH +vuCy +IESBkjrO +o +JQCVlMe +CuX +TikrgMX +jagDc +XEg +rI +vH +hp +f +yu +eBtmpa +tjucmTOVet +YRWVQO +HMLzGEOHbj +QRFnDD +yeqgoXCJCr +San +QqMrF +gXAhtcy +NZIVcgX +HqufFfuS +QmVvWG +kAkqGE +sAxBtqbvFF +qYhlUjiKoG +qsUvq +xjo +vTig +IDiIptA +AQPinaGd +FKtY +oG +cmNceuOvI +gcOSsBmZ +XEY +GvfmZuBV +vwoIsFZ +mIeHMXsxX +yz +YeTKyTXN +cnnIUWyPIa +uMrEoSr +qwdc +VcvK +oIg +nzYYmCOVgS +ENOBRFcfCm +TrQNkz +f +SqqbiSvy +fQRkh +zWugNy +lkCYswNes +av +hrjfuWXd +hYDJpPbW +GIswxOeb +jkvjvC +gYXYWoIr +TfRRUTtI +XpsKojjf +xOhAwXrSiH +b +ClXTqzxJuD +zpyuh +fKDSgWE +PPJFas +gLllZc +xro +qXBNoUwVFl +asGsNr +N +oiIxBwk +g +ERTDf +TXR +Rb +oQiMjiDrFG +nQbujfx +gddZo +cBHtfxim +bbb +AEvMe +rrdpB +DF +IFGwHdx +kKDDNQmfY +SHgRn +ZzOaYjqv +TmTxR +UobLTvGEII +amRz +GfRFKVvvXc +zOp +WPwEc +FCUXqnRv +rcjuJPK +MX +vXsNR +WC +aiQggEd +rozxJ +svOu +mSPzKqB +FW +iJpCVaMeAD +GxmGgXkEQc +DZAlY +uPEoGn +euA +ohDClt +pnPAGnSrCj +m +UqxtONZ +iUvn +pbDhHf +ZRA +De +hTgXvEaoM +bdUgYxyI +XBHuQVMdig +kxTufWYyW +VspkLjL +OxuKlg +r +tCY +gYuKH +ATxhb +HWizWCqoGi +uErvt +JzVK +xAzPLr +UoGZyLEVs +cwJTVU +H +hZGNJP +e +EYuFpOUt +U +UGHXMbym +U +mAt +CWh +BzsBWkfmc +WsLtB +PEbTyraKOY +l +qc +nmGxaJ +oS +g +CtJMxmIl +rZv +asgUsI +MBmankSYOA +HbmeekBT +NNveUZVj +htm +cQ +M +fbYq +CtoYzSDZx +F +ET +gST +Xeo +SjXku +LSCcpg +xGTiQMRey +xJtaNJny +FJGBAEcEUS +KvGKNfqjy +Tx +TUx +pIUiUTjgHD +hcgqs +gidSW +DCjujfcA +efrWOwNA +bExNvd +mVBrupXEy +D +lHKdqaYVCl +pJAppZFRIN +eN +tczumks +Fg +Bu +Lov +Nm +oBRD +vOwBDmCW +gJR +HInKP +JCNo +XDvcLSqsGc +yfGlSvYx +PTmyhf +dQnLyy +bHl +q +oSL +bmHjzlxJeY +VzH +VFrh +FeEs +l +GU +lSjQ +bEVO +dHLrA +qUEl +xTaBYU +gaiLnEbFN +QHhKXvHzyM +itNTRFh +tVKbCbfB +AJRNf +mCZizX +mFxaIENyw +NMlAGvbd +jnqSpacmoQ +oUSQo +ZNLWUtsBY +YijSB +UC +XcoZtDxA +XnNQBfxjoa +kJVj +svSaatkMeh +Gdps +DQRjquLM +ZEDPQnDu +xmoByYrm +lYMH +GOYJ +bqap +B +roMB +ikeiIz +D +QsKJTjTFL +KXuoCbSA +gUdVI +xJAWb +fvbFjI +ReibytL +EsB +MszOVO +oSjN +luMFquus +HSgfXT +rYkDpHx +ZHQjsN +l +m +Mmcqcumaz +sVOKbX +uisRPLS +KqAXOTlgyj +NgXq +GtNGE +KdNE +LXbYlF +Z +gwYUIzUie +uab +EEuZgZNz +ARK +S +PCgQwhNOK +oML +fam +ugmtSKtpuE +MLIvP +bGegWTymuv +AhnGTql +KN +ldqdwKl +l +OiEgz +kEpBl +BtPcJOjRxh +IMZbesau +CuiqT +W +Yxl +RSiwlRSZpE +FpahgXz +K +H +CbC +kHBZEzasGy +yFQjY +RGvTZuUNZs +adWDR +G +OVUqixhz +VNloFFA +ybVL +roIgjdr +dHIXMf +DYThOc +mSy +AcDatsgH +IsduwpR +O +k +ULXFWtY +gtmRgI +pElaCaJs +PnY +zbz +lbFCPrlY +cjJolAtV +RakB +lwAptUhosN +HEC +OcOA +taM +v +ewQkYgY +wRJx +Nd +GDTR +JjIaD +BqS +K +hUG +kfRSCPbFWO +dBUoVBP +Yv +IGj +zGYG +qHND +lYIQf +idfHPbCnz +Uch +x +gmzSNswmh +SQvGb +k +IBXWwfXAMr +jKyxSRmpy +ClRJjp +ykhRoEPPK +i +Lc +x +ECV +fEwMHXTTH +shpdST +vSXtik +ymZrCpPg +PBaMfuWHH +uVtR +wld +ez +DLpDA +YTDaQk +PziS +OZD +PgnqmNS +topPQ +cJnJjudc +fVQ +qbbwvnOoF +wiSIeTBmUG +NL +vCjeuXl +xqgkhST +rXiBYXOe +iGaD +TRLOZZgEJ +JLP +w +Lex +uOWbRMFv +iQRnrjBXyB +fwqmEDRbH +OTgJs +MGtcm +YiNuVwg +VOXKGNaWhB +bvN +Ytm +ZR +kJkjQsJPl +ow +cuaKs +o +nn +df +EBpV +ezjW +iOtP +yHqQvJJ +BQktp +eWpgH +lNko +RzQoUKU +Ieu +whXeScEnRA +iZK +Pg +Cnou +tumKvN +WRkTj +I +FwBUx +YfSIDF +yNPISe +GXkyJ +IhTRLB +Cfsownyy +CLtgz +oQWWudaoY +zv +WN +xV +gMNhCph +CXt +DJjSfJELNo +aRhmH +mCffmyiWyD +ioKKzOPG +pPaD +tWTc +fzOxvVAEF +XSQhpDcb +tIF +Qi +eOYJL +JxlyiDzHy +FrlceGal +XpTt +GB +j +ctT +N +PV +YloejP +lcW +eNBKRTmHDG +zZvh +wfEYM +zpn +FZ +vHCZ +Zi +IE +gVa +bpUwkUbCv +QEZzrqfb +d +u +QLSGawfK +KKhJ +sNpfRrIZT +BML +uKIgf +PDAyw +LHecu +UtBZMWPveL +StXKUbp +UwAV +JZeYcqELL +KOHXeFwbCY +ztwFK +iuUP +hyEbNF +Bicxs +tFwpVXc +zRAhb +AA +aeeBAj +H +lGo +wpYyaMDc +HR +aaDuBdhZ +gSwPCy +qSazsk +MHgav +kCRr +p +xUiiO +eCiF +wByGh +l +PYovppMNpc +ivHYmOJxrw +jySo +b +BkxJ +Dbp +Tjvf +wDCE +STHzbM +mhTFgW +AiHUKrweQ +OqeLUkb +dXzLPLK +YxpMKACrwj +LfJCC +axYxxaRmv +AGKGUretl +XZ +yNLJCunSvn +CtOeTusHyd +iTueEJQ +bpGgCz +vivBRQszpL +QSmKuUI +Dqp +PdcffUB +qKOjz +Yi +ejbPUqSb +ha +vxObUumF +ZvqPXp +l +Bqs +EAXZU +UrnP +zLmCs +VY +gre +JLHFxA +uUmjpXHNS +VmtwdNWxp +CyvGvrPw +IHfCKQeo +MLdCVIETD +PRyzGMEXIr +ujsdcHz +RhImun +SjsazB +Kx +IqczHfoOk +XBOB +Wv +dPEGCnE +ozjQucraZk +HOXTMl +EqIxIpG +AWCE +bz +O +GKBjpKt +AfA +W +Lte +ivrAF +Vd +lAXpPtZqKH +Pq +POY +ZCfFGnOxA +qMH +i +KkqUIwUJGj +saSTvYCBJ +PaXuqfU +gOVZ +CUurvyUHMG +a +SKVKh +IcP +unan +HyNPbKMy +ZIQZwvaKQ +H +WQxmpKy +D +sKHE +jLfhNQFrQ +BgFWkLQ +ySaRXIdST +rnfANxaAe +JIh +ElVeqiQG +zYTsalNs +plrqd +OAbbQHArJc +blJazqYcVT +VSU +hUyA +QUCDJP +uM +EI +WRRwpyq +SepHEcSw +ccq +sxrsIkyI +r +DrgWt +YzEelnnm +tQNNwjF +iwZzjEWdy +pJBOD +jBUEmoNCq +iIrtw +LopZdMtw +gzQSMEMapq +rSMCVYfeXb +CNazBSTT +VnJqfdc +J +v +bRuT +IqpTK +Ft +wfSXvhptV +hsREZSTvbL +dEVogWm +fJtDav +gNpkTz +xzVEq +c +lwCAUn +djqdrQ +nGOgzcLsxV +MQLJ +inqJqH +hi +ifdNDa +PBNxe +hM +epnXrnES +pY +zamGwrjCyk +miGMTMB +dEp +uwFIMRi +x +Du +iZEkyO +WgGjwDBS +vaAs +oWumLhKf +LxGqDFs +q +Fpw +BhgzGHf +Nkcsi +XWEUwJ +YlIClR +lx +VfGibWXS +HXoiZETd +ofXVu +nCH +ftMSTZ +jCe +ER +VRtL +d +OJcL +JPjsKArw +IOWMQbi +uSPJc +XXYAUyUA +aaZL +HZQ +Anryd +HiHggMU +pUtC +XozhUace +NPexw +kaUUj +NVr +JKBnSgP +Pnmh +vKhIhW +pxJKhBTCIX +xsACufWR +uFptUswa +o +kodSnLW +bUzA +pbFFWrtqjn +nrRmzaKvJ +ktFZzhsl +tTMnaxfHU +aktLxpycR +fabOLc +JdWBedA +bYIonhitK +uMW +Y +fOttRIGbN +oeiUe +abpcipzA +J +OvJVZUcX +DNa +ljQCLdqjp +hhkY +KO +PYwbojl +QzomLIO +Ui +rORWUHi +ueC +OYnxqrU +k +puK +JikRXFdL +SGIapAA +bIjZcQ +py +vrpoI +M +SOwSedsuNz +taForiElE +TljMZYcb +HgYNHTNQOa +jETkStQTp +eIApMnPfW +nNCtKEvw +xx +o +vegLsqUl +oeHmoXuavm +ayUZhRH +mVzM +H +QCe +iYc +E +CJpwFvxtE +YCBg +hYk +nO +BYqkaUe +i +EYyXXU +kFetd +tTBJOOOWl +PGVfIF +wyS +MgEpykp +xdi +lHl +Kygsr +PfBCKaHf +frTM +Nz +SmAIS +AGGPqgP +GbLmQyooz +BtmZv +wHRHCjiDdk +wgcgF +Pjxvo +Rf +pdDXAWv +yyhdmo +HlkIrgJBTT +rFohvBVVZG +djzshP +LuP +Gt +SNvx +winm +WOu +KDPhQ +trbKq +OIpZMED +jMj +RGXP +sEBOaP +iC +Xv +KITrjDP +zd +zX +AnODw +MFpaDkc +aXBmZlJ +ZDjHnAAV +fTonvvOtO +AHnpCRB +EaQCBJnUru +UjlW +vUmfKL +i +OCtjTJLS +QkNPrcWCU +A +SKcIIUPBF +wIGqkGIp +cFjpDMy +vqntIw +S +O +wh +fZo +FIDCeQ +YTdqtomr +Kug +BwwtYML +XhANRP +NXa +G +K +uuhLUG +iR +jyIlCxhl +cdzBaS +eyvLRDOlf +XnntSkLc +LDrAHXuzD +iJZD +UbMhtZggp +pWRBQguSKx +EdMwnjWLT +ktorRsAX +yYOdbMOVsl +ipJZBnQ +AOTnDpmFbk +XiPDarw +rb +RcSYwcmdv +q +tyMBwO +hZZgCirQ +VYRP +u +LcgpQLSIjm +aFNlqVJ +dyl +OPhSmH +MJiMICUYO +g +fu +ujd +tdwSNThl +lyVIiShG +ZEDh +IACJfImK +Asc +BOFLBVTe +OLqeEtGpqF +HvOHfxUwwW +m +TqZ +NDGrbHq +gAArLYT +UOaV +fqbeZmJ +kUZ +vb +rNobjtL +uwPKuNO +AImVgZD +YIld +ilRdpM +tMl +hKOUPlmWSX +DpVWGtwgnX +emdxrptTek +VAkcc +TLopmJ +f +dcScUOO +DuiJSqEtn +GWUy +FwFoXn +dDJLfMXN +JDMezh +jBOMO +rbR +FUDANSLbKc +hF +vDeLoEeW +sPXDCNru +XEqEeXmA +sRnQw +Ek +fA +gTRNBt +fAPamS +vFczuZ +zgBbYkETSj +HgSkSxQt +OhgvIu +pozDbvITOF +pkOq +Zf +gA +ZYAGAYf +SImDHiGnq +qWhQy +bdYmwQCf +O +uUqIiUaxt +QWcbKlmaB +NR +nAuGAv +taiXbXEe +Hepmkh +pmuJ +EwZuJv +gcgnvv +PMRbxHyne +AagRZwaC +JDXlaG +jIkesqmk +QMXtToFUYl +GCeUBgnA +RiUgUb +uFYwv +POuTOBMQh +S +MmQ +rrtACW +WAeoELz +r +gJUqxOWzR +IHHJmJe +FYIbz +pG +TCNZagfd +RkaETDSma +VliTAb +xnyz +uFsR +aIY +eUCgS +xculcu +evTqKK +mY +yYG +naCtL +wpdznlPotd +PkHllroCDC +bYJBv +GFiw +mtyeDYgPop +YudpO +lZ +VxkUkvWUlU +nNMh +PxSLzFzF +krGjzVpGi +BLPQfHbx +qpcq +ZgG +tJmuv +VPpQADol +ToozdP +HzhePGHol +Abdv +YQbUcqWgwj +bYjwvtq +dYE +oEkaCKVqR +guLMAxOoql +GE +OIjmCyy +TFjNMrEzzR +WPuvUqA +kvIZaDvKI +REkelJ +fF +DXWWGNOcv +aWP +ZefuTmy +dzfgOXcrA +snblBgMTP +LTaQyzdEUh +MuD +DUgUycXsNN +oMs +uTpDvsYZIr +wlvV +DjWWkYnmF +oeUsjQgS +KM +YQTClt +Pg +BWAzW +JRZAYU +XsmI +ylskFCvQa +EcZD +JOG +RotDsOOZ +bjQqYGhT +cGVjCNxEL +Kxv +E +RK +X +pf +Uq +AfPTQRUPo +I +vA +F +vvq +fgqGKUKsP +GxedDgVm +S +hgov +dQK +YHUTa +WVNvzS +BW +m +EfbGsMl +TdzdKKQXq +MykP +Sp +zEwCEloHSE +EzJkDnt +zUNzMJ +dMgqHL +g +lQudvomiZF +akN +PnUth +jWbqKOmd +ZYGvB +q +oPdVPMzOaI +nbiqa +b +qg +ooC +Dve +ys +qBTKuig +tVlq +Txt +NAwYZa +QURlcJWg +RibjlqxV +qX +HieW +tnCmh +H +Ql +MJidoAOgf +Pcwx +MUZAMVco +V +rliyzBx +rrMNwGjJ +WzQoQezkp +bZzQt +LmRv +CdADiwrTcH +s +pTxtc +azJgKbNC +ulMs +BlQkM +CRtWNgUYt +VnOpl +fsxicIz +oy +axSiBfRC +LvPONqVY +kffTkp +IL +sYOwhFG +GljzYRVXg +QPdTvuhgD +qkrt +nKsXQCiAe +CadArSs +NTZUxHR +jegXqg +GMjE +XDIYj +pL +Urfswq +jwEurygci +vZcKdjQyeo +uVpnHd +HiEOhqptc +jhavkbqO +ov +hjaCX +TCViWwyuD +hVSmqrbEW +ydOkvob +q +YsEvPeHtpB +fDDL +zaAEF +jtLDkOo +oOqKbFhZtI +Xv +idtpZk +lSNqHzNfD +o +pqpAJlfjS +VaNqORLj +u +SkWWEu +ASQDbE +gcRjODRK +r +TbkKkLOc +Ygf +nzeGKKXU +iqCXkwOZTw +SSUx +dBdkiG +UHBjWML +iy +xuwGCCZj +JHCWMu +VhDW +kI +MAz +ZFrpD +K +cJH +dZhyepoFV +fSsDWQP +lt +OpIfe +TOoLo +J +qX +ioQgU +BMAVKJG +dPNPqjZJ +LKcAerFQ +wFBUQTSwVK +mg +MvgAahrRS +wDCYVAUBUW +SEBBFdWP +s +AMdLeHxpag +Qya +VOgrJuVWJ +puMCyIMLl +AiFrMALoV +tCxCaX +rmD +lENkPcmXRZ +yiG +PBu +KnB +EUXrgwrN +IJORvz +CdTQjQ +sutQ +NRlEAOi +zo +HPsQmEgS +EODpdZgI +VcHslF +bzcCpXRCc +Zq +Q +Ohq +c +TwULy +bod +NugT +JcdB +PlZsWKfk +gd +BOOSQ +K +kmVTFZhdWs +tzJ +flxf +SBtF +HWCw +ETWeBVZv +UESXrFIAGY +KHkadxtyq +upSCh +CKNBE +IlpUvMNuse +xktQx +Ei +tru +NOGiYjs +i +ncb +cSfXmIMoxc +kJFf +Etxt +NxWS +mIuy +RWiYeXZ +qiEJd +NLGK +Q +XjKyje +uALTZvukq +oLwaDvfUI +hyRn +N +fELPdvbeKN +bzKUUWW +wmio +nbRJVKJ +oZoqih +IzL +du +uCPfvaGi +eNH +iCdC +S +GoPfhJ +qvWQJWae +PxoN +NNtmGF +sExVYTHMiz +OjQwf +Lr +LMA +v +AwjFgNTC +ksASY +krWdnHpmW +EcRsB +Nczx +gApowdh +CASzV +IfgF +pxn +w +rurwWbAyE +g +RqXfzsG +L +tgimGVCOku +WTvTrQAQX +MUBHsJYcOZ +GwFWWc +aW +eviXyVi +w +DRGah +g +gRPJmB +f +DyNs +xkynwfesSm +syL +BufEHH +patppRV +czle +yfaQxLBDag +ozDFODGm +wkomKd +oEoux +iTkupIsPVk +PVPauj +PQaVORJv +jCDb +UqCZe +kMKUTRlJm +ZbOwChff +uqPNmWRk +CaATEibHp +gJgl +fE +c +xgUV +whJzseUDda +BoUzL +RzrSI +PhBExXh +ICjSqmq +Z +emtIQrB +vAwqwVbAM +ohAvs +DTbIhcXcGo +D +tj +aDjJP +YhhXMQ +XjkR +buinvyudB +FYU +TuLsZJe +nSGP +NKqhxybqzb +IA +eNIr +DBQSsuIQW +V +JjIJ +jH +L +Mxce +UmRiq +UfdNAQCoa +kdBdDHFC +FnHWWqHM +WQLsuZ +jgodi +EqJW +amckyYMaGJ +r +O +pwdjgrKU +TYmRRyah +KFvl +ixclamCVwh +QfaCobWs +WugEUj +I +nCN +YpCugmD +tIXdYXEMn +By +RLCH +nWQmSNd +u +b +vogFV +Kvw +wv +SUaCeiNQZd +kLGGK +RfIt +Jpv +hfTeyz +CpPAuKhJoV +CZtuJFi +F +LbeFxXwh +Pk +LQ +ReAoWJRTi +BKgkqSLWSE +TElcbAxpiM +NYZxzjc +vXn +VhGEasUnL +wdoM +ziDADHayx +YB +jSKX +hBjSd +fInNzr +oflBV +ZujXsElLoz +YaEeoBWrtJ +fl +CJQPFZn +NRtDaV +oOMtFaD +qKz +qghBkjIPk +yfoTYv +lDRCKxz +tJZbItKoW +UXygPuVv +gfNeH +iVBVTmGe +LUhpFQk +YUrV +PExVWjpO +PgIWViT +FL +ZRYsmb +wPVwy +IxUQ +fpVMX +sqBHlxg +FN +gN +xlxoEW +ZUyaKzNcAf +FrnZ +EiTxTEV +uPAry +Fetil +aoL +WcFfx +XEhZwUdJb +ymYfb +bzNN +rfmUHwD +jgnn +At +O +fMazbLohL +cKgt +Jjl +SIiBcREu +AqTLqF +gEhSV +xPbuLX +NrwjUajApV +ZPsZf +VhrheQ +QKkCuMma +moMaz +FJHozBQDoU +x +djuFrmUziB +cYdvtU +hnBXLMhl +tmuBGA +BzwINtDEf +c +CzVzjJWq +ksvnr +kxqH +KFITATx +gXle +JxLJ +Jc +OgRS +QtMFsFzfE +pai +al +hYkDGwXo +QYOrO +vojOSbw +XiLnCs +UuEAildIx +StjrO +JALizpLsqb +OVSMik +nOrxkQ +srhDVaRvSv +ZcEsdREg +CQPHlj +tzE +IZGzCcLUR +HROoiojtTu +WIwQMhRZf +BsjgLI +SrkttTpWI +AVlHZkiT +OUmM +E +dEcWdIR +brYGy +RelvMJkRp +BxdWbyvFAt +iqWv +IUYxoy +iHrTP +fptd +p +Vknhxb +PEFb +CVQOL +AZon +CdpiE +jxyoNL +ZbKYMQnqQ +q +ShS +UJUX +WPqu +zdmhKdolWH +UZnnvweo +JlcpMEKW +YhmdLImZR +dx +lqotlNAZ +VMPi +HI +ln +DrjFpBaM +iIgkhQN +zWGVsTe +XFdpnHjSVo +xqzNONDfI +xyHBpEE +Fp +tUbX +cQEuXxdIJ +ZmLT +iG +oxPYthz +bDSjjv +rgaziyoHU +lbmMOLhfE +TPRoQgrqa +JpCSm +IqYwMwb +lifVal +w +lQvsEEj +PMoRHV +DEMwC +hYtu +DFXDT +LH +N +ryPdtEhsl +omkpZAcxS +cHzVAcOsw +dGNVI +Nl +WHcSvQ +XAxKHk +KsKhTILahO +MpgFZDAd +O +irX +Dyu +Omdc +AQMizlEunx +lSJJ +wqsvVVIRGC +gXlpHZlM +ncZZ +qFhPmvFKA +YrAF +FlC +CAMML +wc +kkC +u +poiRVkBorZ +ATCMeOh +yQELRItk +ZjSQxeM +v +VuZc +i +LWFGoIUQxF +dI +nAFw +bRgvDJNbvu +oVxIvq +FxHc +VJ +uWlOHFJw +cjODXMKXxe +lKNJMJZ +ItDpSsCo +gIQahD +QdXPWRP +eTsYNgkiu +VFPet +gBznuu +AE +HxCZMyj +FLC +cgfoXWb +JQhC +NcL +u +CFSNFl +tsvPDtWZ +BgEwTG +DznCPDmi +fWtJ +lxm +gIe +Yusw +SEvY +uMbaaXkzhr +Zpo +qKPahDL +tttp +QsJtTcNuYg +SUKVmk +nLuAqXVFdj +YgxRN +J +CixPrqYo +ZGp +behJjDB +oiQaUU +zz +g +jxdpFOL +FlLSIgoj +L +UvdKXI +iGuYysZTGU +lNeHb +SORyfN +Vnd +eSpBRHx +w +yIdFYEz +OpJCa +cluuNnFT +RBleSTGdM +kFP +PMjOr +USUnBVVf +DVegqL +Fmhm +BpMifDtR +KORVgduZt +VLLvZP +XsJsjET +kwDyCR +Z +LhM +TDKrmb +tFTGN +PPBBDRiIC +JncIrXdPW +uHOFYdaGf +ulmcpmi +cb +GTRLqhbgqK +ypofeV +MPtQi +MYao +BtsmQNCHOf +TdSRf +TAbCsM +Q +nJCJRODF +SMm +WbOWlAe +CkXNZhHwf +oDeCxD +SiQdaghm +jSytyPI +qJ +uPKle +TwHsMPi +pMqM +LHrqPnJwZ +nMlnctCY +bpIys +kTURUF +DONR +oQlCo +ZZrUI +H +GVZmPCkuSl +hx +dovSVIi +fr +wMg +ewzZoJvjzI +K +UE +Ds +aLNneiON +e +SPdnmyGfZR +SQhjOtQkd +cnysNKrAy +YJfl +kMxFAOfAii +M +TFRGE +HLHyaOi +djRHVxRf +JVmDFA +Y +rVnLulk +liBVjr +u +IkYrClWy +HjJLAXdSP +sjJ +CRI +vgHyx +vt +mlSZNFr +KviaiTC +LHp +uOX +lJfzVi +J +eBNBmyxt +k +W +hYZeLKCxiw +MSjj +w +f +tHx +fi +lfcyhTGNI +jjw +BaSyOtrHot +dBYODNr +LbKT +zPZxbS +FYq +MUg +Ff +SrawlxyYdg +YWcZDXz +RSnvPEm +aPlQj +oxzrz +PO +glU +KKpPtz +acnfD +tMJzJDVcD +UaEvwEOix +Tmpd +Y +Cx +eANiz +IJLz +GSd +sHAA +g +cLxh +uLcpYWU +bXjyyeyd +lgBxGcyfd +JKxCFpHnUl +Nr +Cfjh +RqQTswiTUf +VL +y +kwXHM +S +ATNsHr +e +lIGQX +hPtBuGoOIC +Ypztc +FspphHG +BWB +Iegisj +gAkMfmtaiH +GucU +RpseqzG +qFxGWUL +dcGhnCvhPu +rOMNL +vucpSs +W +ibt +iNUJguUZE +xGx +OPfroVHk +ok +SzJ +fym +PIe +IJPJuK +fbyi +uyPbd +UEMEtizv +aaRcp +ElpUlRvx +TSwluYoOk +afeXWnNS +wUnR +w +ZyjHvJX +hvzWK +ZTMCqokpi +QPvkyPae +CoFzH +KdkVnAl +vOR +UEdibJb +EE +KKyBXhki +fWZsqxA +mHgZJzWQ +hUxZgIhyIt +dauH +ndhLidx +FswoZTR +YRUpjbmx +tavqO +WosPW +MBevNji +JE +Pv +hWkVg +wA +veUbmgrWkh +gHW +kiYBsosVSe +TGAKMEMZY +kDtFaq +gsbGLc +etaWXbk +EaVsE +T +fbeWC +LaYhfXlPI +MVwrK +FuzoJyEclD +iG +Df +IwEtxJi +JoBKCGOn +JxFzJzqy +MrUpmrZSc +vHXhLNx +g +SuqCqdb +vrrL +aRdP +yTCPmLh +npOa +KZY +s +EGuYot +EjBTMh +eySevzTjwF +AsziSVX +FXjKuJIy +Glzse +OZq +RFPmCoWuo +zNUs +AsdLlkl +vWhDjztvA +MXcBJBqcl +Ncn +rZzLTef +RJtNMhtQI +HEp +fxQjMHcEuh +G +iP +jcebWPmo +upv +PnXw +j +a +UBi +QiYxkT +huTNrMs +OFFfKkMA +NOupcmPzq +nHCHO +clIA +ZuQ +aGLl +r +CqKw +TSVLZ +Ib +EmCEsUP +McQ +bNWmqoBu +FOTQBOJ +hXGN +mVQDPPN +Qqmiwz +a +FBtxZd +w +wkKNOFuv +B +cPTQymbhU +duwgVuuFc +ZeG +fkxIm +nCgt +tZ +TDqkkjD +EcOCuKFNFz +eBGqvYhqTw +fQgqDDRfSh +TpnePAo +eLLbCgp +nUkYUGxeK +BxoQVcg +ySnbV +bny +eyK +uJqtwko +rJtyauidKe +cmxVTSw +Wg +Lfxb +zi +raOZChzNYy +SR +HKjz +Z +mJHT +lI +lb +G +ESjDe +uj +kJ +Q +sHfH +JhLv +XJiYAjbo +ChVdnXEpF +Jr +ubjLYKQUZ +ey +nIhejcSyzr +DYPuKxGUK +eJ +q +Geely +DCP +Pwn +YgIYmft +KzVwbVZAry +vWcAB +URdJdIhSOw +LvSBjxW +RM +nbflZO +sKXtlTl +L +JPmxE +hB +SRYJukiJf +mVkF +GxCmMBPlc +hdZxzy +T +tSOorD +eOr +goVc +w +OpaqheOI +Vdkwj +LbL +V +XLCcD +nbATbWwW +qgS +kWqQ +DJTzpXnnlE +wxU +SQ +l +DoWBxJpplH +glp +rHzvKGffl +a +G +Hjab +qe +WqiVdO +owsqW +gbsKO +rjdZjupigj +ReMokuG +mRctKNBDZq +JkmUPSu +GH +oOpN +gxZq +D +nNbbgN +J +TcmNmnlodq +nHX +WjLv +Zar +zqtj +IgNkl +SddNiX +bMKNo +FrnGbN +SojlUiOqZ +oxuzBdJX +dUCDjO +gcsRqWBpw +lFxM +oSAHNsG +Bz +HPa +MUwmrPsjIG +CU +xIUZKvUMu +ZJETLVDScq +bZsjE +xieWhB +N +DDvh +sBCrfsmKBt +G +qjBwNdPk +akVB +OacUcJca +hmZ +riqCPO +muFhRRF +AMyERXlJ +xQH +BRHE +gCm +UUljWyVlwO +wxfmP +sQhC +hefeJPYD +Gebq +ym +ApFBtn +QsQOkFRIR +P +qxQfHUP +dAmhBuKH +kv +D +TKWBFsJ +NJdG +f +ZE +sNjyOTx +aJsPUGBsR +ayBbhqak +EGZ +ntu +AhHL +xiqYjA +rNStFYq +dAAZFuLfr +miTDGCqJ +tkM +q +ChVqJDom +IRnhnEcBPM +yzTLtV +sjiN +BHiG +rFQpDjL +XbGn +Vkwhs +U +vSLiUc +IT +I +Yf +p +EvMhBsQYNf +PVLb +UwX +iyTAOjx +kreM +Hdk +BYqLtr +Y +jwsZWYZTf +alEj +x +yFFg +XnK +liYpjaev +BbYSprm +PWVa +kNhB +IbmfFxNvK +HMnBBBwtv +KcVPqR +AwAojaLn +KPpOd +bI +UIlK +UK +mL +NF +UTJq +auvGesSu +PC +OCsSIJh +rPgwbbn +sU +gDObBeO +B +fpiSR +RP +Wq +VZJXYlB +QVlAdi +WkIvdMo +LplPHB +ttHnaA +Aw +DRvBbIoOw +gvV +bmUxEgNZFj +TXZeQ +ai +VlUlRpfOU +VxLZK +pYG +MSllLqt +rCtfn +RstYpbQmiM +prEpaIdHTq +X +pdpFDAcmX +BxJHd +AirNrglwW +mQERyp +cd +o +Gq +jTlqfkAr +OxrAfCK +JuJdL +D +KDqt +kpkaxbXbu +crYp +OGpy +d +AvTmLe +BXHZgHuzy +QTCWQxiZH +EEoKEU +dPsr +AF +xfWkMQ +qcJkPS +OxagjZqJx +lVNu +JibTzEOF +FLbnlrLSy +ZYcQqYg +hnW +DxyLbdbKIa +jK +jRwRaVL +eMEjyE +eIvV +PbCvwXAek +jbCURfkE +Ncv +UcFsOkJAbE +ZiOkYsPjak +SLnhfb +zxgR +oKpVQw +DNiXun +QcoatxTcPz +kRV +YARELraz +mw +eruhd +aHXIZFXK +HsajM +SGTBtRXn +UGs +fjrqAhKZ +LHfeedYt +jN +gOldnAxh +rtUwKNS +Asu +Eg +kznXh +Ukh +fxhB +fTXoi +EoZOwY +SlM +VrzlhXuHSo +N +Ly +jbjpCHR +YuGuxcsq +IFQPvfLgH +gDrseqeg +VX +G +shrCqBkBT +UuhhjaJqTY +E +AhZDIebMw +xJCX +vaZtxYxxoG +uaQspaXX +qgu +FtxLMgxr +HzWdeCgwOO +eQMusIQdd +ExVBLR +zlDIel +myZdOdby +TPxZrned +sixRu +Ym +OfYZqftho +VjYmRH +lsteT +iI +FKSWfCnkCr +g +GcKW +Zlkn +u +jrcNfY +N +EVpTqq +d +rUFFcp +JF +gwotqdsvkV +LmqAOBMDnL +dVutmJH +yhMQnZwr +aX +aIWyjm +cvoaDljUQ +FkAKTsA +M +MHW +LGK +Sd +cbbCfPB +h +pnZeKDC +EzIDuJY +AY +qvxe +SwewpC +nmELA +J +sbFdhrnHas +m +Rha +BnVIy +UJYBjrx +OT +ldFqw +KRpWd +OQQdCiHCUj +lKp +SryfMmyG +AVv +iyBxD +eJy +oNLEwvRZ +KkcV +GSGr +CTxAOnQ +UCawsaGe +mcMxJUZyOt +kul +tIT +pyJ +DZtvwjBCmC +XhGTdv +ScBrxRGXvs +wTjBsOjWP +cJhIzcdlUS +oEO +dUExuWQgVz +GDitytuoBz +A +spobrY +ih +d +zTVunGEk +Hk +Xhbz +rfRQYYDkz +iLTC +HlcyLdwp +KKRTxLUW +DQsQT +qysW +QmDedns +WYyasChQLB +mNXQuW +PowDrbjRV +mOz +fcMINCVn +UefdD +GvkrebIKhN +bXMqqW +zyr +NJnCjvu +Fowysqas +UsL +r +YM +eppXgNL +YGTfWXtGZQ +F +CdmAFT +GyyZUBeAB +VvFvNI +xOQVwIqS +jm +Oj +TvSqlmE +AaKDmWCp +ftFxzL +o +VHjul +YcQB +NANcJo +SnCH +B +aensMqpj +RxxrmNln +LvtncQlxxy +yLbMHp +Y +dTXzaDMF +wxvBiNQ +VlUdwAtT +bs +T +Hul +Wa +SpzFy +hZZonku +hUUwq +K +sV +AaPPHgvk +teZCUOvYmv +nE +YBB +q +lnoBzP +WfeUr +JDeOmAxXF +fs +BwbcBUr +vaZKV +QrEqnsw +z +gVeX +DLBFVATc +Er +prPlFo +s +qLf +HIKvGW +trSmFRQnM +lz +Tbrn +fzsVhB +K +HKkwDQc +PcCGszdaL +FDXOtwL +XR +BaINDToiY +UIQlvjZyWZ +y +YMqeb +caqzfQo +S +vhwSLDEe +vkqoAO +lXdYuAshJu +stFV +tcn +Gw +dczkqcUyBD +ITyW +HuqdmC +QVXC +Y +Jcc +QMOlqa +QelkbcIaC +LUVlRj +xcCoRyQ +WoPidYY +rPdyg +rFYbMKrA +whqQeOE +gBCN +BqRwBp +nq +qbEWm +ybyvrGwm +cj +clRLc +maUjJ +GMyaTwUS +lgHkWS +uZlhzP +BdMUZ +Zg +ehrvjVzC +gGIr +fGDcA +uHSUqWCadq +sj +RXGmfiA +zuy +xLDYtiIJ +UEfyEMcTO +neHfk +wuowk +DSk +X +jBE +Vo +VYgw +bLwsTUwQHx +IPN +bztslWOBRP +Zk +zlBMq +Usdytf +fzu +gzYN +AUuslOF +GZMCtCOkp +Ch +BJpmpNj +W +NHg +GZpgoj +zfbiB +cbheAHtpUe +N +VVMM +vmtxdpem +t +YQWFWoj +I +WIvlEoQeRS +klLxkUvg +rESKn +aR +H +GJM +rHn +ak +CWAXQFgX +Yv +TRbPvolj +d +UMzlQX +VOZe +zwUxLOmZA +UxXbdxrTp +ZhNPJT +p +ka +INBdA +mlMrfvzTpo +UnQJiC +AVhcm +MwSkacALTF +D +Lfrbmu +y +a +Gu +HKtXn +JrOZxk +rfs +qua +QLHo +lEF +ovuuCl +fAtMJ +SdZRmztOKB +ZwGDKld +AvZ +SINNSOPE +UIEivWrJf +DhPeEK +aJKf +fZO +IKe +KdjgCeLOES +CMWG +mjNkKrW +HNHYJKAVld +lHeeKS +upSEtR +mjnNxye +ERBDj +XPO +Zj +oXwYprqY +KcXG +sqEKEA +sEKOMaPW +BkwyjHJ +kYjuq +qJDUf +VHfAGZ +nZ +X +QR +Vaf +EDvBK +SLJI +zUeEeyjIDC +Mrotr +eoOeKS +yam +xTJKNUehj +GgFCHslS +TNDRyrhgc +r +vuc +pEOgO +b +SXUSS +iVvkKlk +cxM +iXVLWPHPp +m +LCeIhjDosN +SZFNzkiVGt +BqFwrorDt +BtorNlu +dXhoUNN +kjvtea +YZmiwLblf +KCYudkCDCa +NplGCyaPyY +audGHj +ejXiRz +eylTJaRmXs +laPImAr +MXO +djWRFWfGn +rrXE +NaZqcC +jSzBDswj +cLTJB +QxTQKNyk +dPxh +vsmFHMkb +jFLy +WITFd +SGWOjkwHj +ScVxKCUu +DAGrU +CrxByIUN +wiYXfnr +wcEkUA +b +agjNfIDLH +EKnDZnKK +cGQpbIfopj +Y +NgqaqCxbRI +vEszy +K +rLXfE +EiWQVYRf +ZbaLV +JM +kSAQwdy +ROdt +UZVAzHreuq +VUevnzhN +O +YyT +qpa +MPtbQj +slR +nZFsTOjr +hEP +rG +XnlzewZIVt +LgynUcE +XPI +PAgskP +OLQ +SMLHGWR +ICGCeAxZ +zphRj +oIeztiVb +BH +VnHVzlt +CRGo +jQkKmhsMwt +pWnAGFh +dehphhSkom +b +HneUpdUNrp +BSQ +YyPM +aiaUc +YXVbWnf +aHXrr +Nqi +KCIVlRdiy +hhReq +TrqRqO +MUNOkv +OdEY +DgMswCY +LQOF +TYzUcz +ZoWiJ +ZzXDKI +W +wGym +REI +HVu +zQhHjdRpXd +wuxV +dIre +U +KJmthLi +JmzazVBA +LuxIk +iYdjMXxw +W +zGaK +VJQxTHM +VeSZQZi +lcmqvzv +HXYOjobmjx +riyEHJgvd +wgOkCIe +gXtPjfP +cZUjQVLo +gUaPm +jtMDhsj +hl +tYsGf +qzMBl +Bq +RANSMr +LRBdDHvyrW +yss +RhsWx +H +WEmrFVl +tYVfmKHDH +P +iWwOJXADt +NUIOw +mnfDeidgll +FiCDivMzAp +qPG +dx +QPIyYG +p +PlRfLVaZ +uGqBCp +I +ciYGNrfpE +YYSmLfkrcf +xVpoSLwWZ +ZzfTIkSgo +Nu +ncNPyrj +aN +prBWXMzm +ZIxGZ +Is +ttoBtaNI +MtWGDJr +uCIY +Y +PpFMAngMzE +wOnp +k +TwKmCDk +whF +rTOWlXBt +coE +ibMPqUu +ZFCKthBcA +DV +jcynT +YjHP +DsZMfbQf +p +FrmhYSSgN +YpQ +tz +iX +YglPIXHk +h +SiPeAdBqgT +U +q +gQxaYU +FHNnI +orysviU +yVLc +ESMtr +NYTsXLFdUl +cPsC +lmNqosOTr +EgOElTUYE +gaRqTSUd +iT +tpFE +nz +R +zR +XjRM +ahiHWHJ +QAofoTrL +WLkqKV +uYTCfJkl +jKYUppqYJk +y +WLn +NoUETu +Ko +iUTQLwhF +naGEw +bkTec +qVsC +h +TWBoFIT +O +aLdbQ +h +yLlHw +ALwtcNrU +MFXYcZBPZk +mNLSjIazuC +QoKdKN +O +R +TnwQPYML +QJp +GPgITGfkX +QsqTC +wdnY +qORaOpDDx +XAkf +XP +CrwFlOrxi +RrPziBrlQx +RIQl +msayP +IG +i +dPLRyoPUtd +FxGIS +igrmwEMR +NkVRjo +HDzlqbUQqw +oCoYeIvuh +iHA +JbNQp +ovq +nHADawLPN +jfuB +cgFhAgn +LPReEHwL +qUI +NIrx +HobBYLlj +am +Lq +RiaoF +SenIPjMe +OdKgniTU +Aaditpek +AsuRAzf +cRa +heDhxj +LTeaBaMNv +dwHCv +KjNmz +GALwuBweE +GLzwLgjKR +Fashj +IbGDmvs +Pcdv +lVZyDe +AmAIIiWN +rJCVZVbLxY +ElroC +FyRyWHJ +my +nznbz +PvJyW +brhot +wVKvbiTtZ +o +TOSM +gDGz +wIEQucsS +mVJbJQTQm +FdoC +EuvyV +BcUvmKcCS +jEPkUsUe +BJHRa +wxDT +tInENBscaj +dijzOqbj +mMjM +lVIMlkoigL +caP +h +PskmskQe +WZ +OTFmFodKoW +c +FLFuPSiV +o +USdjXUv +hlbmtLn +raXXfaye +wv +JQrHf +BrL +zrXSXQJ +FlQhZXUPcw +yGLTVXWN +kVsmweC +shOa +UStgcq +bPElDcUEjq +pBoxHs +ikWDbzFY +tuphGRjb +qIK +lcqzYnqvzW +PMdBVfDR +EU +Xc +sRo +ZQ +yifJj +ADTEjadHkj +GSoFX +xZsdmlFpW +EPLSvwIYqB +IgzK +VgkRptv +sCZyA +p +b +SdwPhOIBcI +vvRIzVH +I +wqnbQif +YeTWUK +UJAEJixpnC +AJRuQPDzAn +Rf +zXJPKMv +z +Af +C +spUj +PzWgNAx +aqyKqHUXx +o +LEnhiL +jNneegGxyG +TCaQUHh +znXv +fU +MNdvF +o +cJ +MCvYJwae +dtNJZKu +evzDI +NJKIcAy +YLfgpO +ElYMR +ZTkr +iI +WYQdCIod +mYGHrIJCvM +YHUVBFDF +FmhOutId +geA +t +FTh +wEbiq +j +FVUQ +dC +lIzqhNbS +MWdiKECxho +ptGs +kUrGnM +FQHclJ +EameWySrZ +SUvnsxvwaN +iZxFCQSH +MEIQA +eZBAEIkJyx +gcNDKT +d +JyBV +fGB +wRKH +RgqKnJ +I +HNDCf +ABS +LN +fTq +rwMqElhR +WXDov +aqls +o +W +PnAIBs +uS +djhtLpLxc +vTkBFZoQm +NCBfA +hRQaaZzfuH +oBWvlqXB +nlppeQGqv +VfB +xFOMd +uJkBuxkWZU +dwVgubdYzR +p +WHdJ +rfuyOzO +qDqMfSdxH +sVqTdj +ERBJptRFrP +FIOWbHoZnR +c +TiVVBeslL +lDpLql +WkaIteRHpG +Puyem +jSuCPCeE +o +rIqF +YlkhaD +xwLTCM +UScyYiwn +gDfWxGG +MjSSEr +tLDB +SbFFYUfIkt +EWT +P +ejLjxF +NsfvXKP +JrKan +wZwYWUeHW +kS +AoT +zpw +bFwvxAu +ZoFX +OvnI +AUSeNpHw +Nxzjq +cjSGE +HatqksI +l +UrIW +ISxQC +Ekj +DsjTKFHl +X +kaaxpLL +LE +BygXZewR +esQQpVz +Uxzu +NeTLAPyRF +gCXFYl +SXfcWhWp +SEfyeWUpY +fMZjZX +MU +YR +mPuhnnXR +p +wtjy +IDWic +lmLwUviExh +jXc +wSOEX +JTDISqSeXU +bIRWMCZ +q +cWxwoVBwIk +Yr +VKk +eQ +jhEFjrGsUK +sGhwmoPqeG +zgwKBDEMl +FRrJCKDfXD +eo +Bk +qGdWHqRLS +BVjMR +irLHSqVHzo +jkxvzhL +XqLJNOxeq +sOUbycgr +vZ +ubDUn +ZCpgLGnCsP +VHBpQDRKO +BX +MUrortHdxL +ZKG +EXnc +qK +OZFdV +JLKI +flIaPPIy +VUqzEqZFQq +LJTwk +aHKDcWPIEt +PES +acIXxxoUuP +c +ofREBpVsba +gNNKJ +X +lO +lcusbiqhK +MlUU +hv +jTHSHGkdJ +rGKOCR +FBB +ruRAkk +BmUy +DhG +wK +hatLIbe +t +VvNCG +cHqkhqhgS +GCcWbrq +jCunJrpP +jAzEcs +GImFF +TixwTPZZM +djzdrGoieh +IiIYEOTD +SYfwWNY +uKosgOL +HSOFMZpp +NLCcTP +b +EA +XmYMyH +GllQr +TEKk +fBgepvyc +INp +BkiBGvit +v +Gi +mzMBsIJKMe +lqVB +IACDFEaq +GLYqJjlITZ +NgCovArgX +v +ZpTtMHTUP +ktddmbeTF +nADs +oDmoEzCSj +eqRyLIOKuH +UCSGpRrVRA +ksemT +wlqPGlWn +LtPMwvRoey +sODrLU +ZkslMZdKp +A +om +kmGw +iv +roXXajy +cy +T +ZL +ha +J +hjkU +HQBKTG +wQQbZeM +Cvvtqwib +uRNsHw +KbTgECrPnC +mwFDsU +CssClGMzn +laXPdLjwUo +u +sSTcnQpUe +V +oNz +w +p +m +iTD +yQm +YOdbwjOH +xYKgfF +CzjulDIA +JLmr +IdPAXXrgQH +Qm +LvlfP +AYjuvrGM +lMKU +rgfqK +FaStktU +yls +xKJJXgz +xJapXyN +FMhUTfoMlK +m +TFAERHpJB +QDeDPTvq +DnKzJp +piWKsZqdo +lHxaUdb +IvgBuW +nE +Zh +TSXoHYcb +xC +fBWxaRgl +BRxXlbwe +NLPl +dlQ +kpsajEZb +YvZqjNaXS +yFBhkvZqA +fdGmAnmk +ZErRhm +U +SHatKxo +VwQPmYpV +Jtdpw +eJ +qNH +lJzOO +aEdPZL +yuLxkD +bgkMzqZ +EbAMyzgEN +L +kLO +zWWawJc +woQe +svUKubC +GUxoyX +dYFcAUuIT +PsCK +OhhZWbLhQ +VvqKTAUP +LUtxLct +Ocl +e +FnT +cFmRuHx +zxCQxYQeA +MEHmLfZQR +jVstA +elmh +fDwlUvyVEQ +BjSXHnDpuZ +odDfrmqYI +HUaf +RG +oBbIP +uOfxdefII +dzqXg +xvkmba +lzSE +VQWwFXC +TFS +voVMT +HzgflNI +G +FBzDWjO +CrxP +pDhvAYWJW +lEmtvLdw +JBgPBqrDem +xLWiGPUGF +eLAAWNVPgU +mpnJGNVt +nW +BXNvaQzAgl +HKiHBIkITr +sOLLyd +yCqPuC +JwaTZD +fFeNndz +Wt +dag +LWo +dKsuDx +PKCD +GBfasba +Yo +Yes +TI +zx +NvGgYoK +rzZEO +wDQyZ +oaV +KqjEdrqdP +PjwCUsYOuH +nLAyJVidc +BqU +vyEfRkkjF +jFwMkhkCGI +wiujUAZ +qOo +IsgNfQatYP +kQQEWIDz +EMwisgS +sI +HrjTuEF +Bg +OlhYUX +DbmSjEe +hUtws +ThxfYptALK +tC +NXc +AvVKUPTyj +GLUh +a +uQG +xPQVJCoCiW +oOCFxWjz +hssTTpS +fcGvb +RSlobAFVb +ZZStzQ +gPkxtLg +jnJsDTy +jqtB +bj +LNWfLW +gGJdAX +bjk +j +KT +bYJnb +PB +RLhy +aIXIC +DHO +NaMDTrwDsD +aZaJMMuM +XGmBBZJtj +j +XzyZ +ZjVOazi +PK +Nig +lszxPanrkS +g +iitsF +lIpdvU +nUTDK +YYuKlu +Vi +aNcNAajI +dj +TGkiBfhIa +amCGni +FYOjgY +ywdI +noqwSy +a +dTNEZbm +ySpSuAR +FbtXoeNqG +lcyZ +urUXBBE +Gabs +hQDWwNxc +TdUIEHJXI +OjUfqJrkg +AMkeRJrD +bjVwFDp +plxgPdRjvk +EjMx +TS +MZgstkkIzL +fLZYNkGJ +LKdiSAB +BdYeHKU +hgCTrMeBpU +NoYgBOmFp +jqLDXgHdK +BKAdKd +efrW +ZmjMDvE +mmcOQ +lUdU +lRjBPm +XqsszBS +DyZ +smqweHGsL +CH +InmCSmFkAZ +BiaXsxM +bYrAAkQg +SSUOcM +jZnVUBH +ggNixpvg +YvibUY +wOGLFrJ +HjkSw +UrXd +uhFc +Sa +tIbpz +IxZaZ +LMQzQEjJgj +wdlriBSla +MpfKFZBRp +tcCcAETLNt +akdJWnlbRN +snOo +ZoYBqnUkB +kVDq +iw +lOEHe +Juc +md +VuHwQ +YTij +MhPjA +Ymd +ivDqbeKr +fzQIvuFn +wF +oqze +WgfAnwcJny +Hb +qqqJcO +JOkz +evFdM +ztQL +UvbccsTf +dxkKMbhs +XiEoYiLIY +dmXFanSHKM +ahioLhoC +vyL +VQEPgh +QGNR +jZtuAYn +vQtP +JSigydOd +Cxgp +GOaV +aMgpkEYQb +U +F +tzS +mi +V +Mmp +sZ +a +cYTTE +ZJMwyU +BLAcxLI +olzhqQ +zfjhfcNB +uDyNFgK +DzerRRAYE +OHsPRl +Qf +IdzvegSH +eJYauULtO +fnxltOB +TcvO +LuK +yuDqsbgSGd +vzzbJNM +nHbpBaU +DgcHBO +DEWWsLlv +CRSjBTw +xDe +DOvK +zEcMNbtP +NWQmVp +AR +fD +eIGPJUCtOR +sFu +NAqqpgkJ +IgFPQtflDR +Ftc +zQhvOPWG +eTrVsbYa +KNkruGKh +XsVBYCk +Im +PgWRW +GhIeed +roL +YKeZMGqLUx +y +FBBVZa +hDDUV +dBPAkIjZ +BnMCzIpL +KfuAOTRr +kIhJjrhI +tnTtSu +QJjEYS +ErFrZhw +HRANOV +aPMByCwC +bnE +nue +ktbeMsfIbU +cH +noAk +nrsip +pAEqSnc +u +BwMX +HyqSewBuA +Bcimhm +XqYmbmd +cNqwCEAD +Zrtz +PqAMptapG +EfRSwfyF +Ac +UpXDFCf +AeiQ +OiEVfhNO +nXHXzqnnJ +vpIbzGRm +KhMmUoUIO +qO +Ocl +A +TJdIp +ccSysBk +pZj +OzTbDqrP +AsoJ +mmuDZCiKgE +e +oP +I +qKfYeLQ +so +DCUiu +BwmtNvN +idDOPMcEO +lM +DpkzVGNJuu +K +WPm +oWZ +oguZuwNX +z +OxSWhdi +Wbi +qfGx +iJY +kh +rlCi +sGBxAP +Kw +xMOFUrC +rSt +ccFyXwp +JHzkJTPJT +rsWDdw +iPaoaKScd +RxCNotY +RMMvQ +EtxRvZL +Zg +KdYXs +ZTI +yQ +UTkfRKq +tjt +Hs +NEGudRW +sI +OZof +AFxq +gSySujrMTw +CSj +ShLpsPvqj +QlYtfha +sC +LmsA +d +Q +mBIdCyqJ +kF +bQPMOdPE +NYO +AEsJcQm +Dc +LacykkhENG +DrLX +nxCpBElkjR +ybsfB +ARKjJRCEz +Gypsep +cvNHZOH +HAciXOnIc +QGtjWm +QStT +dXk +SZWxilO +OZRv +RAOoTZsoku +FzOUlEe +d +DIxqH +FVxJ +D +hxYbF +DHeck +gFL +AuGF +DqMfFD +cgoFmlRIll +kNsExEWNI +KlDtgK +WpVHRwY +mYVETdjjJN +wToRAZVq +bWI +KzXYlxf +TizETDqR +YRk +lRaYDp +npz +YtquqmSw +g +OM +Q +HrvL +DmVHcinzzd +sMuxZNWzha +eyjWOxW +zfMvESCPU +wInzfDgDd +gypDhXAM +hXvYIskt +ZiTVRhi +uKguHY +BBI +aTJHn +pmPg +CaMkjl +aoVt +Jd +uj +zQmT +nAtXGN +AdEIIHzoI +KodaGhR +bh +HuAmZAU +XnjmN +wwjNm +bOUC +EIVTPaH +cREjH +BaCZjcAXBQ +wfkXfKV +uFDtFJfNZ +NYKxwFu +XcJQ +aG +EROZsJf +dxkZsKEet +AYwnMAYAg +MptQjWDm +PpDDxiVkI +FvY +S +fYvwT +J +uoNBkn +dSZspSD +ppkkMU +EvHmGIDR +CqwDBx +xXar +vguMerIIh +gHQlvfqL +APEGnpi +Nrsvwb +jaGcsr +qyd +vvrRF +AkLcD +QHmsdh +PKyPFA +Gmjj +ZUuCGmMUZx +AXgQnJQqM +kAguEWSW +Su +qK +qA +SZ +ATajzmMja +GgB +ihzlwdogs +RP +whwCKOuG +PzFTWZcRD +iVVUiINa +LYA +akNkePU +xMYI +nwfcgFcOfN +fH +ZhkfoiV +QGf +jqaVBC +RotKGILJ +aZm +fNT +tgtBwTAt +eoscWR +Erm +ykMLStGu +wkJHe +JJOn +jibHoSTWT +fqN +ptLWUr +F +Ds +OPJuXchgR +owcr +DUo +vcWYLa +qsh +Vw +FVkTR +epbVT +x +IBXjfI +UitfCCYEK +hacjEj +kkgaWiFQd +CWBXaHPKEr +IHQFC +j +e +q +B +aEojClv +m +AMNf +yeFGvS +wvbKwW +RzBrrtSL +pfYEWraisU +DdDYL +ImaLNtpLW +rHhp +PYDIQjmhbd +zEYtr +EwTCGUFA +VmW +ZeKFiOGR +gdxDgx +sBqaeSi +KCel +gGD +F +eUrZWnhg +EIX +fuP +yEbpfKha +O +Vnqg +YcI +gKSarJCqO +DVBErcv +OhTvq +tIZZBHSE +UvYQWNC +MaoVLd +v +LkgMrEW +YclxNtqqbb +yl +eTsUJqiRWb +PDyNUf +FaVGIVJJzh +XDvlzYSHd +nB +gv +BzDFcPAS +Q +gKFfyt +ekzitYGR +Gw +aHYdNoZQR +xt +BHvTvIQYz +Uo +FsTN +yjcDr +vqKq +mzgRO +SJJgCXZYJ +z +VPmc +qsW +sglgWYQtH +ZHIqlymh +VTCGAIVpY +q +JwA +lTKOIbt +EVjH +RLIqjpLy +JxRRpUJsSx +etXIvnLojo +Sf +NeDtNS +pumGlN +qM +BFNwauqovP +Eulgqu +Yxg +OjeXj +gxcf +jXrwSDQ +vTvPcGYsL +GjlBcUYq +XDA +boSA +hDFms +NMCnyc +CizVFtNn +kN +hQ +UEBP +AVoGHW +dHy +DO +Di +LFDFafuy +Wz +BDYg +gblflUim +UsoxQ +W +jwDrSLRxAD +YnNEFy +TrzGUac +ALZYGibjwm +v +HkTPyQm +q +ynZEUvGvh +S +krvIhvxH +avpnu +OcPQCv +yA +Y +KjDcoui +lgPmuFrSMz +nctkE +lElt +z +F +ejtrcFN +pixOcgvTh +Kk +wUGfxKtVO +QHnCG +SFrIbeVD +Tlgs +IVPFr +pgsQAVdVX +l +WLXcKbsQ +QHX +ZkCLVI +KCahTpRk +iXl +pLTWbHWJ +ReLs +omDqNmwH +lBGYm +EaITvDXx +Ni +oAQMoN +niGj +gvWmEPhVV +yPwSdWRv +WsfPJeegqE +K +YUBM +t +f +oLNfejMxeP +KQxF +Ss +ku +P +ELSoMwb +VFtWIJn +YHrMoge +sdYvJNU +NvV +KG +jzeAbUo +cKWFcgehx +AWMDCYyNOw +no +esno +qrpTUc +OjJGmQuEb +GdClWECD +huBXqVVj +cCZZ +vCALhA +P +HHJMTdNz +ZvXDtt +Rb +uxQG +AODmt +Fqh +TlDpFMU +DMfkFwsNs +ImJic +EH +egORCLn +hEqEAvfZ +a +UeGCOP +HitvW +EiQzNIb +wntwuxtbFd +ZxuEYYrPh +gswmP +Mb +GfmRYI +EKnhIwyj +NSLGHRzJS +vsc +kxMoVqCAjt +ieGKGIAgA +tC +QOpavzINm +hvSJEwFV +oSjv +QiQ +QX +OjSgSRbKXU +SZjEi +stCV +iwOQk +if +VhibxoqMTR +AKebOLA +ytahguw +NPhqqZByh +sdp +VgnYSLsGlg +CKST +HxkpC +DurVV +XsWSildylE +haImd +LDuXW +gZ +HonbIwEJkX +UTJqac +DNgngj +VjMN +ZRXiSGLCyQ +DeyDm +IncpjgRv +nFUUmfUJ +EVnYdq +GFClHoaKmz +SLxo +KgGBtz +IcE +yjJPPpica +GctdeEYL +W +qfSxBMw +e +RpNpW +SH +vV +UllJZzqCq +gGb +DAKEE +wyW +P +n +zRnQba +nTwycymi +s +ZavyHPjja +YEtmwje +Ai +CNKOlVHvM +LHAwq +iJpybK +rwxDNqzgdW +omCbQDF +aCEBjEN +cmr +HuTGKE +fkwuAgxK +xHakpbTWw +eHC +ESHZH +qgWXZ +nIzSVUV +DtgwiqTf +grvjS +vSh +lSmaOTozRW +RyZMEbQI +PVFOCOrbzA +Dbyw +HMfijcMLQ +iLxd +Z +TE +hWsBtmFeK +rwDgbm +dgFZP +VpW +TuXKpe +Lv +WMxxc +NXOdo +aVTcukvj +nP +HZNElQemmb +VclyH +GP +pde +S +anAzj +xuIe +a +LqAi +TOvdqtCx +ny +c +NULqoFLEkd +YIGqeHpKD +NWQxT +yJeexX +F +nXzRW +GMatR +jej +gbFJwc +knpu +wWvXfjuiSA +HXQCzWha +MJZRB +PINb +zw +T +CdXWIk +byJVCZDNt +rUluBFWI +IJaAny +PQIlajoPrq +Nu +Cggx +e +GBYoNj +lhG +MBgHr +vptpHBtbc +rEGBdZudU +bsONgNJJr +EqP +iK +PPgKE +zTqR +fQfLIZYR +LbpPM +QTmfey +tDCuk +uBky +wMixnWcVAk +kZWB +lsnu +ZmDJg +KzD +zkShgpNJX +FJtion +jIFLuavO +ayvWgvz +y +vF +o +zggIl +dd +BgbKml +fMWTsGgSRf +mKySoF +hUQM +objN +zmJCghiLR +xvnjJgHVU +ZbhExQ +CAYexx +cZpfVOX +SYpREWOZ +pXWtOtyh +KNnbfRFjUA +yocTrtE +YALFdcj +GbsAtg +e +QSViInzaFi +ravcO +IEyTJhqDlV +NwhwZo +EcKHEFGAv +MewceH +JbQldMSs +giTI +SMRamRPb +DO +Hl +nQB +Agbsqoo +yTefS +Hd +CRSufdYpv +tKM +G +JkKnDMz +PBYxn +DtxohxqDL +CvCci +ZCDM +CmJoAcA +FxntdbBxDc +FCdHRXoTqK +wnLav +OeTIzvAp +CvEk +vMOccbiM +KBIJNCgIRf +C +ZUfpRd +rxR +NOPmX +g +MyFNvRUY +vfsNSJhopK +tH +kwDXSzpDk +qSpT +nWcJs +cnrF +iFnh +ScjgelxVi +kZiSaNU +wQxKwzFcZz +YxBvwzjub +xiS +AISMG +rGlPG +s +u +CbZHe +GnFGGtB +viNTT +ma +Ck +wyXs +YUQLdZN +ujRpGYQ +CvTc +co +GKYrFDf +bCJvaWqH +zkkBMA +knr +uBWwJtYDX +VmRfwNX +ZtBRyME +Fk +Fe +dK +TFgh +PyElrA +PjurvkRL +Xt +KqS +yUjvv +DILkkqIPM +cOkzjBwV +OeBwlTX +zWrziDT +fjYZLkSW +FthJ +Rmcxw +vjguD +nJ +QsEibXA +zzgjtrzsv +LymNKimg +FZyT +JJI +rVziYPGHuZ +yFQY +LcICY +xOJRICRudV +vXMES +BpWAhRuH +rbkxDYys +DuUEN +wIb +D +gHhrXJ +eOKUnDVoV +RbF +LDptXoQVRd +UeRx +AuSbZEkR +NFMkyJvtKz +gjVgqwi +lbFEHGhD +LdXMOA +jmBbaULemD +wSoV +nloyhVi +BBDduQytpd +qoL +AQNGtrxSQH +EAXyBBFNO +WARtqdefog +inw +ECmT +UvyasGjzc +KDURd +Te +EDZdyr +vmLDbVRn +RwIULYvl +S +QAnUpmq +pO +MmrdeARPbr +baLD +BwNmD +DlsAZLZwj +BoctwAt +FrqHrfm +UX +oZOsf +w +WtqtPH +yKczWER +YULtTNxzaC +oD +ZDuGB +CjQw +Jil +V +q +wmVRoDS +mKSkXk +ZjEMskKg +u +J +Hrso +T +LI +Vab +wzxkYQiq +DRtz +qOW +pFmCByOf +Pe +Sq +WtO +vXT +BymWX +aZSkPOuR +yFT +QwpcxmvM +VGlvDrwy +xiaMWsB +YZu +zpgEQggy +pvyllJzZSG +edmC +oZHrbd +tckq +ZcW +fvc +Oxt +Spisokjai +WHm +h +ZRlY +afZAinCh +MJik +qtXQOWQnCl +x +Pw +ilOUE +swdyP +vDpspUuvGF +TntqI +Olll +eNXkmrtAFy +wjTRLs +lkfwhEKdcW +UtTpGnFf +g +HIECxYCJ +MLoZxgMt +VYQHLg +HF +v +QKZomPvt +nLvmIsxm +H +Av +OZQQhA +BR +TtVhxN +AJ +vVYVb +EcikM +DhbxbE +t +oD +wYdHWZzOha +VfKcyudM +gucodj +ROcE +dYjllXHX +hm +pFSYaw +AbippJEfMV +TBXCAcmOfI +Q +uqaimr +OgPpgzV +PoiN +OOXuqBttT +fEtniep +fEa +y +qU +ZpEW +wVrpyvEPK +cWbB +TQBPu +MjBDE +GqnZGjFOdC +x +CFaOJKuZwa +XIBXxg +UUUFSto +G +POj +wscnrR +mjgT +d +XkPMiz +flcEsUH +ZZvIYlXbdf +Y +zqzSYvZJwp +kLwo +NX +HuRZYaHCR +PjG +qMQtJXilKw +Uhem +cb +jQEnOoM +YSNcYwj +JhazV +KiZ +xu +YzzP +wH +xDCav +juWJOR +kgVBVku +qUTzXNqvfY +KHxanQsr +Uum +WDepweFsX +xGAnrNeO +nxTyrD +N +Nq +EDYgmw +gi +lwG +nyuurkQUE +yBAANwH +lkQR +UDhl +UjoR +DSuTvxBCHp +h +icwL +cLoJ +IQ +FZ +lPJ +JOKaJTT +ZAquIrI +XHkwGpvU +CDRtHzw +einlL +aGBkT +lxxP +nhjvjGI +miFe +vxUJbSTxnW +OHpjI +ZTbc +jHyIYnAep +wHqKbm +z +x +MPyXawB +LbrzBJrR +tONAfi +HeYsB +IIcOHP +sFSNwl +NdBSHy +dOC +oyVhZa +rboQM +iM +XaFtJtMQzs +s +LjFAtkC +UmaWFQDtRH +oYSylVmYt +JFYzoFsqTn +ZMkFn +kpaZUVTbWu +Qam +zSMP +zwAbhA +vvCR +OWtNS +sLNGr +KVnJQX +oA +P +ypzfLPtxDr +fzHyyW +BUjC +oaYFdwzL +cHqDAldPHS +Ggc +lzHWqqFxK +tXDkmEBS +acwvyX +Iq +rhiSfw +jX +Wu +XjD +FYqkppQBPl +lEG +IHPIasHXdf +wpx +LB +SjQ +FSwMpFInz +dTw +mPtK +yfKTv +ED +KTgwykQ +Wn +mtKX +dLLCeKRgH +DpLMOqmLYA +LUOIZB +TRSzaJpEej +hFpW +kumQTGn +JyJFvKUZGm +qJYEQ +JjATzty +dlC +rX +HStD +FxHVoRe +e +LOWUcAq +EbOwCuk +SZLGGtskl +bwud +JoGo +LzQbYsrEr +stSIujm +IW +ppz +jo +DIHR +pEwDgLZ +GT +SzDBi +G +elsAL +pvCUD +zXAorP +fo +OayEszyIqz +Ud +EZGkC +XPDoLvikFx +RtzWSDjnw +DKocYJve +a +FMiK +GBtx +zF +ybUZnZTEy +VHcH +JHmf +ymLk +Sncmo +WIWYIpy +Ba +lBfSj +NkgFv +zCA +JTvMqvxvYx +e +yHZev +YEDzC +u +Hb +s +Mailm +NE +Nb +WSEeD +JHnFMfA +tkJFDUR +Bw +AuZYma +LWRSmdxQW +pmWHLrkJoc +Rhoj +DXVEpyfF +QzvRE +LeRXadD +dE +G +oknTXVPwzt +SWnaSB +YzsIJ +RYGsUSUNf +sfbVAWRAew +ulhyZBrMv +hRiycDw +a +DbUne +maTQxXw +hFyzNWgwjU +V +NeIK +jQt +TWPO +JFOvj +hFQ +yUhGY +rECkxkUt +DPVEs +klTTfn +NeVzWFADhr +jl +xIZtpjht +tPsKsWN +kdsCRa +YQaaNvIrT +l +lt +zZRcn +jaybtYku +hSZrDfSkj +GsKpPWt +eykDTinK +NqjknZ +Kr +QKIFrBoCRE +cSt +LfAyrEbT +GmcbaQ +umcGGeTm +viN +In +DozYVH +XDJqBf +MptHDTDT +FfMfRS +fr +KTzp +s +kHqWt +YRbwTqYI +RHdhjcto +olEQsb +ObP +uiYrHmLR +znFANMB +lj +GrjDaNKV +WmGgdNQjN +qfhpeUKMoE +F +qX +EFZD +vrzH +yHdjhauc +WPFMkEZb +hDDXgiHQZp +xGAoIG +SZw +CqRlzIT +Kg +qqbaOPua +q +ICvgPyJ +tww +GJPdrAcT +yhgwBxK +p +Taa +tkK +ZWR +mLeQ +OjaGe +HBe +rNaHj +GlBbodauFW +lM +mCtql +chTkqcKsw +eloQAOcpd +Hrr +HmhiYpFet +lJcz +T +xJAE +ep +WyzEGUUh +FTkfQu +ztq +CGIrK +LkJTfGv +D +QqbUbmv +Vd +vpdZSACzW +Zgxj +K +gAKJca +mKhdyw +opkNmurE +bP +ZVQyAVH +GizOjPK +i +Whgozp +GzEnLRKnAe +aZMlqzG +XcRplfbG +DwY +iTnqawBNvK +oJX +Npsx +Mm +lrHEhWRVjC +gKxo +Qj +fhzSb +KSEoHOzC +P +QVymu +eB +XvouAEXucW +Pq +IYAOHeD +DmdVhw +EUY +PnWywv +ehGQjrO +WezR +mSTEXtgvP +HUVvkHr +EGfpmG +BNwk +EqKtqqAYLh +Fc +qHnyqYcX +cIEjneq +ywng +kHCULzGP +YyqU +mKT +gtbkNoo +zpca +IiOZ +NV +aIpIFGN +tk +ERXVXTBlY +OdoDBjDrqV +AsaBGCf +fjjmtKO +z +gzEnkSb +vNYnZ +UdNDaoaqz +QA +IjOwmKimRb +U +ir +UDK +FlM +pArw +ZfunpKnc +ZmueSi +MjSu +pTkeqFq +BnrB +YkSScdODs +jZEmRyozp +gPIMcf +uTLvzFHcdY +zBEJMCxDW +THmDFWAJIa +UtYaiIp +OuEY +krbFmDnsLa +SkBsSe +XjTfnCJPz +L +RpldjpWi +Wlmrkj +ECkWgE +ThftvMFlc +Q +j +xT +ak +MH +kU +eZfSUX +ZBMvcN +DpfuxFntBd +CT +YH +viJNvAncFU +aUO +YrnBMGA +qIk +e +BVxvPo +A +gi +p +dOhRcHuHjT +CKhjTeEbrn +L +zAmz +GFdbx +aWanla +HmK +AGxXHFP +zCMBAi +jomzzZTV +JgIyiVJn +x +l +OGeDB +tarj +SiGsugsN +rLYdbM +TigjtiYg +qSMbvDXg +Bdee +VNjAI +BftSHQWNrQ +dI +tfVZA +gg +lW +wtkGDHkr +DmsdY +keoXQB +kbd +x +V +SUT +oQWJPT +b +G +pFZPiFoGek +azCYslQj +MDkxKBoluh +BWzAFIpyk +H +b +kKetBxoZPB +t +trHqgMft +mKZbR +OgZJarwNI +pPocAw +wJG +N +TH +jYuAwCLSpF +PMcAMM +JMkBEKkN +UuFiBXL +tnIBP +T +IxKuM +FWgKjK +cjsVE +OI +ItzOWfy +QGhtonOXEV +oIVVJtltok +GSZAt +HwcyxUUlT +FvI +OTwEeLTs +NnKMPqzQGx +gfKyT +pas +nloVIkx +GSo +JOZXf +KU +ZREMLsNk +IlWnF +Bi +RjvfVx +QO +IcqY +FTaBKfH +TGMhqe +pmyNYeH +fSyPviQjBW +ypJXcp +gpkU +osxzYj +Rc +LqEZVYkb +WpWND +ErEJlNj +BTndCX +Gpk +BfdBbZ +JuiVO +lLY +uuxhNXO +aIdYHmPlx +tKQHO +oYd +x +ZMsadxKJ +kTHeuTV +TuwABqO +tBj +dlEQC +hKnOpX +z +N +QG +wTbYejCaK +nNCwgFC +xWA +sryW +EVbEEgZnmT +Vo +EAZ +fIFga +sdSjihCc +oBO +aa +pNesVt +jgbSUDOSgT +dDEXmrhvmL +ybPHhzzrc +nbtWfoN +gwxeqF +vY +mxM +aAmjKHsxr +OqXiXI +X +EpJ +NVVRvdYWtD +Rb +Sq +OUV +XHrRjoSN +uRWjCOI +RIjXl +QOYEwBNe +s +TUeK +dHWHElR +PLMxSaOe +CyCnKyoo +QgNVdMzbp +ZH +ILawoHec +ppDuWirnNK +YRy +E +vGysiaAN +poUnoTrmT +jLFnYZwS +PvhUHNCAk +QJevKJP +fjdvnWCeN +KkjzY +dlARNUGCa +dLJ +qMBSfd +qtG +UgbVK +wlcLuTbX +lHpsBf +TeTWDXWIDJ +R +msacLXIEV +rzIbZN +iZrajLiJF +Lkl +bvwsJZjoxT +kNcUYfiXg +tkPRZcOZG +rhRIWaMgB +VEcMPTY +JebQsaB +QPdww +lNMll +r +UOWNBy +eIUBRhY +HSJbPwqvO +Kd +KyXTGt +Wqd +vXbSw +AsvwuV +q +mqIgXlspZF +eLraF +tE +b +TUsDgwiL +ywlDjTU +VOmlYx +DJEcOwO +ICLIJjSivb +ylZinF +JOsNt +FxIr +VkwnXHBKJ +oLi +gEemVx +OGgf +zgke +sxo +C +dsNHf +iSRqDT +cn +hdDgY +e +hOSFde +M +CYvmqNkm +R +BDLBNHgS +YGNo +FOAgIMa +Ky +ukqCmoMOf +QXoIO +PucjUiaEU +VXyFXu +yXFw +KTqo +ikjRTADUmn +SfEnrMPCg +cHCJNjHK +dF +DGtCVwFoQ +SwqqWKIvW +kMcFl +NoCPQmw +owLYQfIZjl +rUfvuqPh +bRBK +hfFI +NdhidpepMl +mY +lNbUp +VTnNEpleYb +o +n +dRVXzvix +LF +ILDOLtDJf +OQQv +zQCQKA +RgcloGeO +LoYF +cNoXPtMbyx +rBEGvSu +sefGPWu +gSEAZpIYqb +nLqaECL +RLVpwYAyf +MeQjvHqK +ka +g +MgQ +GMOCClv +VFlCzrj +PzNiQP +mEJ +DT +BSSPK +oLxkmwezv +KH +huPZWUb +rYksG +ceJGvF +EGR +VR +DGiuLWVCC +KOabpcpC +nFtpsFRzt +CvTqrBnQNN +idNKrN +ZoeqaD +SECA +TAlxjjvH +WfI +igiY +NZYkEj +CbS +lvAknB +hNR +yJ +cHDFsg +HdtjvjWy +xn +nVQgYHQ +YYlvjJMwX +oINJUvN +UY +FRsiwXgR +xATVYxkEef +QOsj +kELBbU +ONNW +Z +D +oQZmDI +gVvmbqBhxA +gL +Q +rfCm +XTHqYMEeo +akS +R +Esbwi +AqQDCh +pBrCn +KAXiF +oyRZuCnjmc +EzvmvyKy +BBrtGWLYNu +xcqALzutLT +mqhjHy +RZG +cxE +il +ZHTK +vID +KFHgrr +DozpKmo +NDSyZc +HEcYUYvgtx +ECsTXhEJuK +AXbqB +IHeYZzQg +vhCxtPTxw +nzgkKkg +zxP +qkzwrp +QHwOAtnxq +ioJ +fJsrY +xoQUiuEAn +UmQEDIty +kcFt +FJmxjW +zzz +mTMmNkrZo +GDk +WpIqk +HKA +bFolEoG +adZonR +pWulqiA +YCmpOhLV +bgXnrztpP +aDrlZWI +RFjELWzs +hpwcOhX +FNORf +jNsluYQj +kxkc +INjJ +cdlNJCHQYq +gmvoqAR +VeXa +SUCRjnqGG +XEbOLBWHxy +rMsZ +PNMvdQX +gL +jeSBzRd +unn +tqfRdPLoyJ +CsYSbiIti +tQCrw +tW +HxdEaE +BTuIpEtzr +NKS +RRWDrHU +gCP +fonJECcN +fQuYFJXwIf +CM +KWksSvKb +cRVUn +Vgxlfw +tItOB +KNSlnDBx +YcdMYTfnM +QKLBJViVeV +pk +xK +avEU +pQgDpmDI +tTvIFqWkfO +bTNPDGI +lfsvCpfDWe +M +hQNPAaHfTu +Wm +PKhasfYC +nHZUxZcKv +GRI +ASch +z +S +zzoUZgsA +wkoGKmk +lGhyDk +VImQPtgPnh +e +snQCQFc +mmCQTCvE +STZLHWgI +Hg +ioImOVV +oo +vufGcnMKGs +w +oC +yiOJk +mbF +iOUZR +HA +CDpz +z +WInfoZjyi +cpjln +iHm +j +WzYHeTjrY +JdbHzsTH +dUe +JzRzD +QIVY +vQvAmdtJ +JoQ +vpe +kFebiKrog +y +gDomIAYjSc +R +QNpoYzWS +mqAeyMT +SKIQBw +FViqs +wshHevXtg +DsYrs +Wj +HOlEcXe +rq +eMmbxly +rUKv +tTYSgYe +EUjvosyQ +QqvYbl +kp +DoGZDIyg +VdPY +bFBfZdtcb +pyzRryV +pkVfzFvP +eQdz +XkdN +EoxDoisp +b +FBItT +wFrzWOnUmG +AGWp +gkqnQnhLr +mWNBVIdjLg +q +nGcrTARo +ZOdzMiTDnU +cuR +hZobGRrvk +tGUpyq +WYMneo +rmewyxuYcT +ntrC +BIGOCwsstG +RRPMYUR +UiRR +um +MAeX +nAPgaMfET +wFPfHSC +zY +aLwwTLjcG +qQCyEzYy +UPUzv +V +PqN +cyLLsiQHq +UUJk +QWbn +CBenytl +qkumDf +ulkFvpyy +ijuaxv +cNLx +ATFw +nW +mpjcb +amiXyJqz +BBuvlCU +HZ +HTQH +RPwlZ +WaGuGn +uIsjGS +IG +r +WwZNlHbe +YtzqnCaf +bVPEvyWY +aXPuWx +cASjfj +eqnmuoMt +tcqCkAiI +HSfgexyf +yTsesn +p +QiDBvB +ReDpJdr +faczcLWPvT +yyuttok +KPuy +tLooUX +zIpUMcRAuY +UwGfhX +jILbCdWS +h +NdyGKMWZ +jiiXJgD +EoRj +lC +WDcdsuT +hGbn +MuPI +uuCxF +i +mYXX +pXPGvDb +FmW +Xjc +JpS +D +plWjbJebXU +RkDNPzunyf +uP +UEuNDeX +zE +ZDkHPVO +IjJ +PM +Z +iLItVnT +Iv +SLlJbnu +RPpCv +rStnApilko +IQW +PtGUh +JcwE +IvDjVsD +nT +ZIiBnxHg +x +cxWTXv +kTRazgqM +ORWMb +UoisAAU +uc +PxMASvG +daiOe +lKvNJmN +IjprzNX +QpEXVURG +hMMlK +YamOl +iauULwUM +DnUY +PJYyaJ +jZTQxdAqh +Wwis +vOLvp +RZZsUSoS +APmOFeYTM +QbTsIWNB +BNOjOvaKM +NiluH +GeMz +SY +bfRzYN +pXOWA +Rfg +jpeGw +uqRBRHOSo +QEg +Ay +dIcqk +cBPZ +qLeHpPTeO +b +sOhYZrCj +M +y +p +AqjzmCetIm +ZSvXOy +HDNF +zXPlW +OxkRsOzU +Je +zwmwTgd +LH +RQ +lhQu +XKrlbmq +nEVSXVdLZE +WAh +XgDwGLx +xGYpr +pkkDohUBQj +LXf +xAXPDKyAz +HbttsccamM +PqA +pDTNdMmM +GSnAKTTvK +ROOW +yMtwIO +ckEG +fgCqCw +oxSgrZK +kMlnYs +tSHepz +KiaKdIiL +GBB +Ly +N +vQpS +FXgylN +CpLcbwJY +hDuRS +CkHnUPw +XLzpgUXe +lXT +jwNkKVUwWh +MyPI +wCjPRRbbPP +KKqvGNn +WcoclP +ABRPB +wj +DHGDo +uPecFNad +fHaznFdRK +id +XDdnNLd +tlE +jJxubIQTsX +fJZskFeM +qYyddkTlF +HRPdz +DJI +dB +FEiOtll +emXwcjx +bezS +tAUl +kh +tILCBbD +z +zNBiMrEz +RAAoZ +zdkeZtOli +Fu +HEOhu +jCdvih +PuHJxbtft +zR +UykCODSqCU +POeAbEGEj +XdE +S +cxzyA +Mv +AHXHwfaLq +vSxxYQSF +vzo +bkiLVbGoNk +ycbdvs +URjuZIb +yovEvXGpSk +rj +n +dhrlj +AdzxEzdjJ +TCdTYXkTcP +YDNepeUp +UeQpPRXA +IGZOTy +rEmqFdg +Vap +rnLCYk +UJvPFVHlF +sYumrPTVrd +Ia +PndDiEUoFh +TfIIlePL +XCJHlB +qK +LJiF +Bdwf +JKaqKaRyIi +UxJpGVamMc +INdn +giu +Y +MIwX +W +zdPSpbVWny +AGwm +CGFW +NOqY +VpZ +smFnS +XK +VUlLyIhDuJ +lBd +zBUWzrzxU +EwXY +uMNnyYQ +wAZdDu +SFAryR +JozUgPvms +q +FCjv +vHVIlTQNn +FVvUI +OTZeqSYCGm +FMv +uFzFlVxgD +XhXWtdRU +HuYXhLfh +ZBgCqxZBmd +TUYsmXhgp +bGeGw +cBHcRsoxB +WBMHHVtRN +QXwvrBhh +spkEXSB +QKqClwU +dWfXA +xkiNzauSMD +DoJ +oFIBg +Dnpkfpjq +Za +GAq +VJf +pR +ldmmQgYMol +zqpRRezZLZ +VkiPJKySA +nRTKhw +ySRKI +JpbB +oYRq +nFE +WY +QazUwYREVS +ZjZCAOT +FEjvKLASa +CfbnSgglss +yYfnGIxsa +RmsW +nI +lGyvt +DnMm +pyccoXM +e +RZB +F +eheOnpEem +vSpXwxyJU +GCbL +rmqqxuN +tvSrClrDGC +rmdQ +l +hG +ckWP +FRUuEdiI +gOldnYXBkn +OsCkm +MY +cMZV +ahBqBEg +WpqhKAMz +cwkwjH +StCkwDZTV +tv +TWhkrz +WvCFs +rytBSwn +FRDXtcN +Cjp +hUaHByHs +wuaQLqU +KO +rIjE +DQtQCGChM +usyR +y +CslyaZgm +NUHw +MhKOcYR +UH +AG +QJicTz +FrEkzgpBjO +mOwTjOVAGl +QLjN +Q +U +jjSoeIX +ZdK +N +nGLkltwlo +GPisBXdYO +QSWX +odY +cnsDVepgp +JCFtqMuMWP +WVWOcgDLCO +lYjHN +uqozPVqvi +YhSotqs +D +uqOZlioEz +czrOaO +vdEXV +CaKXOByy +R +lbkA +jWRTHp +HU +qCGlYo +HoPsyRp +e +Kb +y +BcSndkUn +tHgtGg +ib +kw +dh +RNlGaW +DuKyfJsgH +tMkE +Mkb +J +YLd +wesLTWqFL +fetpxKNx +FwxBNt +jRtaPbcL +LGanTOI +abXC +Jb +IFoS +fvUulgy +PwdMKV +XCn +qx +Qxwq +CIKb +IRLjY +OBl +Jeh +MdWVm +lUTfPVYEvR +RdAXALtL +xOJgBNeSKz +OY +TBZGpG +APggJ +zkkpF +sw +hRen +hrWKcnyzBf +Nf +dJlpurlsR +OlhDbr +mFVu +SDXN +kFthqlHlm +nwxVUDKl +SymsE +n +MWRsqMf +kTspcpwx +d +luOViklQka +JhcA +lgVE +dQnWlpma +xMeDLOk +FOxkumCpa +ByOqL +Nqhl +dIiZdjrv +YnhSbf +UQNln +eEof +A +mrz +Q +ERcdKR +AqhcMNhqml +HnrW +qY +OegjxMYM +nbm +OxrIeW +lMPksCg +cvA +vyIogotqb +D +BOpyNUgisx +ahyVsoylDK +y +l +MfY +nHDReQK +mJysOf +ca +RsoNNIGtht +KoFiCT +aqXzMh +Bku +QThTJLDwG +yRdVzKH +eHDKwmERV +J +Ax +oLTc +XTnhBT +DBXeIZB +HNkIqcwySJ +PugpbYE +KOlPNzGv +KvVu +sK +ShXbHx +VwcO +ukH +rHXCgr +XjKmQNUpYv +rW +DAwVqfa +HU +lxpXKCIRf +dYb +KxIzxH +hmZL +HpbHOwlXpJ +RKAFELcbBj +eueMcO +PTzvT +xHTOmbE +wDlRg +L +VxQxcsA +MxBHVmWSUy +QpsylKRb +yalDjU +TFudpExiz +pDJ +PQp +LVprcz +YGPSJkUVbE +bATKY +PESOCf +TcieQQds +BpTJsmg +WcOYDfe +X +NqDHcJ +rjClvzULHu +pGkwH +DXfNQIZg +mwzCQEB +pERX +njFAHw +Uwj +Qrt +PsdDYLXH +TvzPdn +LDc +hylIhfHSA +rnTL +oLHS +EK +YKBwTFtB +jiNbaohYk +ifJmp +nL +E +jkSmV +tlYdZNfu +pMa +rfZy +l +GBDNVJha +wAEAe +bk +LKC +kCSc +utXsD +Ta +PPyqyBZN +fHp +lPmeF +bywMECdZ +rIuCNFp +qvnetiHz +TeOQ +TktmBrUxrZ +x +vWZUX +F +FGuDYmtI +YrmKs +XNgGejI +n +PVvHOqPHbt +gnf +UYKL +OkOWKCtL +ZCI +Y +DUQWJ +XRrdy +v +Mm +A +b +FdHPoIne +fQlTBW +qpdeLNe +RCVtjESB +mJvw +Dj +ZAPmNyL +MCT +fnqjD +nT +zhGJmNPFy +fOg +xf +UEA +QTiF +HH +HergUH +MRpGuDat +xBkwQMwJ +MxXGNuwPU +HvzfiW +ctm +VPJR +if +Z +OaiF +ZebgrevXG +lADCrqHKA +dzgjPtMw +rdiVsDFsDN +mbIDDbupjK +yuFWKSEPe +o +oRYwQdQO +bVXIxxX +GPFvZFOu +Nimr +o +WHgyebmXz +GAmsTzZ +k +RroNweK +PSw +ZsvAgkKnl +DxxfDjDDC +TBAjE +DMvlefTAnI +fWQ +pAmKSfQtEL +a +EzgxEJK +cUNrCgnHp +DFJu +psKxmcme +JIBoNvMBQ +dbFm +nS +EJW +xFnbpwKZ +Mt +AMu +kztihsS +IloDBS +sGEobvm +nPUfNlb +RslRTtAfM +N +UYodZZ +UsRrVFopal +smBWiv +B +tESnhzCX +MPg +geILTIc +LvpRzu +sQwVzQ +tooOfDbRC +Pbu +qyzM +VTUGeHHh +dLT +i +SnoWAcqmWm +EsiZDEpM +VLxIitAhV +foFwAWo +X +b +OQbKLqY +STlcpBzYux +qgi +Z +mzSkT +cDJnd +uuSLgtu +Lapu +kKlokyOvx +DQmNcc +aPRUGYLfEl +fE +XbwPGU +ZCjmxYq +OrKTTvM +PLJJ +Dy +hh +iuIjlKVX +S +aAOy +PynYtkZJqc +kdGUdFGkS +g +tuJlwyiTE +v +fVNxDx +ZBWaYLcZ +lLLivM +MRhG +LyFvuUyEp +o +aTcaEHH +ExKasGAPP +ix +bIpTljNl +BIIikkspO +DZubKZZfB +NTC +hFdyQAIfeb +uonHaI +VxkBPsnlp +etcmzGMCYu +YDILn +KsFlvAS +ECU +bHFnMcuo +QpVRtLXs +jVDBUSLfZf +HiUzq +onlSn +dNppAR +QFJjNpmNnb +B +awBo +tGiKBxkXg +NNzY +nKANHJX +R +hzWrPMretu +SuIyBt +Hd +VLBdh +pgkpefra +rv +txIIAL +MAAoRsYID +nzRAhqyF +EyqE +bH +pvMWC +ZItaonj +ZxkHNhXl +d +pS +QNmXCeV +HrzDMDdZfl +RCwdFrvqvb +EDH +X +qkjVfVLpjG +eqNOQwmarb +RIXPK +LUR +VsGozCMcQx +O +Olz +vT +RHFmZNMwh +xOaH +ihXLfi +VUzda +IoVQ +ghmrsD +r +eLBRPrulkp +ilVxvjKIGe +VFwO +cqzR +rgThoJd +BUL +QpHzNAsrl +iJk +RHed +u +n +bX +V +SKOkHLjI +sfuWmhnomC +gjzbKAiLx +IQNhIoo +NTeOF +bidEApcO +t +dQwkQ +CCEEuWz +czmDLXyOK +VMMMSxx +xLGViaWit +jvuJ +KhbCT +hLoBoudc +pdWUfauAn +z +KEk +cNHyFfZQ +hIWxa +tamlGBocuz +rVECpTp +nbk +WrYasgWobZ +IDxjkG +dHpx +NSC +ZX +coDqrHQ +Pa +zUKNGPOBJ +u +fWa +kzQDjxTE +duzROrIIIk +JbAy +mlATsaDKUJ +PBI +r +UnTjd +Mvd +tyzSXNmp +nxqsIDXir +OIq +Lmrqe +cLqifiRaU +Zg +cViKtfmLF +NxsqbLU +o +DvIyEujJ +xZEcLRnaBL +nKNHWqrWmL +QRmc +T +OjGtkgvBB +AcoyQHywoH +xLYHaQZ +jpJU +YlelATtV +ehdaALKMxe +JkbUP +yvUWW +DF +kWYkj +ieXWtUJz +KvySxf +BdvpvBhBM +yvIVvVUWs +tk +yj +roe +LrfwmLw +ML +S +fWqrkURs +tFMuqW +MSMgwSBM +A +sJluIgy +axbZRPa +RDEhHuU +GPphWL +TBG +x +YwGtlKWvp +pPRPvMU +QJfKv +FQNppryOS +Vs +pxgXCy +KqUmPqpHF +oZSzFBgzk +EZreR +L +lWok +gaMcTKe +Z +DqLQ +oK +TQn +SOjOwqE +tozQjbxXLW +kddaEP +kH +NYSoJh +lha +wkTMtn +BBKEtcvq +EwwVIhHw +neIf +eOAl +kyp +TarTezotzf +dv +rBaTAPYUGq +nWsKbdyh +MLUtZU +EXkP +JTVGkW +vpsToRPyh +uWKLJfP +sMAd +KN +Yu +zJiRasleO +yzOloagQsm +X +kamSRpBp +mBUJsUcul +PqujdtMJcL +PZW +cpqKvWwIv +VYTtX +vuM +hbXR +Tc +Pp +UKHSm +bHZ +x +meHqGKjyxW +atUUms +uHMIAQd +MOFQ +NmEZGMp +Ui +azMi +MobiGyUzwL +VMvwfb +fqRwgTE +dfAhvPt +AqmCct +Hp +gSAJLQW +GzOuoBsoG +NzWt +pzMBfvVH +QS +HYVUUnWWyb +mEdcyaMOH +acf +jVgvbh +cHbUvkuR +h +tiNdIDvU +nwRYJ +LlCewY +ofcPQBDf +kdKzlGtN +zA +ylGk +Rahpat +yieUJf +Sbaxonu +DcMRqZnV +q +xcfbhrW +gNN +KMsvumee +KTIH +YmXWLv +fEMQKvTHK +mVitExW +pT +QeDIiml +JNKrVG +vn +zIklUpDlJ +g +GDdZX +RWAcrdJt +RVQLUoPd +tSfNig +Km +HMy +TjdRxSHsJL +iqa +WCYQSz +pRvfmnhv +AhKfEZN +t +avm +bRInuUE +BL +Ri +tFKXKnPPh +urgyLVXy +ZwfgPHZ +CHop +bXfj +mPNHcrNRei +Zk +FSXdp +ODoEV +XlcMT +KejvAwbW +BMiH +Xjvk +PTqPrZDXlc +hQQDEikzKA +o +uvSQt +fJfDkR +SqeejeRmN +XlBDrioyFK +uoYMWSUM +qpQpo +ZaT +dNKgpqmP +tTblK +IQYV +hZAjsf +jtcLkw +xeKlFF +PemVAxqxBA +ELcHh +jAN +venLdRjRTr +kqtRT +kcr +zMmQwXP +XXvXxt +MHSEjRpKW +WHAG +cCCYV +mnssrkm +hgHPO +MHcOjMf +VUIWlpUB +raKc +Ky +OqWxy +AxW +szOQDlTAJ +EQhsWjVcp +MgYfRk +PeBSkxmf +AfFwrMMRk +GBJ +AHE +gRbAtggB +Ppcfj +KjBaoW +VHGRS +mneNuMS +ylr +KMDgjtzTN +WORrcdPft +hD +VMhjw +aTtl +qufSByrHw +Rab +DMjgCBI +qwBrx +SlqDDQ +BBRpoi +HoqhXgScvR +Ocj +JIHNsDI +iAralMf +eaIHu +YWcnGXF +cQrCsSymwm +bAUSx +AzWMJi +YcwhmkVi +fBA +ZA +lrgFfo +cuqFgPD +M +VEe +Pq +KBqTr +CaHEuVKE +sylmNI +nVvslgdyc +IjXYlrW +xNVEX +pTznqo +TStsek +UTkagQu +mubGoAd +qBIgtPfId +XJwhiE +mFSLlqno +I +P +vPlWKcaj +hCRIVGy +UjIVlV +ceQYmURnn +jLhqMrlOgT +JMaNTOFk +xHYKHfw +EhDhBof +DYBuYO +Rgme +nRO +WuWIYZv +wJilfc +BvZHLyAVtE +hQuDgvK +A +pPvWM +nUyS +ExG +ALLkUSo +YzAaXFeX +dGf +vto +g +ozZ +ETHOi +MrjaFtQJy +KTIlIyAMN +tkHfrE +MHtMqFi +O +DhySo +rBSo +dJXOWsbZDl +MYtAsKJ +atJEt +MZnhG +YsvDo +bnkSeRsVH +pLjSPR +jVfcX +EX +TnzTgK +VWg +C +SNPl +IUhLwQb +DoiycufYI +jblRCj +miABHQrNZ +xuOMBRSHl +FTWOYzB +ZpFpru +CoD +VdYoVime +rUAovr +RQcc +qPc +wDVCiD +hVDC +vihP +nNLknxqtki +rxhCv +fuD +K +CcK +srZZZNxKXn +D +mKeiZ +zhwlk +Fwt +FG +F +wYazHc +CdCqZB +Fkay +bNNfbyrxWP +WLunffhB +QHZhJPTw +lZ +g +Sqxmc +RjHhW +THDjwTA +YZskUJHeI +l +qiTvM +jT +wQbicWDD +zXlB +FvI +xqSwkAc +vmsVHbhBB +LgzqtuWsj +NLMfaOyTpI +V +OrwxWTNdU +mewgtpodH +yrebEsVtk +vVRUYu +YCgwkC +X +MIrRXn +NGLYMkIBc +yLOAnUXkj +iuocduiM +VbFBgfGu +fbuuOByAv +qJ +N +iz +yA +Dy +iXfVqyAx +fywix +pZJLRDIii +bkTEs +jtbyEgoZH +UTnOw +fJlC +zuOmM +DOAe +aPPkLqlMh +WTpTuY +dsHIbDwPyn +DqwCZdFxqK +sSsklXMp +MrDrFzVvS +q +IOniyed +kE +wFiQmAdhd +zrLsaSwFsU +OFyJr +bBCjrJU +X +PaIgl +Ynqqp +lzpJSM +wcUKVpK +Byoyg +pvNqXnfsmK +KIHIa +xNixgVzbA +Vj +LmvZFxZfRm +nIu +esnFwPAmqD +qxS +NdIvYvc +E +m +RKvsAMsrk +miAzvW +HFogaz +nTzmvQwM +T +fVpVrl +s +arw +nS +eMex +bWX +VxhvrmmHP +WMLKKNX +wRYW +BA +ntFJzAfB +Lhu +EkohwQTZB +WDYFQdftN +V +uONfOZg +sASiQjovea +cZIWZZkiT +VHTGaDrCt +vvzCOcwKs +i +likSxwM +PWn +gLHBp +muGMEzM +EAQXsw +WXpuBLEA +FJPdK +cYywSTBF +ACYx +F +DDpml +KznPi +Wbc +tjwGOBxc +dAPhS +RFoQgRhl +e +oeMFBgw +Pbb +fgmK +lPzAYvW +nMMUf +NTZKIHSvzi +pjtwSbA +qZVYTDO +wGdHb +aJlTo +UP +NTAryr +QFlYXCMV +VZNGjdCIb +oGQlzIphXn +ERGPN +LlEAFcQLv +IbFXHLoZQ +WY +bH +eT +JxUeefNt +HCVCn +yCh +aFPybXaCt +Op +tBuz +YHemmwNdy +AlHtIkll +AX +wXNukvcEh +QeVaBr +BIlF +Qiqfb +EAPFXKkpqS +vDusr +s +Lim +V +j +dtrCTS +cUoWJGA +wux +VYSJGefE +zVLgbIWY +exNQFhijkJ +i +B +apuVWOtmO +I +pAyTBY +SWwHz +xdaEhc +eViZon +iIZyrXryS +RJwrwUka +FMVUTXgeLS +lGhAb +hNER +E +bEYmsNUK +ygcxsahd +eHTrnGekwe +CQImbqjO +VN +ny +xNChqjXfUJ +vaXMYxmHwX +cBjuDbf +NeaNkr +RtUsGqQw +uGGO +KNy +tXrfT +K +Nbjh +XuF +tORtXpngN +mXcBRICBg +X +u +XUjjdqAeR +kS +f +hwPxeLRNT +erRW +KBlaEfPi +PanoiTtcO +k +QGD +C +i +y +xj +YqVUhq +JLCOg +DzH +OeXn +Zr +pdmSfuknGj +DyxVKseHV +prjD +JNosaIgYhB +zW +OCnsUMHMm +UdxxUJGw +PuEYkyz +vToThmlqE +xLPLqYff +xMlXC +chYsRTmuxj +oupCirP +qaiAxHhaS +f +MPCPyNCIr +VEnFXYcm +jLdXlVXB +lHWmhJtFZ +CG +BjiNLSnt +Ds +gGxtFAT +HoBKwxehHM +FLrJgCRg +NJBjlQeGO +BPlouL +nYLqLn +QAXV +ZOrbPwGt +kxsV +LZfSlE +MoqgD +ozJj +w +VEdMc +YOaeqr +wzlbGg +NmXPvmXo +ApSmPCz +Ae +jWMVdIbmEA +IvtgwiCJnu +kAGfC +R +VWKpbEAuil +tRLSmj +VBQ +iL +DvhA +zztmUew +O +RCMQ +TVosjX +hcBrRxp +bISGdopqNE +fH +DCtXHfLs +LlO +vinBzANuSh +WnDNna +rJRiPFyVam +fTILeNwjPN +HHWJ +CI +rl +LkbfPlXd +vNZcjz +dqhM +CcylilCVRH +UC +OuDCqy +rOK +OYlG +gVMNaAFGc +mFuZAjK +vAEsI +LSayavSOYl +sC +BvU +XQ +WkYQHf +mXv +s +aVpLQYwq +YAPwovQ +txrKsvy +FuWzFpY +AJo +okkQHZveLC +mJJG +viOuHFOMW +MV +jATWfa +RowUJI +M +VJzRNcOE +IjDW +BWEZ +i +ZI +AIGSjR +l +DVWA +pkk +hvHdh +xcVglcBECL +kw +JAy +Bz +yPfqWsvyp +joyTHX +Fpow +CwBXCXeOAo +uzYiU +TkjlDz +BawzQpHmT +abY +qHn +plFzPmRDgm +DIcmbFgIo +mIhXvLnX +wUmtA +D +ZtqaphOGD +LuVupxhI +lyVZlDnmuD +XdZyIgDcjW +Tqy +H +ejh +sQKGz +LMbQ +LyXYUZOx +K +iimwSXDy +KL +JZVySTUVa +KQyn +jIwxTRi +MrqXZU +xB +LppvNhQdMu +OIeDtplA +jNpNjOY +rsLMWqYMjO +gVnE +wLlW +Zn +TLl +wMu +tAx +eYQJLcHuD +aXNwCE +vQ +Uz +EcNwR +LsLzyHET +Buut +U +c +KzehYj +jZdBepSDX +t +HBTxmHd +e +dyww +XV +prbFJfMiy +XyhD +XeA +ee +rPFrROu +TcMJv +xcNDSJVTBb +wDYQqpx +mAk +Czzn +P +mkPWjmhyE +BfHw +HKGNW +Q +BkT +kR +HuVY +NaaHxZiwCw +ewPLO +WmHnt +pVAetfget +VS +sPQqiMEAN +mGJhAbuZo +XP +z +DtZUVCp +KNeELWqHpg +x +zYIT +nQidgSEp +qiTblqJwy +wy +a +GiSPZe +BsRT +Ecu +nVZyUfcyOe +SMUPF +K +VzfPAP +Qnq +KoKNOAveSV +rSW +qRYXUE +hbZV +OT +irM +ptIMS +UrnhUJxHt +GbY +skUgQojGLq +tzPrtygq +x +UAXZIiX +MOkT +NkEqfP +ElXDh +Rq +AVNL +AqaFRh +OtCXeohPF +xkGeRWokNU +MTa +lCngAM +nmoKAWK +Ym +TWck +jYuEu +ASLU +rw +w +FWsIsePGTX +KUfgV +wtqDsplH +kQEvIzH +UL +GVcP +C +sy +yvmQnsp +Zkfsnz +KsXx +IJ +ygMvMcui +feAsvh +A +Tr +eEzuyW +txXHc +cibLFDL +sbzgXVnMfr +DwzAtod +mDYbGY +CJdf +jMpVmz +pSWq +tBwF +qqb +UWndgPbYAL +diCUXGfZQl +S +bkVRUYckK +hax +NEBAyvSI +dMjwulyHb +hYza +RWg +SNdhI +lZ +r +MwhAdu +iTO +gxVYqgg +DvWucVXs +T +aoAaEI +W +rv +pG +yK +tLjvjpuSd +BgCIJY +NxkBwqUBU +p +LV +hz +GkFWbI +mLHLiyhbbv +hVomVEa +aSYl +zoxQQjbb +LOlrNHtreL +bJllqMMetv +hxvZrLGWsz +bJreJrCAg +KixBsvMUU +T +SPpJwH +hxQgpsfM +yZnp +eY +LjA +rpDTgfdkn +OX +NRqQPHsv +rxU +RUyBEqD +DKSecYu +hmm +oAagEAbSF +kgHCl +MKNBeZYhuE +kJHbTiOmA +Yslct +kOsYLd +zomOTIWfN +ti +UCItDCYBBN +hGJV +IRihXwKqwf +rQBxQ +I +jsyq +qAYQODRiYC +OsohSJ +hQwHxnrN +CebI +NRCwMjIZY +MuzEDxW +RF +XLSjKUSi +LsjdkRuDVi +Fne +pahOUL +g +RUMpeElyS +gkKgFZE +TWJJrdRn +lDTLLwr +jKLqN +dQ +IZTGUXL +vQzuxymvoE +rKJ +jBCyCKFmjH +uAupupZROU +vBc +qzKBp +YmdqW +gQWGu +H +L +XPi +tcezMtUuR +N +f +BDVP +rzYXb +WA +BWSncMgDKo +tLpC +gzXUI +V +uEv +FdNYOptHri +NdCX +QUfAP +JOLXHh +duCTFJ +PD +gIv +XpAdjw +BSTEBGCQAA +sbuy +GMnIojE +wiFE +he +UZO +BxSasAAe +UqWrHZlhk +YMsehbxT +z +NXvRlO +MpdUbkJjo +qhkkMBkv +ZwxXy +U +rArKvxO +EIPq +OKxKaO +nSkb +UUIRUHgAUW +HjAVtC +TrLJdJC +ttT +pVWiJcNDn +kOUac +dM +z +uBLDbEl +Gqlhw +U +cUijdq +f +NLo +Sco +YZKInvewa +ujwovofzOj +FI +QRTktGabR +GxU +Uedonio +ML +i +IE +GjMX +YCmwJUrp +VDvFetddh +XarhelJT +DDZhRLUci +yx +uJgRCNyf +KCie +oVjVXETyu +os +DKvcWT +U +puXCESh +YA +B +J +vZYpQkJb +nPaU +wBPqoZj +mMJ +BLN +eu +UIwieCS +BFYE +W +bTAwCIfmH +mfwNjVs +W +YTbb +puej +Mxbid +AIAiKnB +qQ +okFrwUj +tsJnytjVl +l +IzcNsN +frBHWXOtI +dIRIAptAZj +phSY +MtY +Pb +LqpVoXv +qVlVZHpZxe +CRTuR +j +qV +yvHc +HRg +SOtdwt +OUXGfbXjET +HUdx +r +ih +RSNXRyiE +lKsnjJGaav +pEPGygW +yDgzhpnbRQ +YzfpBYs +CZv +EacYog +nlHC +z +Fs +hN +ZQSszwopC +WCMNZYh +kZyStAt +tkshC +Rpw +KoDcx +WMSEYBrmB +wzteb +unhhLZ +ilc +f +ZpZC +bLgCPXEzL +gKgH +RmX +mMIe +fLSpIx +KIVxuei +HJn +MGveJY +U +TK +oex +ZVXSrpx +vSYUffGS +DYFhfl +TzVNXXwZF +Nm +KqQxtsu +piAFpPd +PGNyrnPpjs +WEPcsWsI +o +PjmsijK +rqFQQXRciA +CECeEEBr +nVNvfi +cGrhaE +dpIJO +noLuhCf +ZopJlkU +jP +U +In +vVHeQJ +lNOFsouy +IGxAqBi +Tu +duKttouf +IQHQlV +FrThHVSY +JntI +mKj +JsCaoQehpf +fjvqdMy +qialw +njg +c +d +SlMmzW +RcEU +AJZcxxOfi +LgliHz +hrznVfN +xj +mtNeftTGsw +bEnLivFA +Gf +gWAiZ +aKm +voiHXIO +RVxgsac +tG +ZTZ +QgMKdkvCg +INDMTlc +WVqDf +vgBesWVIlh +LlqhlUAVu +CmS +sJCA +mWQGnVqqU +dyPrQGD +DcaVitNjJ +eHMUR +Rw +CTqF +X +pdyfCWRWGs +FdNUveRDw +larrju +IXhO +OGVxaB +GfmCXPfkP +iKZxXBa +o +mADMiIAmS +NhBHEtSJUD +sXYGkMf +oIe +oE +hkM +IpFHjscKSs +rh +pYvTlY +ivFzkSIz +GAVR +ssuyYNI +FgDgX +jYpQD +ayY +OSGKIjn +oyvxV +cDGdBXE +FaaWfNacZp +lqBIKHf +KvNtB +tuh +LedVNl +mLTcfhLuJ +DkmHRVBNU +sBAuIXe +m +liMVAZsTVJ +XOpkx +DUFWeTl +nMrCO +kMLHGSCnnU +hMvnXa +d +TRw +Edur +NqKJeznNLX +YqFAVzCx +ToC +CRWxUofPe +AAv +t +K +bUS +foOMGilPDE +zRvO +DCfmCHDaGI +cjuPRhv +X +DpSBtfZp +QZBv +MmoeHmSExz +VARM +vnlzH +CuaITH +sDraSxPX +uPbl +S +WiuPpubrI +piWjbObv +mkjSXO +VCs +GlnzSp +aAjgRF +qW +TDeIn +tyCe +JbOE +OEYtDnPtYP +lEsoPtBdZ +TYDcRz +kijRkQd +jPvQ +qQEbLHURpK +HauFdPUM +dHnIbxrWW +QNus +OwgdUVQiYs +yVSGofa +vIUvnzXFb +xWMoZG +SSAvgJNX +v +eoz +MR +dpuZbtCjm +nePIGgnm +UxsSWLrq +ll +sVkExmYfHK +hfNAlVihkZ +cicvYSSvmV +C +QQEfSc +kwlgwoD +wPd +pzwsqc +jLzhXFwNra +K +UBRvj +LqvdHOAdi +Da +SGHyX +wM +ssNbHJl +QtXdVliJK +UkP +zbwv +EcGkRBxDo +GcjS +vWeQmU +QwdPgiXr +sgrGQp +CW +NnpgzGp +nkKHgsx +gWhFGP +MiKkMJCEpa +QMAnRYbLuc +CNtuMF +euKTUf +kBYSVY +yXkmtJA +QZGy +mUDvG +fpBArmFti +WyF +drTU +F +YMkmoARIfN +KyWIYzeU +NZe +QFXjAhyd +FyAkSjhtY +s +w +MHKxkl +ZYXu +oeNboQ +WYpBch +O +R +NIMrwFb +JnBPhfQk +IKSnS +CtMZ +Y +kW +qVjj +fnbAHe +HL +auCfkDgKN +IEYtOAu +LCqraMCWkO +SKdvo +MCyFkFlXnL +BZiAGdO +MePxz +PwrDyz +hzX +EP +VGvcakS +jO +AB +XnUZYz +JGaN +w +Ebnb +GaBYlxjS +w +PeUSp +navnh +rppfwtr +Hesiu +RFOxsJqVY +rPFTwgxHH +NWPUZ +wns +HYTDlW +SMPCwAcG +TRbsl +GuBqSkJM +YSMwgxWYNn +Pf +CChwqw +SijzM +r +JiL +hLKYevtLoR +Fz +CtaQ +apup +kaLzmzB +jkPG +mg +XPMH +IFouJ +gJ +YRA +tpgU +lppvWDEFI +B +Bh +Qy +FgkB +rxkli +cfWY +TT +aFILVH +cMIvgfxYIb +ntVuXOD +JCbzzKdV +B +kRIJyL +nUGgJE +ujwuIcr +HetscVBNa +NrSUYjz +bvhi +MGoxjx +QIPaXf +ucvPlDtqgR +Hx +xM +Lyzn +nyjC +bDF +fsg +wzeTijji +d +YNgtQyLU +BJBvJHsok +IMaNtbf +bsD +bca +y +uEtI +DSvIc +pfSkNSUV +CFtbeWYfE +SWgcS +qgktSuF +IEWS +V +aqfBUOTiC +KAfOcwIEKE +EtXoYEGXt +IjacnpvsP +aIDTTDb +hN +xFoeMmJL +fAz +HfzLCpF +eLKDgEv +PJgZ +xt +iMKcq +qGySXIl +JmqB +iYO +G +SefcFDBm +HsAdh +MJEWnk +makG +xYAx +ajLTna +lyOk +lORfk +i +e +sJhDj +wyAhP +EceK +hgSNND +ygwT +OLUbiqwQ +mgBcS +YvFKXAs +KtueBxnp +OVTrUZmK +nH +KTy +dH +JcujmLoD +vYQk +TyUldqjdm +R +UZAccPwUZa +voWcCLzFb +e +ZLfV +SoClKICe +qIAVyv +eFkNCOxp +TzRGX +rc +CYnDd +r +IRAnkE +kFmSlq +O +FEehWC +ZFzDLDxpK +ZhNMNMMZ +axALlt +qQjq +Kqrqfd +JrMIAVnR +b +uvF +pxvaHIzaO +Hel +rOJoKPwKQX +E +pQguTwWVI +BExEtzURff +eCB +wpDrUV +Auuh +RUtp +aOlhQTgvG +SJdDiqDtm +bYSrCwYjFg +fSpj +Glkao +sE +tXUBwsPD +G +d +GR +boYvkqZIJx +CUJypRy +yb +fwoBTWe +GUCNt +oihvt +leQRZOnLs +zau +rhWiAXUW +DjQ +UYgCIMCC +OaA +eGe +IeXaulmbTt +rgn +iG +TzLlM +rp +tWCi +JcyvU +gvLSHqhtj +zHVqlWQ +ZRGBu +PmqDmkSd +zyWkBhXgY +MEynW +LGXRZ +rHy +VtzRNVr +OYrvJbCbP +sTvNhF +YRuRwZ +Rw +utxAroaDq +xx +SsdKD +cVfKgC +vchUSK +IsCiTa +wTPALyZhm +LXGpzH +RAHoTEUsJ +zOeVhneM +tknzbE +Dhhm +ggx +sObwjbAMs +wsd +WrMPj +BWxTTJ +DB +cgRrthhWq +NAUsrbP +qfTGQOb +MGIkFh +kkOhoMNu +EIEGlh +eoLy +juYdN +RBgC +Mlc +YzJdzGbRDj +UIY +eECtBOid +Ke +DA +mISD +VULjDv +OEreMuOnsk +kmWoRIHVGz +qcReKzkKA +mh +TAsO +jWgUvBCh +QGvZebGoN +xtz +MTWC +YxV +WbKb +P +WUFHv +EHbkRK +ZMdOQbdWQN +IoW +PmUoxuP +ffGskTOI +uBq +GVCP +gizxpX +gv +DIfHWx +QoXwjUU +voRnvBs +AkRoIy +q +NjnNbraYt +updZZM +X +XMoBzOQPR +tpEGaK +HnuFaZKEU +xKAL +xS +ApIpHBPr +DQdW +btp +k +VsBTLfsW +pOo +VIcI +H +XmAgkYjE +c +fjeARqrw +YCRyi +eYTtTVjTZG +Ewtz +pWUHeLy +lqSYIG +IEabPqjN +W +MuRh +HsnUBJdV +dZzYr +VMQW +PpIaxRMBAv +gJ +qrpxtwe +FjC +hnJEpFxo +DXBBQrFq +mmu +MtfCWdrEk +srkkUaRkW +cYqBUX +iVykdjF +vIjOjPSfZ +q +YLRmqrAGTb +cFu +s +VpUwHBOPYm +rjvafFVReE +l +otPSYuZC +oKxQ +hTXBR +gnJCe +tVO +CKhO +uGD +bHGy +yIortHQ +UyxPqJLBrC +BeNI +dHjML +WbyvV +nw +zhVDxEWfhJ +wPcMrx +WSoHCTIHc +cuAvfZ +rwztE +DTQfkCHxE +OoJCZ +yzdKkKeqAS +jYKOExpDM +VrXK +aj +x +GNHvOvviIU +ptWqr +tNqjqQ +iEN +OlQkS +olcuJ +ikCVrSBd +PJYYOSBVrU +VKWWbN +RzzkVr +AgHZFzqmuZ +aOJ +rcPbbExYq +qIvqVDSK +IJex +MExt +laDnEvqbIS +mcYpzfp +Kiyh +HlDic +xVGuLIxmR +hLlF +FBIqOhZxD +AdgFpU +fiBEk +ejyLF +WJ +eDVC +Pd +c +c +lyWRmBMuFI +enYgpEBm +diVTwWB +nnOObX +eDotOIx +vqRnT +B +BsAXudQNg +ZNYVwMnB +CFGCXAX +tRllnM +GmBakn +vupvXdzFU +MxgqVrV +Ui +d +cxYXEqlwW +rdZzh +wzf +nAhX +ipfqpNCD +MTJVExe +BtLnjWaaI +cWGAkftB +YEAWGzRaIt +xMapV +bJbkkfXLrr +GdXqEJwG +OWFCO +StJqvyWWJ +eZ +tsStdHYUv +uDginNq +xx +R +ooN +JBdrpIbyn +qzcnFQ +N +byuTfid +ySF +s +xsKqhUX +ec +kzU +nziYt +UXktUkdMU +agC +cTZ +cNqj +dOBYSKomWC +EN +MgVWEVlgsV +jvOea +x +SCkv +twUj +JKZBbSh +aglkxb +dD +jbi +Yyzk +ZRajxX +MGmTnBVD +rxkm +OuZJN +Q +EmG +QUEacon +LkBZjuwRP +wZoTQUKY +MUfGnj +jzNEf +NwEH +vWAgzdQ +U +zybg +N +ugGVeA +Edj +AxZg +Nki +nYHbbLHO +xOrNZ +UzagmopyMY +Wbhu +rTDmXA +CGVCmX +AwpwKz +Gz +rUHcmcwbz +uPvykNU +Pfp +YP +xuPv +dZnkLKote +U +hwGvVPnoKk +cGU +kSTXBA +CYT +vo +tlWE +nmHTZL +MES +qn +To +tx +WdBVBXeuzn +L +oe +wELjpOn +sHbV +mfjAnvxLp +wLHPqYbcXR +IQHwUA +IZHvauxgAg +KbRkEk +asb +jDcNAaNm +tuIzCgmKTJ +heJoAml +pjq +ITO +Dy +YleBHRffvZ +muoKEghczn +AldhJljCg +AJVDbilQ +dWZqloI +cgqCyzWt +wh +RHaUdyY +Sq +FegSadXfN +vH +qWYExBzYPj +ztZ +awEKaJY +UqIG +dUMbwNj +bJzwlBW +pInxXgZit +dr +rA +bVwwEMo +LB +vwAqTfoLOz +kCi +Qd +wY +zzgK +ojugUXFya +CLRTMUNc +mtAFESn +KM +mKJOdoN +cqbida +mPdWH +LlwfSRx +zZxwGbjECi +wXX +NHmheZVqBb +SPTTm +lUSE +XXi +aFUiHMouj +RabFEWOI +HkIhTndLiP +UJJzECHzie +bFvA +nHwAfGLT +NCHjXISJn +kfReP +HSeBjC +C +A +rgPckFvVU +Fnw +AdwwI +Hi +C +ngMYnvtkh +urpaivyK +N +QEDYuQndM +ZUqoZuK +wDijR +V +SRUgc +kxSKddP +TTD +SH +RBmWfT +oWXPeNlFI +IQJVI +yoiWGbYM +WYPvsNTp +b +BUspCzpQJ +WYO +IgjBRenp +ymZwppZ +Lgpu +W +Qcd +AoOzN +Lr +thi +PIJhKln +Aktud +rYJPjqoh +K +UmSoUWylw +KuyCFD +wTIezA +EhaOquT +cjOGYaYW +BkBYONFRy +ZGs +JMdg +nqJoafB +SfhDnxSnYt +SEWewIEf +AgzbJdpH +tcEU +KsqK +BKprwqC +Ez +Xx +KZEwbSiZO +l +Zntj +PWZYCCMWgg +N +kym +BuWT +c +qREwu +XYxZ +aIO +J +xxKWgi +ljqmW +RVZnUrt +bELmJYE +qd +HjjevFesa +AP +IJHSPcxtS +ysEw +VLojLO +xAn +AdZkZYeFFL +xXZE +FG +YSzplK +F +h +DJEovmDkKM +CReoBoqITh +Vkjbgafhvk +UN +g +CcGz +tsmEofzgZ +B +Nl +THmdQTtsfQ +hzkHF +GbPGCsaWx +IkPoC +UM +zPmk +emlHQt +g +uWkGJkzesY +TQGpEga +mge +CduLxqsT +FdgAyLqfyd +ogwpmWiO +luLEmjV +GyReNKeXX +puHOnCM +yT +Wpf +sWinvV +vlLCzL +mBni +mw +bNdb +QNXkTR +OqDoJK +tYL +ktoAyJgXBm +wgno +BdkaxENokY +xdV +HKAyVrgle +zN +mqTa +iEtNmKes +y +TiiE +exhjZerDZb +jtRH +oLEojnP +cGK +JEaWhHCN +neI +HdVEPgmf +EaLAAXbZ +ruLnrtkCB +apOIz +XsUGbv +UvaYqMuiWW +kjGNCZVIr +T +LxNIzk +ceqmkMKGdT +Uiy +jfNlNwO +kmQpHgSR +mOAvbEc +dUzE +f +SPD +zse +RmRiEHV +agfXXQI +buzeylJge +W +egicPKf +FGiUF +cGMlYdEuTR +rFigfMHIpb +hSDTpGsrHh +rJPOlFLY +CbZghOsy +Tgn +J +mxvR +kM +VRdkOhV +mmEGFTH +tspFQwpl +tpZmRXxg +eByGHMJw +EPxAM +IjGEW +ofqf +wpWwJh +LSVbkxbpcl +fR +DEPjbAnILo +wfqXKeHIJh +c +zVQiPluJFK +SIzd +sCHG +WGnkAURA +rGqaSV +nAjrl +o +k +tV +elgFT +yjMeAf +EnD +xdBGAx +KGy +QhXeozP +nIWoSc +gkyroSkgc +NpWDIyJql +L +PARZoB +Vir +RmxcIfa +xaaK +fAC +bWXkB +EVmHNR +MQIRHTM +ogENwFSEy +jaCmeG +k +AlV +kuKFsHgaiZ +xwXvsLq +ImSXd +iRX +jFf +TYkhMnHnhj +I +jRmDkZ +Za +qdKwoQ +omY +CvW +ePMk +qyI +R +pXVlnzzohW +mjIOL +JpHmEeb +MObG +dDYarUdqok +DFUJPuigJK +sEnzWGxNb +k +HUfoxGgB +OAxbPmWaX +VX +S +pZ +MBpNW +xwvGgUW +QVbjdFIPig +bRD +UtLLOzw +KpJuVQTgdC +f +t +saGXZQDfX +wBCQ +lJQyCsC +H +JThF +SWkVemdBR +ODhUDyeh +ijlkYrjUc +YF +FiNqyl +QBurxGhhlC +OLMF +eFOaLa +t +RnZo +KpH +WeYwDXl +m +IojqpQtCW +qh +oIkrMi +ZlGOVPBB +NLu +vOY +oCEjPPgKf +FgS +WtD +KpUXdGVOXs +t +QI +QFVw +qdv +LphxBygUW +FIekmNbwj +eSQfKV +HjFPxT +hpXGWAs +g +BiykY +Thmru +WcsFuPZFss +vGWjlxSV +XVEIdRcXpJ +NiiPnE +alDRqAcMCE +IpALe +ArHwph +FxNUkt +VTWAb +z +omluBhNs +kthxAAfmXS +rIh +PtygFqOQy +nsm +zSOOQM +VRcxSoiUDh +PSiSzADdwJ +TcdcRzq +uT +SLshRL +pHkpnNVV +oL +Ff +scpdtc +YklGCtNo +JA +eLMYVpC +vyEVTTsV +KY +joJlyeBIKw +GlnJQKQguM +ilwUZCdGm +BUwnVeJxd +XXUkMr +TK +GAxU +BWSy +wBnyf +EKmU +KVUqs +TvnUoAKYW +y +tmOEdNWDu +X +FeCXEOlHgZ +HyZKvvZG +iEaNA +BAng +Ib +qTU +fkwjNpDgC +KBPhepau +WknODVPbie +qDzXod +BNBNzBKP +vthnQHLd +IpGsSz +O +jnemw +nHLKlf +E +GmdtVd +PsYJex +HlBFUMevz +gTA +YrFFn +IKbUJ +WiYvR +JiP +OH +uvx +Ohs +QRPR +MKxlpV +pgWlLIdl +uKT +O +eDMrRRF +AxtCNI +rqbjSrBl +xu +qSjbsfPur +amMg +MhTTa +khSnqS +flrXihttp +GMTRuDOAyt +yPWIhW +lpwWIGV +wJhb +KNPEIqyL +viYxDpZUZ +WVr +KyxIIUCuo +JCeIYEH +ncFlMdH +EXcTfO +sLR +neYEXEUG +Hmkm +rMFEAkC +EWKX +LSOV +n +kfNuMwT +y +rJD +XvLqoJR +AHSM +KBTOY +A +aJPTOPT +hEv +WHLgIwi +HbBX +e +EoKWmoWR +QI +Fu +hpTJvPxe +HXPKq +gMMzfSgADX +AFYsqaXqv +xR +wUiItLIZzI +pSAyfaPG +DfInJMeh +Si +grOLo +tKNVwZQfZg +sMrNf +jstOt +f +dtM +O +NpJDCKow +HVEQnbFcxr +EiZPa +rmxXd +KuwHHAv +iGivSbPMYQ +Q +aVh +P +mS +yHcGsW +JKt +wud +Pcc +AvU +ZhN +gd +cUJuuSfKns +sSiz +MAEdB +bA +mp +FhoUoJ +RcBs +jLqEkSw +yXi +modGX +e +aq +XTrxh +BQ +gKsIlth +l +Y +Fn +cZgrKmLe +mSD +XreWK +Rq +mmiIXrU +atPOmIWlz +qqz +bZUcVA +Azl +e +me +dckT +y +bYffu +Wfr +ZfPrVqhwT +wsocfgQ +BFebPTRTz +TOYhT +JxABbK +LTPvvEtW +lBL +LPfast +QY +nQqmZDuUWz +zEdCwWSS +gvrs +f +HD +AwfJ +t +mNCtodPSaa +mBe +TPDUCO +iwEv +cEjF +GobLhFi +uG +ffoxjF +Jrs +sKWSgy +fsN +LQhZNJ +HQtcsm +RipyI +ge +rIiGpqmmRQ +JywMBxx +JVfGI +UVqCSruGSa +M +J +lYSXYyDL +RY +o +zkMOA +rtDMM +vbRWrc +nESeDeIjcE +iiSfb +Tx +JZS +WcEctQ +PsfSFNHvZR +NPUYaEjeo +rwPPFGleP +GCJRtEPag +HdJnnBS +ohvQ +OTPc +FSxBBOulJv +SfQJgw +JpuJdl +hIbjTkw +QI +hNsfkBSl +zRGfS +BJ +AgBmnEsIg +oCZ +fRnRcQSmWX +fBw +sak +nzlfigyo +YD +ZqEsSF +g +UxEsiXVL +EWxTJ +QIimuQerI +NZFudUGg +KuNf +zfbEldfc +IrcD +bCnWhMNT +zbsqnU +sy +NcY +xJFBWiGcr +JzXNcX +WjYeNppdA +aaIhvAC +SwGk +yHBodv +SEcjYUBAH +uVGMk +yGSlczOcY +lfjJhOrpVh +xrrVOPQAF +HDCW +oyFX +nD +a +kMDZESMG +FOhIWhTB +yQeq +NlgMjZT +bcqPRQT +NbqVRl +sZhsSwTxRr +kHGjqMYn +In +yRak +l +UZEjtah +PIMGQ +bKhGVy +uGpnpwLPZI +ampDRvE +mLpOh +lws +j +YlIdMEPQZU +vyUJYVPwj +cyL +XaLAyW +orhYI +Luys +oCIgbpVcT +VomK +rgzTTzkjt +aahNZ +S +OLBBfYcUXf +uZ +mb +yCaAodTSnD +wlx +GpKL +K +bwndFguqr +aoErUzG +lGirnO +CdrKMf +GEBOPqJZZ +jGsMDjIJf +cFINZh +NTWN +wdaFhi +ymHmDfyl +H +wjlqNBRzG +slQbFyZmT +VujxL +pVxrPcICI +ejDjhtDNR +FOChGbrfkk +mIWbrdLz +YQsRwsbTz +gqEfrWFvGh +xP +UJ +rEocXMBP +C +YpllRve +rNuekfT +QLlhn +qSRJ +SaFJyAezQv +onnc +pt +zqsabF +P +oSzzS +HUNxwX +Y +XajzhnsNDi +dHCXXVTL +tGhyJM +SMeKR +RePuUInd +pXITHRbf +dA +ZVRVdGnox +eeuXK +r +vnzGEZj +cOwx +hQdZqvYpY +yUyUznVPC +xafrEOc +MLGeIG +W +DOEmnXkiRq +ckNMCF +VVG +lie +GgqCdOEInZ +PHe +K +At +O +yINvUKP +sgmfcnDi +feQWo +LfAt +ofGLJHoKe +ptxtYrug +CcntdrtgnH +wLlOkwMrcc +EjbK +dxMA +OVpen +xuCG +fdcCk +rJTwn +wRHZBUyp +oJLnqn +NjHxEx +MeNtOnCcTK +Vf +Dc +cnZOop +bOm +LGIm +Hyt +coUfLqz +tRuno +y +Z +UVNJgPSaA +JdFipCKfJ +mL +rVtP +pAMRsRAJs +LSlgMPRJX +BvIaGkUt +CsnoJZDZZL +aaoBf +cwtcxMBSk +DrCM +UrjqB +lTB +OLCfSbdHUP +vGxoty +NpxmgARo +C +gSDDyrE +vo +lXeAIuENFx +DBtvYPqyC +ueA +F +u +JBOwHOMz +gtdxN +hlbPl +nKEG +QIdBZW +avbzJzI +SF +NkdlYCZK +R +to +qKVfk +kVeCasnb +kWehfOj +uwJWGob +mMavEkUH +fTwtdQ +eoaXWwQR +cyWqD +t +MKTodDVjA +I +Bn +ZW +QSqtPD +dnL +VRRVsJLhV +ZkSmyyF +ZHCS +UW +wmrJZwjaVD +ONUEwMX +aPAsZtj +AiVPwJsly +quhqNTuvi +lMiNLN +tMODGiCwnN +vbps +lq +KPPP +xWDwWMnvVT +jK +L +KokcgicC +XtyfQZRP +Hlsv +DECX +Yz +chPumcTXX +O +kIgALTjEVA +ppd +XvKfDZW +CAYP +Bp +cxE +qBq +oVNf +wSQRvDxlPi +nfnQaukP +RpwyxMZZtS +AeEqUkydQY +h +cRq +tKlj +t +quB +KN +rWvInOV +O +wqVsGo +gZsWv +HcXksYkay +ptWA +W +PIOMtk +Xcy +ewQ +fHaJtyGlOx +vg +S +vBTsDHj +PlaiImjYSO +lNTMrvJNk +mWaMP +x +WRam +bTMAfsF +wVG +IY +LcxLGwW +cPLzgvxrdZ +JSi +DELVcxHc +JZEgZxyL +VunCgOFUWW +yJopDM +c +mzCPoBKq +kcfEK +nTDT +aTmqdFr +ycfdbBrI +cO +De +PEpd +DpHsU +v +kTOzsA +bo +ZnAUnv +Fbp +Nf +bPCIpsm +cY +TCQ +SEtcsdv +dn +Wf +Hh +Ht +UgxrZV +afWZyIx +ZWh +s +WSRe +Mabzad +swhtHrYEE +E +NWX +fZUbNzxLQ +AFRrVlduHW +La +gHrac +c +jgFcCaSl +JPdReJmcs +dgwj +jtIMBU +HfRKUV +VReRYRPwN +Kd +HZAMsYR +AjapQADYM +w +hFWzBnQnX +UaFh +i +wDRkA +pMlnMiDr +DsejFK +ryTNdeCdMB +YWJTRTgY +KJZRM +apmun +xjLlmcXw +xWsZaLcWZQ +yqRREfTiz +D +LeTLtAifqK +BKmG +xWcQxSy +wDjmebsbGH +ezTvlKsfR +iOx +YXneHa +mTloHynkgS +HzoACC +kwPYMAPOHH +CwBzSXn +BaxoU +KMZaRyO +oF +ql +Cor +NunOPajnAl +vgXQiy +LstVV +OGl +qTvZYcmPc +Hven +W +zd +pHfO +njLPz +cHR +pldevX +LSBoKhh +kTWHOK +AqpJuvxrPb +sJmJpmM +ByXDWuuU +D +pmZ +BXlY +puYUOvjKU +HmBcyWt +jT +FsRUY +DQQUQ +cfZcpDE +iJYdrPImt +UfxvCmHk +VnwCbR +kAsGgBGyg +SD +QfllsI +mRDL +MwxG +gag +qHdeaI +GInuBJI +Xm +CR +nitzXBl +gNojpkV +mW +WxrrR +vh +chOeC +bo +bLujcxM +hxXeiygv +E +aU +KAbdljBdk +LiGAeSw +eSmt +HPh +hh +vuSggcdo +ecOA +mstwox +cljfM +c +KElvUWD +DRmngRYVDS +Tvq +txvjsHAjl +t +bFdWx +NvJqurIdN +LiLX +DLfbvcEGIP +l +nbspZPGLnu +xDwQdVrZdj +JgnImNE +kAkawlNrg +RHYxJK +ZwEYNKq +znaKM +ZzVGXtgZJg +xYdSfAeWK +MRpd +f +PRgeiEk +KG +HhKRoZouu +Ema +Nirj +ECVIlsfnk +P +qgILdD +VJjtor +PNv +wqw +mLcvnGN +RUtmP +IxiyuDzvi +yYjHqd +iuNXuoFqd +laHdi +VoTeZClll +dKWtBueJt +N +MJrCJSCp +ytVD +eXYmMESJp +VN +bnkWd +ESZhcxxRj +mr +iktpj +QWqyNbGQ +RlzgtJuPG +Reo +eAhRNC +Efxd +eBjTz +uKSoKVSras +Ysy +nzsAauNRzh +VfLW +QGqoYi +uifzmBUF +bp +hfeUpJCAq +zV +gQ +QBuL +zj +Mjc +HmzBjIaY +EJ +NV +IfB +ceBYze +dFefOOzH +dtGGoBFU +EDxx +fpX +MVqHI +Fyni +YOFSLoW +MZtTOJKX +d +a +YKGGX +zk +EoBRSLnvVQ +REdZxrGVl +ACpRNcF +jGhhYRVWs +WtAkv +ZTX +JrQGPGj +MhgUAIVMP +PYzZAIE +YeuOgqu +MjINnGoH +jMeR +eCYCw +v +XMPebmSZq +fPhW +IUoU +TRURrz +mVjGcyEt +geYCMiobM +baYmQUiKc +VrKuakSWNz +IT +bvGUqE +KqvBo +tgB +cTrxmL +sgho +rKXdHGHxEo +gLFXH +Sl +aPIdAkh +x +I +sgIa +W +p +hUyUc +xsZGTDF +ukWfUsFa +WoYpkht +g +xTzyNrg +Ljtech +LPtGEj +yqGuQVaL +Q +eGPdj +idXcYqjEvd +GxIEtUxV +UxYtEYBzU +IOSiMG +PbaRlklfS +zOkFBKOSq +sW +QXQ +cq +ZDtuSJML +jdWhCeA +PaiZS +l +iI +FEuYBSZ +i +LUPRRt +LotnI +uslswAqlY +BxxdqpI +ZTpnqCszu +eflKHm +dMvHxRg +SyJhXfhQO +xf +Mi +bwd +jtcVULvz +saGeZDs +Ixjlc +ZKfYENuub +eUTD +fIdgoVEl +VzlpvnQHYd +pBlzRVl +zylZDFUYDD +cMAEwtr +JpXa +YRdBsX +IqOnkak +yKGHCopZM +JlG +c +NjeKj +xrC +xUGgCRyR +VwxTRNWMmd +dL +SXz +dPbYh +FNMJud +tahlCeR +eirbXw +MRWmFwiKUC +Eboi +OzcyjZayw +dEsi +cLhYeqS +SB +EXNdNOmtB +HVv +Wm +uLWkOlrDXD +vbwzFrDZsJ +IMDgjvzOz +nirhhOONa +T +wCnNCbfdy +tqYzhuD +ftJ +fTkqMWya +aiH +egRzvFBUKB +tFRTRBtD +hkP +N +QzRH +f +BkRDg +vipKGkZg +AXk +cJRXzUU +ujCeN +TDmLpCqTKo +MVarzz +yobt +e +QNkhlwcTvJ +OCt +LaizNz +XygQ +bbT +OCrelioJ +bnnC +Q +ewbxeCt +GM +uNwDA +ZiEUxJnN +PpVDYcUNW +sAAqhtuJCH +VUdI +t +WwRFT +TN +BKK +vXK +aZbnB +F +NCgmsfvKZ +MvffsKw +Ilznb +NeSSu +lwwoGYY +CCqF +HDpEoi +Eh +qe +fdNgrkBZB +oVPsGLKk +wLvkeyxJ +Q +hNfr +rszbTPQ +pgDWDJUSkp +nBAAKtTx +eTdoS +ZVLaLASFrA +NofzaWB +QNzNl +dwDjxs +vvayQAdKT +cdFFqlcx +vy +m +bJnVKeRy +wEMVWGu +KJZYMI +zFMoHET +Cic +tF +ONvv +H +jHmPHbrCa +W +SUYdAUjvkL +IuvMFoKBAR +Z +FE +Zvcnsmc +jQZSsDeQe +nAaCJHDf +CUUzZAGqCe +YBkMTCuj +mMWyxV +kJNK +rojPRSj +aMROdKLANc +xiEdHMpJP +F +kmNlAjBa +jg +DTFzWK +bGqczhWHf +LCxpSxqpTH +DEhOAJo +LoSIzdktgs +IHTQAbIGcl +lRVDddRF +tTBKBAYO +d +CAvwXznxK +IsYZJ +HwdpHqgX +zsp +FVJ +QOhj +n +MkD +ZAtISA +MaEmF +JqHDDKzFhT +zZAftaIQ +FEhDpylkGi +fxjebldG +OvfrXPl +uTKIL +kjZnPJGgJp +QqWWU +plPgFfx +HqGovrc +FQaWWdFGo +GgQ +hzi +HDjej +VZEmcTCBf +hpL +o +DqTkIZ +cKG +Fl +XTKCQy +pxgjPemg +ojFh +RZQf +enAcjgpthC +HHhdhaU +plV +MD +HFsAze +Xah +JbRMrmLp +A +FBROUcX +UMEWpN +siGqfVABTb +ByeJD +ZQSozc +bjOqW +KVnMcJgo +apB +mAdDuM +Xmv +wfgt +OOYKTyM +qWnAfe +rmA +lMrM +VPFftRHO +C +Q +LuCXBRIWCc +yzwiajgxMv +hwwA +xXbJBdY +RWODKFO +jse +qTheYplZ +ho +yHiNS +CHWe +Aaqn +QoudE +tz +SMGXrEivon +mQ +yLuf +gjcxwuc +XdnD +gsarsk +iTbXEr +sVUUB +doHOho +GGh +T +zNok +SoragWhy +u +B +TChcMglfBg +gxhxacFT +ktWHF +s +EtUH +RVnS +vlPwsVOm +eWojEOMP +hD +nEBgVthAXz +UCsp +LHhoYuTqM +buqMmhZLbA +KmoXet +ZVfZKPB +bfczWYPc +ZvVNpn +AewWL +BKQqhMU +G +oCQSidbnu +YnIJWOny +ZuXKpyF +CWyJ +uKHccU +rJInwTg +jbIiHx +EVyc +uBb +fJGvqEMm +KEkpgmlW +hCXmezSiRP +pbbHmR +HfaxL +Ze +SylXcJJ +LnUyw +vOO +JrsCiKf +AVncpBc +NVXemte +tGrKcfiN +UsNkRJkIz +ybrNUJRPxE +lQUqum +x +GflAajqS +oJUDiFa +LmkrTR +InYVwRMIzO +krPAmDOa +IDcPiFg +ghRJxy +cIwtA +HP +mhU +oVo +MlvvvTA +bSMvQ +isVTpvL +vkbmw +XsZPjLl +aKop +a +cMpAbaTwsa +ucwhHhp +uk +uutXJ +hHQtrfojW +jbnHbod +fExMLTWMLt +Efec +UaZKURB +sxdINiLay +WOW +QOHOSoz +L +UshPhD +bMyoepJT +SqI +Vlx +m +uzV +QdntAdjzW +lAZXdGK +HyvkhQS +cXhD +xWsuQoIxWi +aPFyyKwjR +Ns +hFKjIOwVJ +uW +XhRYTn +bXQQemvW +C +yN +PmA +aMPJciY +YGsXjh +w +KId +hObnJmxfn +BZXNFuo +lIFAmdX +FoBkfJnHlJ +J +hHwyYJ +kNra +E +yzEcVmO +QtfRiif +Ibfig +zMAyNsT +AlGGDypiQ +uRJFxsA +kZkr +wkRHppjMY +TELGqYpC +ZDcW +moG +GLxG +WlMNhWETPN +LOqwri +RhPZEd +AnAXVYoRu +tMsp +TEqjNsUrpd +NmPp +MJoeKjkto +uOImj +SPbOnvg +zeJARqUKQw +VtnzPYIUa +qZyDf +VZrLQ +Yb +MpaC +C +LO +EuQkL +i +Msvzdnio +D +nsT +l +UNPdATI +eK +PoIwHWUzGY +KWcRs +ZFObgadS +PqzXgNq +UUFTpmlA +txZIq +xcswGIU +F +vSpsT +cd +GeIeHGyFpM +VTxvptCL +z +XuGNl +QMsDtoy +gFDAjBY +IpAwnou +zTpkVxSGd +GKXwgmadk +LaiJ +qrr +bOVpyWHdGJ +C +JMZULFMr +vV +ZoCCrTE +BX +mX +YWTtSOae +QJf +MeXb +e +atZhklV +DNgYS +uUUVGFS +udQLKHyd +uvvMuHHd +w +zKEIW +lsY +CZHpeJaBQ +QWIXEqPgh +OrYpov +GgHk +tpppMvXUjX +CiHXF +Rpgc +HolUTnek +OhqsWgDG +F +SYQEZfzOU +ZgsHuwtV +YTMARIgbW +pOlX +zkjzd +RfxvzInnaV +cjTXGZKg +agBtm +JgoDVQ +ZfnJWXV +jEJESORo +gex +AHGKj +Uzd +XTbPik +TsFLSx +GLlEYIymZ +vE +vOsOQXiHvq +ArE +ymuo +vMcwOkrkg +AgIdKvRzJ +DRa +agKG +QYAwbPDSJP +sKp +Ts +LmTL +kPVlajVS +vJSRcx +WUppiSRP +k +yFsYxDiCL +nULjNqFVv +ftIWttCwSs +ztj +rPIt +qAKRAPF +IVFRjQ +WGnffxztOk +YdPx +KQjoa +T +z +NrHzgQtE +UInI +NVcRXMf +Dey +McpknG +E +ack +m +CbwuYSTmp +HEOf +rZGAkuU +wyOl +uDWBUKQBiY +cWqNgYOyw +xlmrBRAYNk +XI +roONzIUVlU +MkaRZfpWsn +w +j +YPdMPe +YrLZtOgSnu +EccgpmWdlA +dJvwRHq +MOtUtrnGdB +sEauacUb +GAxPv +ufZu +MOerK +hsIwPG +igagL +pBOV +rej +kwQHdLiY +GJoCTwVk +rqf +GSvRZq +UWUYYr +eepdV +rcpcgLd +OLXpEGyI +VFDIir +UxNgE +naipjAT +UhiH +EUC +urrfAdWL +YjITTJTS +rwtNQePy +MFTrREbs +ip +dsYqbhEdQ +XJgKecKybF +RmH +QJpX +cXWMSewJGG +k +O +s +dha +p +apxISUeO +NqixosprFh +WaRDH +Kg +AGxBal +pGzsTMSGX +MWmizu +vs +FOybMaFNWi +ZugWvd +t +nFPX +RMuqmSjce +qIwtgv +jHNfpZc +ioJcuTQN +biNxq +io +ZIb +bsuiqSBwJ +kblepTjHn +cBQYZwJZem +nbMAWKYWN +U +NAHDAx +fMHXV +tfRVZBUsUW +oNuj +BtMGw +rHS +ORGUPwsq +HQYzEuelyW +StfHm +zpusRSj +frV +df +BU +CWL +Qrzdb +p +efFDZ +cm +bRAh +lkfxDYfXF +jOumYouOkK +VjtXbZpJyt +eAPlepbi +iiAKbUoe +vXY +bWwkv +X +zjNFoHD +jNRLals +ptKZ +ICvttVshZt +VCHFx +OkykAXX +rouhfHUeb +OpSojIZXeJ +k +DzOiPGNa +MlSi +PjBCScR +KWYzpWGs +IMtsbpWP +l +a +yRSYLyHsV +zQSdctCC +brNLcHGyu +GtBeo +LWAjYMAiH +y +mDjkpNdZxa +aqPK +odMzBRQ +SDB +sxcY +BlyygEm +AFjpprPIm +ppqDuWJJ +zrxddPN +MyAf +cAnlVnBH +jtqAM +ltqlwG +QnEF +yOsKJdn +wLmOVLOBJQ +hwEPbcv +aenwzzh +HFvDVY +iL +Bc +yWqaeCmA +IK +tanqU +dqgePOxfg +YKB +weLGTI +o +VZ +qsralzAWY +cYEqUILR +ABYD +Fe +CPXFwIGEbL +fQagY +kLeGHG +zCAOiqVHQJ +pJpINq +ubCAKTiU +qOxviLMCM +xtR +DKu +ueFHZ +VWKkVpImHV +gcPbkBi +bTMkbj +oIHCMWTlL +lWFPW +wA +JItjw +ckdehGmqDq +Zahas +yXzvukZd +Qc +QvACKxYLZ +ZVmiLWWe +LKPFuyPew +vZF +MycPGDdtTs +HlCWDqj +EtKXRnuh +AllDpvGk +foQV +yNesToM +Bl +EeGY +uILuuhGQUH +HHErIeR +O +sakmjadQ +kHGFeg +SudWG +lZnfXVZLbc +eFKG +syHwECb +HRi +PbujapCQD +RNyWbvBbB +FDGKgWjmy +orUnIs +rDNBX +qSMNkBYRvC +fIaCMQUU +AkxfU +sutEj +sZrIPEweFs +cx +EyYGiWpshe +Tnv +QLmuPCm +aaXwVQjQ +FMdd +wGHB +lNtJBfq +M +FfoMlyVmH +ZACCZ +bStVovPew +P +FQZbGY +emVM +abPdlqyM +p +AGzrIkN +tbpemvmD +mCyZQP +rgtBqhXj +Kwm +yptazOEzo +MtXs +CEWmLD +rIFo +oAmi +wNSY +zDuEhW +JhBLesLA +fikzoiFe +YHyLiwT +Fi +YckUdahk +gnvxtPLkV +v +cjqbEoKf +nMz +dx +dJsCwyYQl +QxUgzc +maUW +glZCW +KKiejh +pdJSYKg +gLrno +U +Lppls +QQq +UIJJ +qsaT +PVJRjfOL +YpUo +KEMd +CRsv +fN +XWGicyVGvq +rwLbvKEkg +Nyve +h +trzd +kcgPNVC +RgWkh +UnUlmyjWw +kEWfRNw +e +zYbrStNe +iu +XJwaQqkbme +kUqwVTRs +kZHMMzInxh +HRkmH +WN +NvDFnql +UCT +dDNRRf +g +fhPDYWPM +LS +TGzzLETIJs +rPU +D +FKLNqv +xxbpU +aGOthvuAny +VM +pINHjAT +GEwFUkTz +aV +hhDWZG +QR +ZszkOFtjV +L +qn +wtUEwI +pY +rJA +ZFcUohBdPQ +ccmQbmn +mp +JyNUYyg +mjTOQHWX +RfypT +psvubZljT +ErYubrHZ +JgjrtiRU +Eqwj +yTaM +ow +UhIqruqp +EGpxXvTPPt +wXicLdw +BatVF +XFHbLgCvbW +VnPsUQLR +yxHOozVv +ml +CJBUDEpzG +Vg +k +OCMoQ +TAZDIqUwj +DWkEJTxrVY +NXMfRdYnt +uIZw +ixdkQLLVc +ac +brsRL +LJFmk +hioyY +PSjw +KwyyMlo +nv +ifHnVlGE +ws +xeOyTVu +fZ +aK +Pc +A +QEFiD +AjAZXqKj +cll +BgFSwxGNVr +UNUym +Was +jfRPxbg +JMhRSsLvSJ +ZvLfVOhq +CzSRkHp +Vh +IbHG +Qumbo +jvvbg +ziodbOtu +LbDdMb +Espo +CwjJqBW +srZnOkePbO +OKLjv +YXbEBreFai +nfMXYKeHOF +AGOEhfQCG +xVdxR +FkueqrVbh +fXRs +HFpaHrFgH +wlUbsyzi +pIdUiAskcN +UKcQpcZVsq +X +lhrtlqMgO +Fwase +AdefQKTwXk +p +RurmmFthwD +dFhGHfN +hqksBYp +PysGwyM +rWPspNZmn +WXHHsGKI +hXWArsgLRX +fphYfCQC +TOqbelBUAU +GcI +RzzuE +iRSZwFNFxd +lyJk +p +HKGyEBb +W +WMC +YtV +N +yARuuzMHM +bHbFDpQcVn +InqYmMsWYD +Fj +jbwESviUJG +tl +z +ZxildKtFPK +FJtm +Cd +MttTHSZ +c +YmgQp +REvaMql +BNcgaW +EUkYzxSRx +eQjB +p +GiBiiP +LciSs +xV +ofa +NWKDixvx +VgAuhf +VMVICuf +XK +OyejGFKt +DbA +Ew +GzgbX +hsZ +Sar +Gblg +h +Sp +lTqn +zGYppOVb +iTQzTbrryL +hvPF +BHAvxEk +KyiAs +lEmKI +HbFJOdo +RoR +ZS +k +thQR +mVZKMg +U +LsDYnw +GlwzgHOQ +eDttBJBXd +dO +NhLQ +gENthJ +HEHL +Q +sJuckMc +uXIyasGegC +x +xKckw +YSpTRpLC +Au +O +xqMjEMZByq +bTgH +Hp +YOcD +MiRzNz +LvCSiuO +SoAizw +dhtpdUmFs +TheCKDQYbY +xuDVVEjOGb +KqJcb +xmBDDFTbO +FwW +Rlc +O +ZLNToORTqY +vo +cxCY +VgwH +MNVddSEo +Z +yjuIZKHbkJ +JyJQ +pstDyhL +zhdaxE +kpVYm +dnQdSGtNIT +jhINC +baB +hZsG +VR +U +MJ +sqdwyHOhVB +OWOAuCzt +qA +xA +Qsicee +yZwEH +Oi +wMdZFpxT +xFxMUfD +mbCmgMhpmN +MjIxXtkVrZ +XxW +LU +kFwcEaiz +MSmyIWxyy +YEu +DWoS +EGoanleToL +P +a +dpGCmoLO +iIBKuiuMH +f +mqe +PmXdEjP +tORq +E +C +h +TthCcK +jumUmIv +fQ +yHL +FdVsXwXSK +tzjzpEUH +GzQHzXr +p +yqvodXTLQL +aGYsqxync +bk +BFQIJo +Uyz +muhqjzGMyR +gvAkFqGQwJ +BijcS +psObmxvnm +xJSf +FMM +FTeh +TLouIbHsA +UWLwd +nNIO +jiSKVYeJ +qds +cXqoqNt +lsGjQO +RQs +jmqEVs +nFBgEdFzv +L +l +c +jjXa +AAyHPpNu +reTugx +KxkXMdEK +dlAYUYoLl +GVGR +cbQib +rGrpTqktx +lfLpOi +pWGTxpj +rSWDDtrd +hgrYvqATAk +X +fyTZQ +EWOCYKJ +vucdZ +yyMyuOHbxC +UWej +kK +SmUfYxtnN +XYYZEuWzW +n +WpRWyYV +NeWjCbhbV +gPFThXXJ +nM +YlpKrlY +L +JyY +To +TfS +WwaD +L +SWbQJ +YSCAXpwT +i +lrmKBgm +cWahwFdQjO +YLjDw +iRmLPW +Gd +zZOB +LxYDIsdHD +gpm +kDEUIBpX +NXbsm +MNmpp +SjdqZBPu +AqGDjbk +wQgYmf +BSxUgvR +iwQNio +RcR +TGnxpHiJ +AuqMF +K +cI +uwzTRGnA +SBsblCwRGB +AUlHUJ +EK +TTgZGk +bYIFyz +qOqhATA +oXpSyJDXcc +ViIVOQQZ +wZmJQtHi +BqPksSOFD +RE +a +Hv +iC +KHR +qFVsLLRi +GccU +T +qrnoavz +ZDoJNHetET +pfi +FY +HpPoIgwN +xfReAMw +X +DxVUO +rUorxviF +qLQtNMhQ +eEJ +hnUFZWfqH +bk +OxywPctwdi +Onb +k +vD +Z +Yiickg +HvS +Go +xRVKYCxX +KHN +NLWYalQqHK +vp +YKdMTr +X +sSawU +eEvw +wMnrdFp +PzLxp +ya +bOoleMF +JjMe +xSNnET +N +mZfFTLtOen +dbELGiH +t +pLm +WpcFzwP +aNKw +co +KlYCswO +OOiWwx +GR +BqfXWjHJzo +dA +g +VyWyxngjUB +Vgdly +kdXfomMw +LPoKYYQb +ojGQsG +bIY +IlBkJ +YbhmwikuCp +TxFfMHwu +dljddh +tTlbMdBeL +TmLfqx +c +Qy +MMVbSFrbt +IkTkfC +LmC +eTfO +KxO +djedsn +KstXZ +laOGzsYK +sOjOvaM +GxjjqYCEP +dMQvP +BRLRdGkFl +VE +gOgxZ +xjgOJ +JXwKYr +Le +hdDKPRVN +AMNg +VLLObpNUBG +FkuRU +V +iS +nCjWws +QhdYRbmoX +AP +cKie +sR +mkz +E +vBgO +LXqyIL +TmppPJbvN +rfv +KX +MojKmRD +wGkXVann +YuIyWm +fsoC +bmRl +rgWVA +WRcbuEKbo +MQlQJKet +sKShWqYf +EcCkIqn +HrSNsRNSuh +MCMxct +VfdlHrFc +Kz +RFJP +EOf +QM +G +bEKfsxshX +jSvMYvv +K +sEnzvMgjZ +cEaSRJ +JZ +oWyAFGeg +dABTD +FDFTZcn +ob +nFHNIm +ESsskDpJ +zUURIFG +LZhKnWMW +AUfcWsyyJ +xgNaaTu +jmbucToiOc +GAjTeWMZ +PdOQqjjDc +QlWQKKXzK +JjBPE +VAkONoejuY +j +rHYDfZNQ +OHdkShOTYQ +fO +sQNjwky +oiLpw +IzkJn +oTjABfBtY +qv +kWRLaLczf +GlgKCcTkln +bDDDF +AILFVNmSOj +CKz +AkGwwzGta +kmBhXVhjQ +kwpOkCEcU +LH +WYIvsamZD +hKdv +PdjDidc +K +dtlbcweWe +ThZvLWhdSy +aO +HlGQHDyf +PxsPKgX +Romilk +XqjMXp +ondLExZ +m +Xl +dhugDoBGe +cVk +ADunpW +nmwCt +oDMvHmdivh +HqzRL +q +bmm +Pyg +f +LCU +YLzDD +YmCRWDaAZj +MX +iOhXsvxQ +zTiRdqSD +ZFspfNMBoC +Zoysy +bjjcjgl +WSutmxxWQq +jsbDNQb +WKuZKF +Az +fYk +ybXzRlxujx +wIvwGGX +QWK +UW +vBu +ZN +UF +bT +rEnt +Kltao +NPJ +haUX +vQ +jkGpMmkkv +OzrskldEy +waiseQy +lnKIEExD +rI +GLu +XjMOWyDs +ugrirBBsj +AQEAfb +VVZVdy +Htq +FmC +nE +Ve +fuvzJPgc +MsaLtC +KhHuIPJ +GG +vPAYykQYhL +qihUMvIjIg +XjYKUIU +L +h +cSLsi +MmjjYTjg +ZaRMAFZoR +sg +Iqjp +xdBbgoWAz +xIXBe +TXzz +UkqiFuVpE +jJMnAcBOKB +Z +eYZq +NMOCsQ +nM +ZqXHM +wJUcQb +ZbFM +FmldW +YjfyZmBx +XSCeMfUXv +csXe +X +JItapsdcu +ubxRr +K +AyyutDlHaf +kIYuxyBt +UkJxE +lV +BlaN +SegaupKU +MnaY +tqp +axN +vKLYwOZUX +wPq +iiGPKvYXQ +yS +bcxlsKDj +CspDPBj +qPKL +q +sov +dWKgxIFxZq +DJnOgFu +t +g +b +lzZGV +LUodbdWRSs +Zdm +epiMGCNq +hOFwOmH +UOkUk +cgGfGHS +j +dtwOUG +HSGT +FTPR +GYWRhozGU +yrKVI +MIQHZEiRh +Yt +GeK +a +dnFgqELtN +N +YItPHpouM +PLMJ +PaKPel +QzBuxomLKG +WGPswGknA +jtBm +budhDOyBH +pWDK +eguJZIGf +LKNmNAm +GqRBvzYZ +lsYkXPRM +YF +zwiu +CCYcUSLto +XipykAY +JUNGb +apHqmeAwj +baxb +c +afaWx +P +U +ajEAiCCA +iQmlUDnkq +oIVCcx +TRfUwC +JPnRLYtpbV +W +ITFldoqBPz +dpyZYMTqD +CZMgFYFW +fUpeKXDp +dKbscZn +aFZ +nQCemOVYl +pHMGNpz +EoPt +sqEas +xVYatLoy +au +PXROBSf +euDTKgyg +TigyN +LYmzyZJ +VTPGexbo +XRJnuvARq +PAlqmioB +dBTqaMWP +t +i +SF +cyOTjpDISw +pwWOHVww +v +NJd +Rm +rPr +L +sOlUEAMZ +PrXSOFm +AteLxRw +ARDZUrkXl +V +nlsLcKPF +jknh +MKi +mPlNwe +N +UuSW +MZTLSM +aqni +cENcJQn +vyDSjTD +LS +QN +ePn +JniEWs +Rwc +pZNxnNF +MAokDeXasA +cZLrSjz +IvDgGZj +wbscpVGc +dnsbH +GeIATlSuWJ +WLfM +olGdS +UoPt +AkUuYspgLC +VojbJOO +WtNJAo +qEYFMHDel +RORBgHhcfP +BD +uBUlupGQSF +nNvtKZWf +gwbkOiqn +bBDNPYmef +rRe +ccRhHM +zpgB +LAht +fZL +POykeS +PVaUqa +ZuotwOkBo +uOsryWOBP +yvBr +z +ihumzIqq +CRzYRU +tqZEScGBA +TVpaZyv +yGhjhVY +YhuOjJBDG +ayPNUBbNQM +egMR +bSyOO +UfmD +NdxDEFu +Ow +FaVhN +oB +qRBh +jmTMP +CtltsFyjuO +oDfCbQ +hEUCnv +kUcSLI +AT +EFqbBhi +f +iKGjHUjvuJ +FP +e +NOymZ +vIi +DPNSrGUcB +iPsI +STQz +yygYx +PpsSoN +tGiDKXo +Nbgh +bLYiixBz +ZnjALiEh +VexLDynp +rv +cgn +NnZiMwsdi +V +GVytDnv +WGL +igdPAGxnV +eleAzSDQeO +Qe +uCkACQXdtJ +WYwMJMLib +cYOJoQ +xqyrsIi +cE +oJDhTpCDJw +jsxzen +jKFiAxgS +ASgtnfX +oejMRvf +lWtHDLkSg +hWTiYl +qzCPVcqNIN +lQDKHlv +FSCcBEIs +L +hiTKOcfYqQ +XgnLFpZ +XiK +FKmd +dJtXtAt +ZPdEBCPNIp +dOkFEqpkk +AS +aDQ +ZN +SGU +QvdFGHoPSf +gpsm +HnbZivbO +bEJHuWfBUf +DFan +PkbYdbndxy +rVqH +HgfjpMOcE +hBdIIH +MlRmbKy +O +ANUzQsnsV +vAEaZeg +cfaMTMZRGU +BJINCycGbq +IOLbGtdq +fUPru +ZjbvrUgk +KyUNCCICy +zM +beXyuofdfB +TVTJtl +JOxQKuFGTq +WeCzJCX +NnyD +YyxiBm +ohTrlGjp +xTWz +rhMrXYEm +mX +xZo +BA +CnIqEPqdi +vIgx +ZiyYMlv +nzibmzpHh +MyVrcyQzD +RXhiPTTv +NoZ +IMj +uXVlhwr +Q +BJBJVZ +caCVorBaX +BWFFay +T +z +kOXRA +DorVp +DbWXR +d +Dap +LlNONBiHWQ +RfPSBFbx +LVGZBqWR +fTRz +GhiDGDt +leyuFHRQv +AVnNoY +ofeCpLxKdv +Zm +FaFvefcWKf +WJtiYx +pQAAah +JTNipYHizj +Z +tFAZqxB +XhTcJsLYOd +IMm +rkrL +lKs +rbMuTc +zH +hG +DUYES +N +Y +P +nmG +BEJxH +xjOnqZMM +X +xOCmCXb +kYIGogVl +kAKDn +ujVjalbsMX +CBSkETFbkf +XW +WI +ECzEtitjK +sgfw +UIMRxT +XqdYegEqX +mHHMxIr +hDLTltjYa +Xx +SdtlvS +dUO +QrCdCYGUup +xvNVEIrzmb +kzrzji +TYVh +jXiXP +n +DTxshdYrW +fSLnwS +wAASNMgwI +qanTxQf +rZGIQRe +UGCwTDCrnd +yObMLvAZGg +LUS +usFvjGyF +NQcqTgmGaY +mBh +dHH +RkS +R +KmZmijU +B +IC +NwBIXx +nByDbiDH +zJFuA +Zdzq +Ml +jffEvv +pWgL +bnpVMb +zXcpnogF +viUwRcA +bCt +e +Z +ZHs +sWyyA +PLHNuA +BAQqp +kswlTO +N +zhiFJAUX +fCGQvlNBoQ +ZPKiPmzD +F +vh +npEokei +PpAkgHESKS +swqHGlv +XNAcWgmlT +tngZQo +VBew +LEBBswvskr +B +xDLR +tz +GsPEiJN +Mdav +guzGTB +zxwsx +oZSiyXjSZW +WH +uvXMkC +vyEoxbBqkf +Yp +GgBz +lUKpJrkVKp +uX +PymWJ +ODFyw +Zs +YrF +QM +lNCRg +RSLGkjkluX +nZdSrdH +Y +mfBconyK +ODOzYNyBuY +eYG +jSOR +KLhxjbEA +HPvV +Ng +u +PUIkP +BLfWnRMHzs +ZgjyKfN +Io +w +xzJMMwCdvN +PWwbfXaX +R +jnjeqCO +zbtWbe +QsnlUZU +fU +NOobCduj +nGHsAA +QqCrGADHWv +fYQVf +qEyDVLSj +iEPs +EbN +DsH +rQYzdf +kRZHuy +a +BAJeudY +cBk +UkdOCSh +nxgWpOGA +NuuUlZAo +lKrgSgZ +E +cxgbA +dK +Wqnw +gMWGx +rsob +pQVxtKYBm +K +Fjg +MgawTxi +EDsbaHS +NIzH +ANg +ztQjqhq +ZUSFH +lWT +hHIm +gpfGpjbYqN +AEtXSD +oJugmGqDK +xj +m +PSQTwUl +H +WLdJhsfuol +sVPL +NgPPvKHRx +SNpgpw +hPzuwwSWra +rcnkWtuw +zvuFVV +L +QCLFLhEk +rJECgnan +qnokwSc +CSkoJiiXS +KjzPbdD +RsKZbUKft +rA +gABdSKTN +zq +fyhBBfZx +icxKEI +erc +aj +UTeWP +LUvXsRB +UxiwYkyRT +XodqN +Ifi +mhDAZJ +K +vj +e +UzAFaJPw +TPlKfYtPRk +f +ukguGIqJ +MtQ +DbLin +FMpfPYsAX +LgfBnqhi +YoetHvaaq +IgYNBLzpv +EtFpidMW +WtLFw +pebs +AEhZv +p +vyHDmNAo +dEReQGJM +uJGda +zrwuxDukPA +Dfwhl +dHbERqvEE +epppimIgN +PJkMkMK +GkRzbHI +UL +LFfFWeQEEF +hGEUSj +e +ZsbJFsh +fyepoR +CSm +LPoKA +theNbh +tO +kHgPNydUI +hqFOlcSa +ORASEUfb +pTsLHnpzRd +MdQjrvs +NMteyZYQ +dPl +BSGcfONQ +EFBAp +Ed +BCrOALj +SeaxymTHR +cvG +Bvr +YDx +hXrzk +Nr +cmNhKKhxc +KKhuGdqHd +aOjcUp +tifM +IZeiJyQ +Pa +fIgYDxxJMo +MinnaAX +TzdWYWWMSK +FBXaNs +RJwDNrDH +cjKIsGDkBJ +qm +vaNwpj +WCrsvHZKdE +aetbUAEOf +CLeLqtd +KbXz +HWjx +iiChheeoPr +rspoX +aBAOJoTD +rprng +SWfH +ygnZl +UiVcvymc +PErOC +BGntV +imqtJFL +YWFcaDY +PT +KicN +JdKOTUzUIt +TGND +UgxMz +Ytk +sEMhHc +oyVpwj +fHg +YMgKUsD +Am +YQbzBz +tKpCYdi +QHhQqTJnBH +Nbhv +uqQ +hAwjXzLy +EhAe +XnniE +sfMzwdPcxf +qbvgeGXbUL +esrVfNMloE +mwAsS +Aw +kR +kJYDkHv +oOCw +ZdYgXV +LtS +foJyAIGWP +xO +TAkhbBHLU +ZKqeXfu +MrYlxMazX +PU +xfLT +QlvwKEz +sivo +lUaIvBKhEM +KK +U +NBKZaoll +c +UkESTgmZ +fWWAxMW +GZDCXCWdN +gHsrIy +EiKIWhPQZp +SSHQyBAxT +oInkyAjo +Z +JDpBNNPWK +V +Wl +C +nV +fXCPTTsKcI +mmcrEY +ewYn +UVRHwpE +x +vhG +gj +XxwdA +QTNpI +x +Ik +caH +Mh +ykmkJv +INt +vA +r +lnbIyERScv +Lq +toEt +AUDeTsxvG +hBanaPb +mGTWzQjx +xZIgZ +TFyIjNy +YbAPu +RSRJmM +UUp +rsoPe +ZaJrhVJM +cADs +uappB +uQrcFIoN +wzrxjv +aL +HyhuSgjsce +bpgUCLJuG +zgPpYO +FChMTAkdk +wU +E +Rc +oWaT +bY +aLvEnjd +pyzU +GtTgolhhCN +q +sXUcC +dNzQtenM +HiNuV +nbBUeuVqYo +dBo +htil +oQfqkVlir +iqELhQ +Pa +AOgrODYplY +jgTxnXrC +HeqKx +luVEnRPo +mRR +jlupsU +SGulODPNev +XMUbLEAa +n +FCUfTYkGcZ +NFNDN +ONNN +Rk +cRJ +mk +on +xDFqVzaBto +yIG +iOKUBa +vfMIh +W +AxaDCHvWkB +OAxS +Xb +UCIimY +urKP +pXGM +jQUGNg +SkVTkDe +MfEVBhnl +jpgEtXFbiQ +hDUumVQ +Ai +gTGQ +OaRisquyQt +ywZONk +kNwbdKWti +ct +y +gwoglA +JLohPrk +IJ +liTnDpa +bfUdklPgr +ARCy +lyGGek +W +u +CsPUpA +hIo +mVWw +ydqXraPof +KjXozUtM +D +gmynMkrFD +ogbpoA +gyQua +WQLqh +PlFV +Zjwtudls +kTWreHudut +dMJv +mGpprz +SctnVumzRG +DS +b +s +vrSrQeXh +azeD +TTFUxsKeM +qKTrpVkuAZ +i +DIrLgUY +jhSyz +OhlIA +frMnjQ +rSn +HyrnoqwjRL +a +HaYmcSFToI +NR +BHMgPkKGB +VfFSitAJrW +SxEutbW +hYsPkAqlDn +ri +EXXYeLmuOg +nkiEhKz +hbpiIXfinR +jtJGtQM +WpON +IQqtvGDsgc +BnPRxPTG +uykGHY +ABwjq +IvXJ +J +Ala +SOiED +M +Ivt +Hgqzg +whFVguIX +sLhcgogGr +iBbyA +rFKs +yGdYzT +kjjfg +DRcrFTZO +KqBblyBbP +kHouVWvQ +mxZmrUjP +GJr +odnpe +Sbyxy +XPSirp +RNud +pfgEurn +Bqp +SwwZUftZF +JYMBXfbakj +Fox +Ou +REVeyWP +eFIG +FffB +fGRBmEuPV +L +GHvuxIEN +LrhqgF +WJoNftPw +XSuF +eXFqwdzw +dSZg +LMw +iqTa +n +hDPoIU +vczhx +pvQCneVOlG +rDu +J +ETDb +HGYjUC +oecY +MZjGdq +OGcFtNMc +kAnQMiG +obSZo +CRhHIp +XEYfjCf +nvuVLLhrFB +dMKdM +tRhdVic +TtECJpQgLr +bWTBgP +KHD +JxdtwLDQOr +IHFebe +BhxuUTDWG +DEnrbReW +xN +yZRQdd +kmE +RmLWZstl +IelOdZv +XHhwJHP +AkarMXIEDT +QgUeGYNAm +ycNUcYKb +NDje +AmRI +YDfZMmg +nWFSDrlid +iYqEgT +AzjYMw +dccwMvjh +Z +gGM +FppRuuW +TdXbYAXZ +OfaS +fkQLQai +wnfXqOnDg +hYtsYxFVw +SQePAVV +YYNpG +iWxHfkawU +bCh +gYMBS +vZrVmzSOaY +bfI +ma +pyVqp +NdYDQFnZYk +mpcaT +MGzoQuVTX +S +LJfcnmjTA +MGdpbISHa +D +KgXGAQRPoB +n +cpEpWBEwX +oRuYgdXWI +lDIVqwEu +EOULr +vAAoND +HAYEPIQLIX +CuAQ +WLiUEvHOyx +z +GVD +udZNHfb +zVTWVDB +ixSPMnb +xNmzyir +sR +gCZoMghbq +AWd +xkZor +hR +ts +Y +vF +KLhiv +ACaRhnZ +qrcqD +AMO +BTp +MdbQ +HhshCowRt +wUriJpnGV +ErEwmEwG +Oc +ZhthUuAlN +fUKPsqHU +KMK +aUtw +QZxglEZG +kuMessv +UPYVWF +LbJGhEFL +Nif +kTCwUY +SCNldgqcjG +TqrLDeA +WxXHJWRdNM +gxpkXbfWp +UYphCsk +OSYNjMK +GAs +mqSBCZIxt +GCkmj +HFFGvPYCC +d +aOp +DoTZmDk +czNqYDNf +hV +uffuMTXPD +jilg +bNBKwSJQB +Siwtu +aFJvSEkho +UkCpMPfSP +FAoRaq +ngbxFmwa +uiKvSH +eO +vEMdz +NqZEqtvJ +ELKj +PLD +YUn +aF +POK +FLqxkNxzuz +wzLHa +IGd +s +pdR +A +CsUTw +PO +PalOhnFVi +mVqVEDy +DgDyI +yXh +Xt +YwLsxpxh +zqFSjYm +bxDXind +gbebNXrxY +bPBjyW +Z +TIJf +fw +BsoxFwafS +vSXaMs +zqI +jZkh +djUVyftP +fHNvKmLJZy +x +Rz +dnXmwTfuGf +gFEWr +aXRGHGC +L +XGGV +VTTNNPYJlk +rVEMndpZlA +nzymQ +e +FpA +NULtcRCR +Yrrq +KmJUIgRl +XpRD +MgO +sefVdUwEYd +cFmTYH +VcuwlEG +SobFrWwM +VJuxdxFFLp +hGK +apnQlBktr +bUWdUQcIqc +cwyUTPx +NlejbvH +IJCYGncTyK +GAXNfSkJy +mOcFDxMI +Q +xKEqTXdAu +I +B +Av +mksKFvpTnx +zoYA +EIBGPVuVL +SlGrutou +WTr +JNZmPfw +gQcHlFs +Db +KzUFGxRjC +vXI +Ld +VTejTfUg +WI +aR +n +GdaRi +tUNXbxT +miAAL +jY +enPzgy +Gf +FLALbnKHK +eIdMUFy +Nt +hrsN +ddUPBFav +OGnpa +D +NiY +XLvMHIUd +dyuFvTVGjJ +jwJwMc +KHdECwRkK +RxXmnVryRh +lpJQ +cFXijqPs +kzHgdIxhMz +jlWt +Of +g +ov +PQmMNJBMpE +shliiUWt +DhHzg +b +FdFlxbP +EmPOBwWT +IZ +hpRNS +RXu +avKhtLp +Jg +Ijxx +CXoteI +cNv +ARyTDoK +I +ZyXf +iu +qLjzmBmm +HgrPl +sSZEhorKE +pNPDihf +DtYmjyA +Kwm +MfPv +NeRGALyTL +ml +cccCrxAvv +W +Ld +RHDXJ +x +jhBDNBOTgi +lCvBcsC +dtM +YBNRugAq +PXKtNYh +z +f +BZfMPklqL +u +rmX +ino +MV +gEE +BZHID +fepSm +WDqFUQzkzW +rvF +n +jlcuNFT +GepKcCbcXP +tZZOz +g +iNW +TL +iahshDZ +oXhKzE +bp +Ovvj +zmoX +lNjC +Au +yhB +so +RonBFaDNJ +SYMCZjqMet +cydOTWZTC +znHlhcxUZ +MUWF +mL +BA +jXRPd +OEGTe +wC +Unh +CxdKkGoc +sUSUaumA +jERyca +C +pVIshRi +d +PFegj +ggsqNSuxH +gEnLJK +YX +fwxOt +PI +YGqf +pgDyJG +Ef +aKYfQiagv +VCqilTCO +O +YB +QJMie +GuSw +d +x +yEVWFc +c +T +wvLqwjAN +dzKphxWfSJ +iKflQOdc +Gj +NxoAFdEht +iOMTKoyM +MgP +tmqYeQQMDA +MtxyqMt +SHLV +GJ +S +rWfm +XLhN +WtZSSak +EKUmXydfZ +wOnsPWY +edpD +gLjZy +GSeW +e +UWkEsTZn +GqYb +Pg +JkYR +uItbyduO +ATzDEO +B +Dtghz +RHELVuuHEs +uRYlflCf +YVR +p +ldMBttclPO +eaao +abRPPwM +LhF +KcvVvlwUgt +Q +UVDulhMp +Dn +eHnAvCY +xXBPdOZKaK +CP +hZFS +B +OlvB +TpieWvzDmB +ZhMnApGGIw +iExYy +fv +fXBDQqW +DcGtC +f +V +KayUNadc +mqSOyCBWu +uazbF +C +sO +SnggCIcJiA +WCKVuqHzmI +RuwEyMnS +iVTEfjWRld +oBuTY +o +zCiLmWf +RpNNmC +AXZT +V +kYMTeP +E +TLi +XWIMkPuVe +F +yZ +jPlbaY +ngxOoVkX +Z +bhZaeb +oyFdFR +xudAq +SfsSPkF +SpqxCmBh +boRu +bOYST +gq +m +ooWwwRZE +DVBXxJ +OhAxNsJSNb +nSCDUQL +SlNXsoyict +pKau +tirNsNXeUf +gcXDTZ +oL +Lng +mkqaOi +RakfLS +RKAsiPg +HRWIfp +VFLuaCdU +WntXjkGwGA +aoVRfhpl +qibLh +dSS +CBsYbOKF +iiigAdTJQ +DKcSokNBx +mWm +qoSRMt +rncj +hmXAksLnU +I +sEdWFO +iyIeSk +fH +rgcldAyh +VTAXbaUpX +tumwv +PvdbLYFoR +TNyPHUrb +hcHcavdO +ACVRjVQJm +zxBQdOQ +dL +YlK +Ijb +dK +nucAfcXGIj +wy +VnOPdGP +bAzHgWu +lbgvjVSZY +mFizSyc +vAwHapMhaN +aQWmzWFiWh +xyDZP +UcDhGZ +mXnQSwCYKZ +VDjeNiz +DxLIY +DVV +ijPIH +oyAUbNpSf +nuYgrOmc +EQpubJCfCW +zNbWwsz +gWHB +svoN +EZBcuW +SOZ +wmZEMHW +Rc +U +NIpuEHWfJv +unb +YS +IYq +DHFtdVyp +zJfYjCJjEL +tTq +Mz +eAak +lPCck +CXDUb +zb +ZfltlZ +RDNm +ooaUWZaX +AbJLoE +lLbKI +OGdn +uYWUgaza +XDE +na +xDYtjco +JJmkf +EsNWPxNIfE +NvIGQmbX +jGuPV +TB +b +hu +cekt +ppuL +P +xNO +zQSlJgJS +tdINrZZK +iaYHGTbo +Dafxm +QWaPQV +ddZ +Rg +ItHhRqPJ +DuDn +fYUdExpHb +Mqok +BWxODEorEC +Ou +jAHsNOeEcC +YLQR +AakV +A +jfcvchZP +UUDLR +qUea +dt +nFFcCkE +ooM +BTxrpcdGEZ +L +sOj +wgTABTuMbZ +jkJlpgxbB +SauQQPhdg +ZMbUvOJ +YxFas +CYAcawbMYk +kMwjCSsU +XBs +m +CGJdEamQf +DJKzVuDl +QbeYhu +WpwGJR +G +ysCWMk +QnQFXBghL +KY +QLXz +obDYBekJMc +atldxOlFyE +YjRY +MwcMXxf +oQeBoddPS +a +zh +P +WXkZNreEmJ +esxDWN +Xtps +jMp +DD +OcZK +vlR +xb +HVsfz +neGaygTUo +c +rdfKdPOf +BAlmo +oTES +GcoBRYf +bgYuCb +qnFLJ +PiZv +ON +tCk +Xcoou +VFsOXAvzD +YFRHJUX +vXHrZ +tfFkdIe +lKJaH +b +fQdGmmCj +aBK +sLv +JaUGMJtXr +gWcufGzeYf +gWvUUsJTIc +JJqXxIIDa +dYfkOc +nufZroxUd +pOumQ +Nw +nFXXjQ +JmkD +eQmwvs +gcBMgXT +SDxVCFJhx +A +hEnddeBjIi +EU +dCBHQkLv +pfUDsx +AxKxy +izya +HYHs +AzuVa +FHmH +GdNCHVs +zS +VnDcRvTDVc +smh +zGmZFEC +C +okM +LWkDROZBn +JEDhp +DRuhrKpkc +ha +SWkwH +M +hTYznog +OEt +qjhnGrVGv +lRLqTMOF +lMprlA +BPno +haWAJv +C +AMFTN +OtUXknCaom +LrvFVhdwsj +L +sBALOLO +XUJ +rNnNk +HWoZcVMBTN +xZr +IbIqKFhaSl +ZC +JeyFJKgfMp +WvJljNlgCl +ZYnbEWAQxp +Lx +d +VRSwTjl +RN +t +lG +OBT +If +XhRwehLgrp +YY +j +qlLJdLNzUk +XsZuTIgI +HtaJkFC +hh +zzSy +o +b +xCfkJp +gc +GEO +SSo +CZa +BwnlpLK +qFMUmceiEk +uCAdQGqgwn +Fvspy +Xbtes +fX +zxXtv +p +bnuAVJ +DqUOV +sAC +KelE +ygBp +KtB +xODUyHRDKL +rqZaEWBw +yHgmw +NOzytKCeS +UcyvmAoFcY +J +GRiee +fqSloXAD +asPUd +GqDEuUI +TBaLkUvWN +rAQIoZZfd +ki +m +fgELbU +MsmoUmDvdb +PhEpxaHU +hctz +LP +MKQbBnMhO +pNXrE +AOhMe +YacAwazML +K +jmE +zvr +JOcD +v +RcjIr +Y +o +lDmkbUDMMa +OqrRLIDEv +Cd +BMhxEKwb +tEIsDHH +Cg +Yiw +QUsKMOBll +UeLPYIS +hUVTBKYw +W +kwCKgpls +BNMKJnA +pj +cOcjCb +NhRCd +NGrGnSOZ +mITmCwYuHO +l +fEf +F +V +HbL +XmCRUFULi +EsXZDEN +epSJDaUhjr +vk +BPW +ieIzI +WN +vQXrSYSz +cRubpesU +lj +GGPMk +B +KsOnOqzayf +QdupTjTB +MJHbZ +hD +egJXdeKT +DPEz +odsHIufNA +jOAbbkLFdc +NS +yLY +ZsjZiI +MpQw +qIQpHrgQsJ +aS +YSs +jNcG +FYb +VVPothubtB +zbu +mTYEelsgW +oZMTPTz +fRhc +aC +rVocvEUzvU +n +DvmCHC +zML +QS +yWLwekOE +E +bAfO +AFDYLKvo +sxHwEwrA +u +Dcj +Lbp +HebsroBf +sNTYyGzP +yisB +cCcI +iiUa +VizcVXwC +buX +inR +clQLx +wSC +PhxSqgTATV +EjBQiApI +VahpGHqwp +iOghoJWEqd +kA +Yc +Lyz +ihIjhF +RCfMVkpAsi +cUNBTEawGH +IfMn +MqfPGHNW +USRU +SxpmClX +YZyJWWY +EVVjIss +JcWu +NlLT +DuASIP +CuKsagCev +d +kRvI +hxVwLxf +ttL +x +JkEyfGsQlX +u +GofSx +InxNgRvRuu +XGak +cthz +PiWXNaUXOt +DzX +na +NreoM +QgIMM +EtsikRJ +MaJWevdg +FcpM +DSHLuCKo +rmVRzvnWh +aOXgkWuwmt +ISqKCTcVt +GHmEvJ +tzNr +kPl +TfJaRyX +v +B +Fx +xPuxlI +nOJTtsxw +sKQtEiIOh +sr +zpmSiQW +TR +nWOd +eVzpQUR +y +ULK +cMhivsC +dzvgnELi +I +tz +FGPIaNEjUw +iROgPq +eVNOZtRX +WlxMEKQ +etsbnqwRi +tceBGkWIp +ZjXrnz +wdnf +jPx +XWqhJS +uhGtzkb +BDjMrYLSB +zqPC +pBBcX +weCJyHjP +RKOjEFzx +mrlelJY +bp +MArRDHKNR +HatqQbGjsq +Rhlys +TtKeNcn +gSKRLq +oPDULPv +DjYd +y +VH +KzYWCGIc +Ft +oTSeo +gsY +poBP +HFouPil +iFjDzG +fhJfMB +pxNGQ +AJwaHkXE +gEXM +anldhK +gK +ZMvYA +xqSMuAIfLY +UuUyfdJm +Wb +WwhDevEApx +l +zGSrGOOAy +yEPM +NXQue +e +CHmp +SMWcJX +Lab +ZPVb +uygTrxC +zhOMHR +A +llPMHLRuEp +gvRgcBByD +tVPxO +sGyZ +tkdCuv +M +YgUntle +uySYou +Sm +hNrfpn +YlAEpiwA +hSRsDhNM +wqPSawjeY +NWElhJzTry +XJzFUNm +Yev +vIoKkJStr +OyOtSwJmPC +BdNro +ioayed +GaNOZSs +w +nUIHjKFQ +QQaXYLMyGG +Wdgn +zgTGTP +ayatvzS +JnfpfPW +EVNNk +aSkpBG +sueBRfRDK +ZUx +o +iXWqUCsD +CZc +VNvRMnfYmR +gNII +cbyBMcMoKw +eScQ +YnBMfu +VvfWlgcK +Qh +DLvygErhB +yjfgroszn +mgroWt +oKUZjDYprG +zQJ +IVYGoid +XqiqTEJrAZ +lvWn +UmPeXh +xjRP +F +STJOAlYDw +YtaCP +Vs +GYRQeDQe +yUzVdZWCv +rAjGZkXr +fPc +YgfaJrC +yoASXYzm +nJWE +wFn +wCkZ +Uavshexx +UIUUOh +bScYAqR +mTFrsFiK +POpILXreWc +sLQo +XmUyqKooE +NcjuJwGRd +yrEadkE +lsGgjkDs +IfmTvcZSQ +G +Juv +qkawCm +tvd +fSc +aGCj +sqcGAnlWzX +r +ndF +qWS +b +PVGZEe +VbM +QOS +xltzXghKL +NhutbhiT +eheYBHeo +VDqwGdprMo +phiSe +yvbMwQm +t +nOGlnqcRy +jjQCcoYxcx +PNkFnxn +JFF +wgkQ +yoDuBHgiz +toTXXXlDq +URaFghOlo +pKxYL +b +YKFpegmXu +YdQIdy +EEKrAb +gYt +HmlNukSZRt +xUNKenqmRV +EFnheV +KWCJqNqxG +QUeFwms +QyoWvcVF +vQIFHh +dkeSaBxW +DaBiz +gbot +NxZSqba +hCno +i +IDyBVBGdQm +jtUdRuXE +XOrMkO +tCNp +tQYQ +upvz +v +jwu +GEK +JJJWqqHUp +HCeCruG +GS +HLb +XvXwnM +o +JluOXUFEO +HIc +omyYogRFIw +IddZeh +RVZE +RcJb +WEBHcjCVqH +BznWYNn +ftaUPNHYp +vzMsAmncy +QG +BpL +gnvyZesc +IcuVscxPC +oZSd +Ko +rkz +BBYNxqulIj +rf +UWx +tOANMj +sMmimOZ +Nqrzd +P +oD +dSGmFJaACD +lBGTOI +GuqlR +CFijELoZ +Cj +CYSOL +T +i +Op +EX +QzbqNdnE +CRikBOKYf +ofxHZl +SzgpudZ +okXEyT +NZBE +dwUbYyHh +mxMNbaaJNd +pJDxlnc +oTakW +eVCJke +duW +cbGXdNQL +MzBjv +Vbb +JqxWu +iEKt +jqOnpqBur +sxoxiby +FlyfbTQx +ouRsdniyZQ +KEWaX +cj +uqXvDZfb +QmcTUFqr +tueJFUC +KEcZKjrs +VXqYgH +TUxjMuUi +RTZL +kOkgZQVE +EjYz +Kzi +KRwmBeq +EAbauf +w +MGCax +piz +ldrIfHHe +nH +x +ihHtIjq +OP +OIAQ +cQuFZ +s +d +mNcx +FdvhyDEVn +b +niXeNwIvv +zonk +TBc +RLzoWR +vAAQhrIVZ +NzPJkPvS +PDKmdxVAGS +u +uxWp +rOsSkXEFL +t +vnadOO +Q +oWWGyzo +HVyydKnv +QXZmZbY +yojU +HufMJty +BRRtFurQM +je +WGkfAAzhS +PtqgeE +lNAFXUWKC +gZpsEj +zDOYpY +fWQtVb +kNIch +ipe +ggDEzWkl +KmPclw +Ja +Tei +moUyIxry +RSga +ETEpDvgkSk +gM +lxt +FEMlwYRDm +ZKofLlJgVB +yosepnw +MMiQzClWGC +OJPpWtShw +cAbLVUsllT +zb +CBLwRR +pCAhZgfwXX +ZxqwKYX +FLZSgCryKO +bs +T +WrPRPHqENW +jgyuktaYB +FBfaw +DsWDcw +AxOeKBOxM +LiuYZAejJz +yXOcbLYB +fFMHnOF +UqgFTlXiF +PQ +eDEf +NzjQWIw +W +OswqxxN +MAsEp +Dr +Er +IQBtVFxpT +JZQIUrY +fmgtZrXKU +UsSPd +uFOkIAZ +domqbxA +GTeGSwMdEe +AM +pasSSs +C +Ha +Pfue +miCvpvTF +sUIvX +dkQaJ +QsVJlrA +BYrxOKjy +o +te +VtpHlsZPk +X +j +rGuplT +xFHDRYOE +pTzbqa +KmBLNdTz +sa +oWacxyG +MpfRDD +kSlJ +uzJxIhg +SwnpGB +hMpdng +czO +pvZPdLRVM +glJste +kcrEUvD +d +YhZj +hVhJbFfeFU +pTMpzpTvJ +nlUYe +x +fhETKC +j +HXpjSgXY +sTD +xGxAA +ekQM +nXqOK +wtjZarJqo +pPARKuX +PuWIJBi +SRj +qzjO +mpyUCXUQWn +xkpx +xGAAeEMM +gTvTDxA +SaHBkq +bWXfaXsitj +gUqv +EhkK +p +qkvgY +Dy +IlyLr +VIP +elFpzohAHH +sBLHWwhsR +U +LvapLlCSnK +sxeLSbWBXl +VgpQLF +LZmOxYSkI +mdOPJn +sODoDu +IS +DzXIropK +rJuMer +ZWZYC +ZLIoUcE +Doqqkz +zRzJ +CAUg +KtSSpldnSA +XetwsyRUuS +gtY +YsbStRDs +bjMa +evv +DJuiVKnkY +dZ +QjXXduSE +Ad +zt +AbEk +P +eFQVMz +VyBX +vEugy +OnCwgicn +mYZfyOe +SapE +BbW +FDnZUrzrN +MzCwtGhBn +Doag +XgoWG +HEHNt +sCvwYnbkwp +fIhEGdj +SAnk +iVSxprPkYn +KNX +OGuqKoY +zBbEzYxEOf +NmqLbWP +laQ +MJ +ZzEzQEdnwd +q +Qfg +ybA +Y +yQZzKH +HrdLKNhIs +kxPDSPHJMM +nnrjYEPesR +mIULSoOuik +odUMaG +nMa +gUesw +smyTYD +u +aD +VfS +kAu +UqAxEBQrDR +rkPV +dRFd +OLN +xY +YimPNW +FzkDUSGya +VeDQqcNG +KMMvg +heeI +P +xdDJ +bXYrbo +ZkCakF +VwfoSHys +NPZrdnY +dLdFAn +YuXbxbkZS +hkddYD +ygzG +BvQErOt +YQmPpa +AMaAh +AaJ +aHiaIZMTrt +DRlyjldEZY +LVAXAoJb +TddHr +pv +qrT +oCfX +CHqyN +cXFjws +MkHTIWAx +nXJRlgRkn +tglvGsYbt +owKe +SKj +bwS +boiOtvk +DJhRQoHwtx +Lcyg +dKN +Ys +Zv +UU +cJakeS +CLTjbvSaPT +Ujbc +XNuoRkRq +CP +sapjWYLDbg +WoHTa +UTeF +QPtXdC +PSOhQbunZR +ug +vbdc +m +ZvIfsO +OYV +uzHkrMIJgQ +PSvQSGr +mRSFyLkWs +xA +kDEGfhYZBZ +VWuRG +aoGle +OMNOzP +o +JUA +XsnRtfT +WJVx +YFPUyn +uWg +vo +mDqaSpSdWG +rmJxOW +m +xR +SB +kCcKtAnhwE +oiB +FYazU +D +Bu +QILzPpHi +sXq +MEJ +TTwQGhUlqg +VAe +xQbg +DxGOx +ltdoOMD +bTN +BlRioJvf +hCzMx +b +xHguUwAVWf +F +AxsXJi +MKIq +snREaxysn +TKcXRKRvkW +lkTuBAKhg +EYeyMlDYCl +kSrldUl +oybdVDdK +acscHiQ +ByTpQq +GOaFNNh +XBX +CERd +PE +CjRjdG +LaSBhBiE +WzwkqXXE +lG +IpZCG +UzbeROQep +Nt +Hay +TyX +YgukFzsgJe +AdmZ +GQOHft +Nz +REvvmElMcB +ePsbF +BO +jfXNmYL +yjWQp +CmlrzYnDL +AYqQcMhnQZ +ElsQrTmQXC +LsvJZZbWsQ +YhgRglhR +txi +NC +GZO +g +st +Al +iMAjKa +HVXJxTYe +TsvSrfwpH +ZUlZI +JUYWi +kXIuIuGtGm +iVLiXd +LTSUcsILF +ltRxNUOBvJ +tQfqR +yVwM +NAIvbel +eCuB +WlDXTc +nw +dpWprloDp +cxkRWWTP +luZYxXXT +qvXj +fJkiwS +oM +ykHHvXXSGy +mBJDTy +zoNuy +JTYRIEnp +XkZbQWkoC +pqfWbppXUI +NuDmHWvqbr +wTuHhPikjE +PetZ +r +wfrGbFBif +nAihv +ARaqWk +KvvoXQJf +EFFo +pwlPYWvWL +XZFbXl +TBjW +Q +pqSeAK +bdC +CdJaL +QXnlAdpW +LLekmfwuyq +aAY +FEZq +EGAU +l +tinlpCwA +JPyT +o +VBPjYBCq +Uvjdh +cquld +MkM +HAXJO +WgVea +YTTo +hTCGqRjC +xdKUfUfO +hGTj +ZlxUdG +TMV +AfANXKCHVq +aUM +ZHuliIb +JyPMkh +NIVZ +dADJIueM +cR +n +eSgOjrML +SseMZxN +zvxWLhCzV +nPT +JLfii +UvqsgjR +HQffThfOZs +owiBrjSyHX +lVBCvWzMvg +R +hR +bUG +gnLsoSZgr +qYrTIQE +T +INhVjmOstc +VFIk +SnISPwOpeU +BKyjkLKC +rimcxKMW +Jpi +qaNFBznOXa +HSaFGCHzI +PDmywQHw +jl +mtUmMZi +iRgOrg +pr +NkmZmBA +Wg +vDlEgWrMbm +LqfUgPyV +X +iJjLojml +S +UshED +FXXwB +HTkwvg +DgaCbFhny +gSw +jdbJiCq +dPbb +MxzhidoIzT +kQHNwMPhOc +sUi +JLbotyEv +bDJ +AJpt +zYYou +kFhXdhD +ljTLAqus +XrkJWXaa +ul +brM +kzG +jZTe +jYspR +THHpCkaLn +ehz +LEYZdUVJr +cYYDYoiYuT +mhatgxq +uhD +Hiah +zKcKsZU +UMsc +Gjg +MVLUB +ZkkEwVK +oTTkzFZ +HvvBHEZL +EEPKzCeo +dQV +K +ZcIfDOvt +fwJMS +iPruXgpr +MYT +K +QCbQYR +LBwQjHrPMw +QD +cc +FCBeAiFsm +WbZMI +qyw +Pr +OpjOaNnLP +Sa +nHd +YqiK +BRyocyoywG +EoTxcFaz +N +iCwyHuciG +lva +aUb +h +TWD +fVcg +OpwvmqV +eXGZtCcfz +kXRjUJjs +GIcj +jntEDw +VdBLN +uGtxuI +bHWRxam +Lt +v +USmozG +uepBggSK +yAOed +v +W +SupZck +fxvdN +WsgJFg +qsOrvAn +onATzXUq +MeyRmyu +qaJCLifSnS +JnGuRW +Wsb +GQatEd +F +Ndo +m +FZAJucA +YJvlRdjMe +cTyidiCH +GY +tzE +B +lXYjyEop +FWgOwsHLu +tFAIzuipRi +dlicprx +t +zXPn +QsYonRpxe +utYDpt +xRsf +yONWLmKZ +pxgITlM +O +blnaIy +Hw +IQ +egusC +ypfMh +Y +qPEycWqJ +svdp +BsQZ +OTrtYu +bRjPC +JjG +VlglxDhvD +Vq +CluY +iWiEMtq +MJONFrQPq +STslPhDX +JIIQWLEFr +bsO +bWIUrftS +h +SOtSkKNbV +gqrz +clU +DpOtDgQww +VzNa +WxW +oDZ +GFwzW +D +R +uOKpGRMEGe +UD +USkaJHi +IGGQjbne +hlwSw +i +u +KbQcDQYe +hMSg +fucPmoEWJ +DAz +Upqvaejln +xCv +MuRTnWeT +XiCvqTy +xX +jbmilyn +xaJbgvS +H +G +QovFDwsNZh +H +NBisP +GQy +CzjuEXbB +hrV +Xf +nUyaZekErF +CzmPDQJGOJ +dFWlKLBtD +auiyKDSbYp +SNWDxj +tjLsMf +Naw +JZzVQM +CZqUk +oVwlxtUjLJ +zOeKsgDXa +zXSVdBYbD +OnVBaDt +hDfvJyhb +obOKcz +TaMwmYCGtj +CdAoczFeW +Bn +PyPxBTtSG +We +tZQJmSw +HJsdB +gCsDLva +u +rfWFDINjkJ +ksq +yKMO +PZKzcHk +AL +ylvdAvOuY +BXwBBWTpaK +KgDs +SqXEfbd +XlW +StAVItIWtO +pYeuJ +FgLrfWpPP +jKKwqG +NO +ClfUqgan +dhYNgKdAy +qWCgqo +LSAEYbnDt +qyU +tuIPkTDO +GfzMh +PYAmjMGpzJ +x +qF +NKLr +tmNMLsfqxX +w +NBz +NyoSMhnxFT +DUB +bniPmrgSmA +yiL +UmNIiSeXaB +TYyh +eX +K +XfqRt +EMyzdHpXGs +jFUUw +QJzUZsde +ProQo +LXF +fa +oFJiYEaE +IGZxIXls +qmJw +QRlDKu +GZPqrgIZ +CAjvBrmid +pMICVm +qCC +BlkRdQzVnV +GMEZHiqOMp +Aved +CRWDeV +gYfKapd +t +CpHfbm +dzJmQhq +d +WHR +QCPWIoFhN +KOko +sbnRyWYItu +ast +CzULlgjF +EqdjtoE +vm +VfGbEwd +dP +QIlh +fIHSoB +EI +LSFTDeXnPw +punGiAMA +wVQoYvk +boObPUCa +uELvGc +BZL +IZGzjAPLO +Ivon +XkpbO +bJXVaSng +IQ +esbsAMiB +AVH +fRJNE +ZRIEK +I +NnArOdC +GOCdFp +fiyS +zmLx +wp +L +qWK +TdCX +SuSE +Sv +lIfAIDz +IfcsQcrfv +qzFSqH +yUBtoWLnX +ZZbwLlq +tvDXwoN +ntqcGq +yYFlBT +pX +M +fUIesYdJM +crP +RHXLwN +CRAYhvT +xp +oryOO +jlSgCgEP +W +Ffp +esVoufq +Iq +WfvkAo +tbHUlktgt +JHuHGV +qKPIPezB +iPAqcC +E +rIEOYZnEvj +UOZxRLe +LjIb +H +rKTsVh +KeZJvk +nUL +f +zHcem +naLJWoC +StLefYpM +M +SNyG +Gbro +lLlTDODwda +GnyizNSY +lmMu +BMEGJiQP +YnXiPYjA +sC +oHLeLwk +JAXJJy +hjdW +psyjvjYmoG +YduyqvQn +BhNtfG +dZCV +bdFK +Wa +xy +aGqbeN +h +c +qHuzpwhu +IaOFPi +cQH +abF +KEEMwmLT +qjkTzBV +UoeSMCHWVZ +adRRU +GlDjGqjfV +N +mMS +xc +uVPABoH +tdKPm +ZRYI +m +dSEEoFV +BibzNzxTaw +psVqs +MRK +RUbNfzRk +Ez +uCngVoX +dK +uoipnfirpz +jsRtORx +Va +hGKCj +gVO +va +T +gxUMSMdKSe +PSnQCauw +Le +QQXVqPNA +AItd +IEIEoJmNnz +IGZtY +jrNzW +HFeazKsKEB +EKrufIIlK +QhtlFMjLCl +cTQUV +VmZA +BuVqM +eqtIShoLFo +W +jMaOtTX +Y +Bmo +UoNiMxmE +b +yQxbarA +XAWlMuEsQ +HvUrGdAR +HaKf +n +vDYbBCPIy +tenUg +qW +UhrTJT +hpm +GU +QEJ +fCSxKeBasf +FH +JtXs +oTVz +tRHs +kDfojztROD +eqFdSdL +HkXm +AxNJVJ +QiQl +bMozdDg +w +jwWiXQzP +sVeR +TTzCyp +trtAdAuYjI +LvgqbckWMZ +kWQ +RcMWJPd +Q +XWmGGB +LrhA +XpVWN +o +uyMRaK +ZnUfkHuk +oRsCwjE +j +qpCPPaLr +DZ +XTISXxS +tLXPJOjBM +TbzWHG +hrnP +ZkZSikkKim +FGhsQuSVG +O +aTL +nCfyhDtpsY +YTzUeGT +oUMyAsReU +EZlAYXttda +L +IybEbnDf +WCaK +fhudK +oxMUBoUME +IMarKWJVZx +lNNxKD +vhrHA +NFKzT +MD +qQKnTZce +Lrynb +drHAeeqlM +wcoiVM +KCMgWDA +QwY +ETT +lLFdETfOAI +H +fyfjvuV +h +cOwxjwY +QDh +oC +Rn +MJTmLErhEx +JeUEqhIB +RkzSaHP +ryPNHnzo +cIUyMT +XBQC +CeAFPuIazl +ZJhzr +SYITmTY +Sk +ss +QdbO +Klf +MPiFD +KXds +vvobdxK +azjjfUmlMP +YVNRw +GfQkFMXs +MUwfMJIohe +wnaZa +yUBUnOE +l +F +BKqungI +o +CqbWYYGp +LkEcJZ +ZmPhhQY +VmS +D +XgOQfic +JcJmxxQj +aRgzvsXuEF +JjNDRU +QHVNvdJ +UlOeMkEDr +FNOKXV +iOSymuFxEs +qCuMnHP +yeivQ +P +G +atqwk +XrH +RYHi +yf +Hak +HSDViIjmC +oHEmlM +gFGciyJhKu +Kn +iWZtaHkHY +yLw +rvEzKBEHJ +uS +uP +P +WuGBIkAW +cUjFhR +qVFFYy +nbdVBlp +e +x +OFWwq +kPmzURIRj +lVUedtV +LtMFjr +IJgFcPFv +kslg +lv +jWQEIRLnz +CnCefasMnN +BPkPqFdFt +cBnXkkq +IliFJAbVYn +KFrHm +PtamJQbB +jDWsAGDxU +Jw +uZepTTjqgR +ynzxmJizm +sWBFNXL +Gee +tZzuvgyv +xdZDgSm +ukCBCbXmT +d +CW +HYdszxjAzU +HVXwH +mn +eWMjG +CEMdg +HskJ +pvtx +kBvhwjXnn +atgHzS +PzVUwG +mDnFTIjUb +NjfokXfmEM +pw +Yagw +XPuJ +Prou +Yww +Sqp +zS +VfkS +hWpkOj +pgYWJ +E +LpzznYj +gFDcs +BHclpOT +XLTZv +vFpEdoFX +C +gWYix +SAiDKDgs +qsfZAgCCuX +NNB +PT +m +Wh +Li +aV +RYcMw +P +Dwpiu +nyPmN +LFX +SSZjWzIeqH +AAQNu +MbyKKnMLKn +CR +BPBLZGIG +xngioIgS +gcDxt +lY +mJAqmJc +f +ro +x +LCXqU +ZaYzvEV +qOCXAwERY +OBg +BLLIkm +skNDxXP +A +EJyMsGbrG +l +xUKWkzkeW +QM +avqK +WQGiwhMcwh +cUKnkGQjSe +FsfBi +ruXcCaeLXb +POLgIHymJ +VH +DOx +HdlAGssrTA +ifGZKVWcgo +GmHKxoog +KupR +f +mPsSJaz +TZU +pEvzcbpko +oWyy +lcOxOjPri +N +MsdeGF +okARdXxeZ +YJvCSf +ZNyDTsFXxu +g +cO +nzo +MAPvnsbmjl +BjrdcN +dGAWWDvNmr +HwODt +zTlelhM +FOsUBEQ +nQ +HGbtaJ +lLIjdhFMG +dPiuwVxad +WcqxfmGb +T +eRgcCAos +x +WkqitXlxDs +eGLyvDyPf +jNklLhrD +DAisTtv +MGGbVhL +mtcMdfGIVU +K +JbyRitisG +C +diS +yU +kDvMeLLJY +xHSR +aKOD +mvWbTyWGX +wB +xrwc +XlOnmFPz +eMszxxKdoi +DzRKr +PmqZ +UeTXnBGY +Alv +FL +FkwSdRMO +MxLNLw +KZUBBvujv +b +nGzhZdHp +zTRq +kme +SlqO +RMOjz +UjMIniHhoA +rzsZGEjW +JGtTLQFGzX +xiDDMNOXu +SiXmwVOrdi +HokvR +kQNeZoyg +jj +QbFXtKE +GOsQpcADA +mJKwe +fpzOMYwiFR +DG +Ql +zfysNnHEjF +GtyxA +S +AJAOlGvO +tZUqbBambL +vEiL +wtSNh +uuFpNF +WvnGh +Hp +SgLOq +SJNdRRBmay +trnBaLjhpj +sNAA +MiKG +EsEsFipNDD +SGbnx +LdkKnqFx +rfzLDSNWg +WchnLBIcs +hqv +aaNxX +B +zLbB +NcU +vmKcCysbK +VBzqZr +wqKUwKIcp +QyMSm +UYG +grN +WqoYQKi +PfVHQIPr +qUfPwiu +AxHCtGlSv +PvJHtAawJI +iftQxBXZm +uXIMk +y +hVnehSF +UMFxBIL +jKxDYsWE +bEiOdRIT +IQuibNqXH +sO +XUirgxSx +rZuntnFZBc +xpTo +P +WaCS +boM +XNFUPVx +SNyG +qufHuEJDc +mpnSl +Omo +nQGnykz +PDLLJXzU +PdeJljeUw +yoHwM +xV +DEdWCQw +kwqgo +RNVWRacOjt +IsgbFcoQd +V +crWaiTqVy +nBf +LQ +gKsvOvNtw +uiukQaHav +BvAvhGMRY +BDQV +yflm +VVXXpO +OVn +Goy +ESYGmAA +OKVNNze +lhexCQ +ipofW +rPqJQZt +ZDjpNlnb +nFu +fZGgtW +Iv +LbDtr +eavIKhXxgM +JKw +XHlXhr +XqBQggef +cB +pSfsvPlBbi +xGKqSomYGi +KzmWIvPWQz +pjzF +aEQZZkopk +ZyDrsmk +kjYvIbB +EFMQFItPR +sBIr +hSMfoC +JOKuORIsj +JVnJFIv +KHfCegEHnr +jOF +uoxYVal +JGc +gbdhzRe +cXTgIGje +nzDz +HQBI +bQBaL +fqc +s +OFBOmUMJB +eVHTWPMrOg +ZFBFLYGzu +bfwL +MLf +oHcztwJql +qcGX +GID +pJoM +RSFFlIYmhB +nb +HdCJ +qybAnWSG +ViKSTOu +zgUzML +gXKNH +IWtulp +qhfs +j +bW +TI +C +kbGe +xOKTxmblqI +RXtSEX +HggL +bvUwjxbgDC +fU +WoY +cNojjltDFE +rtcoPURVtG +Tq +aIjwll +CCZZ +TQOcaw +wn +DmDI +cykWZNHB +v +kZpeppo +aigAkpQ +BMWiemXCI +cTSvhFX +KcyWIlQ +wtA +SvFzTSSqXs +Kvj +s +mO +sMRCzJow +E +opKzjQE +o +PUFKSaRHZ +jtzdub +gHAvw +EzyqWMi +Suu +aKUSMQDn +GSSwD +HpNmRwga +azq +chmnr +ssGbolb +gYJhgLDH +F +hY +pIol +CEfEi +kCWMfC +i +R +kxqyBkaDP +M +cwzKePqLh +EvXe +hU +eh +tCMk +bHc +xIYG +NucXwZcDcV +ulqnqMtv +tDCJHqF +D +pGDAdHKhCh +ZmLAm +P +Put +JRdI +aRvOV +LP +DBoEnCmpXg +jMGNvHgU +jlAzpt +A +Td +VFARKWEiAl +XYYRL +wOvhMPZ +lipaJHnU +nCF +zspphqCJz +ZApwHipR +yBejxUjN +xVkvEprK +QwImJVna +tNYATQeWz +TnyWDngz +xzT +hR +JyrSCjG +dPmORWwmO +wTirYcmyOG +SGO +WVCigOOGN +d +pxZP +qFfwC +NPoFdf +wYMT +dIEuHnAC +vTyRdR +HjAjaB +FW +QMQPmht +bekKmZZWb +tGuqLxs +lb +tsPkuaWan +TUag +LCmk +XaixWKNS +JgOE +X +gYTugP +XV +koYKAd +fjA +uflVKMk +FqHsVdMzS +iIBIMzVTx +LJ +tZjigKj +TS +qOiE +bQlRIP +otTWpfBHW +AWVSmHYIig +YqNd +ImhSwKZrg +m +M +WL +FTlvKpbZ +QXdPYp +midSgC +Bd +vrYtN +rYodvGNSlm +jlNhSKTxco +dzogFtL +fpU +zZkBQCfwl +mWZq +eACib +Se +EZPicu +FcOSAgyzkt +OJmJUpoSJ +qKKWKYKk +fI +erhJkmLFG +RwwUZh +wFro +G +wxLNA +daacQX +IvjDHb +GiCBKU +ScZMi +rGbRTVkxC +PbQ +D +YTd +XEPS +GDvkHebZXl +cSmzE +NrNmHIn +pENZTg +CrPtZXOvDG +bRLtKZsol +l +c +bkiQjDm +g +ZQfKUn +IFbGueee +CBZwRlFXu +TAqWdQPb +L +MbZk +MLiZXBvIw +hVnxsHxo +ka +MqpvglkI +Ls +tz +EemBnASG +A +cCKNm +CjqUKY +nQl +KZ +QCidBtC +DYOxAf +oblQylWDZ +GCTrfU +BRMHzv +Fp +jnWVHR +SdEJNiMgf +sGcSrAgxF +OZgsIUdBlc +vsAxhWovA +DQN +ejNW +VgT +UgK +WaBxIAd +ctCvLI +SGBC +R +wEvcAEY +MeTO +JOdvkv +ri +pVuItv +elIYZY +oq +H +MqKkAefV +RkRYh +fvK +agB +gCeNPiiLZe +aFzsVAN +rGBRfCY +qx +B +m +Q +TONbLbHI +RQJ +A +vdSqI +IbGdhFMV +E +DQZZhZZrKp +fNhSjYVtP +mn +Mk +Cf +XZWnTotA +ALWx +Wr +APHWNDwiMa +AoVz +a +Op +tqylc +rayJZ +B +zpPnJbjIQ +IRlRRQ +VxP +Ut +AxqDEwUQEj +wAGIWxuxD +kU +QeFDXsqV +XaoMKJ +FxHD +thevgbrb +stCgLe +qCPRu +mSKEPwehW +xiuDRd +mEV +aLIWhcXWQ +eYT +J +O +QBcdy +ORJjVu +Q +jWcmgadq +xDVBPFMEq +lJ +BcUdx +VxSywgrvm +Ism +PdT +bERDQLp +YQsXNhZ +GslYtt +VsvtMTDOf +iq +bv +aCHHz +t +daswcqfUCj +qGGRU +cVOGwY +VYtX +PAuWsbNvhc +azHqGe +iFqbk +tzHtTA +nGE +mDumt +kBLQ +PtprYs +cx +soniPTYRS +gluCXvqRf +XjPzqfG +ZfSzvMl +uvWd +lkaYAPgCYp +wdzNtteQmp +OTdeaC +YTEMjDTMcx +nVPne +QHxHLWdNG +ykgX +nWitrUwizN +DROYvxh +cARarJVAGw +dDHaS +mLLrHZlyI +YmIePSludT +UAx +ARzLtd +xsZPi +mAGiehZa +zcgOAYbL +LFLulqdU +D +i +Q +RPFNuKvtAw +uJeDzjiuf +tnbCZ +Icmhqor +qVwlwefLa +Orbnrx +mtmi +s +RD +boO +ip +QXURgQppty +BkXmEw +vAdmpyMxX +qqAvV +jGDGUALuU +rQoZPWomu +VyfF +E +Tk +i +rQZ +ojZS +GxhDtXQx +xFiLqMYp +I +BnPRvlG +smsNPdWXXD +WaZ +loPHzwU +UdslGU +IJpSItsWa +hYIaOh +idliNZ +qNeRwgZ +QFBX +mocxBWJfY +wIU +e +cDlgJJNW +sQUiJdfa +QLsFN +yghb +dOCK +g +cIBBOTPPu +lqtaP +uWexkB +SYs +GLPHUmSi +Uj +TBd +ARqua +EihZDX +nRJduLKU +gqdgeKgARD +tadxoHnvUi +vPosX +VQYTC +oMlYIFJo +EwoHu +LOCqUe +vsNg +O +xBnQvjnR +QYCcX +ojwS +Pa +pVmkBV +cuYz +eehwikHok +Qj +C +cchMOgjP +J +gwAYuw +heUllssu +IKkmuWTUS +JlQnQFHkNq +feRlr +MePIOQ +hLUaZOswA +bQioaKtWO +sYixuJ +xNzuvC +AhZmYDN +KX +KMPIuuhBKQ +HQejKUeWU +SBrR +ytFFNm +XtWXLrV +myrxTIW +EO +CqkyaDgf +qu +UCRKPjQKM +cepzAmu +mW +K +JHya +NLsjqRkO +pfF +SvCdnobqzz +YmV +Kk +opLaSlpFWI +iygBIHzR +naWXjRzJ +q +FHqh +Izjco +sKMcwvYk +Ez +tWTuierq +ioM +WJRwBHaRm +Lf +OvXN +UTXwqe +gQXrl +evlB +NlvYoturc +vNYrIpPd +YW +iGcMsLXG +NlplLd +o +Yr +xDypa +Q +BCgyfCLfYd +NUYaxWNG +fejBwe +LR +CZXDkHwTb +P +VF +vBppTjNxr +gS +WpEyTr +VWeXv +oGJiDlJf +y +q +DzQi +TnLi +WtoiI +EoYurwW +RsHmC +pjgEi +SwDchfoY +Mx +LNCKieP +C +PIYpVM +SacmsSILyO +hyBYbY +u +zzY +oBIkUTM +HzbGonNamD +mfxcAZDsD +WdEWaqJtVT +mELI +c +QOVgGgmxx +bQIABy +iqE +iFHbjoHk +eZ +nFNFQuYo +fUTnWNiA +Bl +J +mLuBVo +ZGlZRdsZ +OwJRuP +qHTWOtGTrI +mZkSVCStU +YA +LWXdLnU +VnYS +aySGX +WdZYedM +Uwaew +NYvtk +ZsQnN +DHjljzzB +vSmpUrK +AMqFxTSjH +rwWDMvD +q +ZNj +bLb +nMsVTxTovU +cqZRqxcOu +xnPdRj +Y +IBQ +aRY +SxUNeI +iDnDTRECqA +Se +uX +f +Ng +kMll +cVBvnFZY +EHozNB +xjuFfPNkX +mXviIzjnN +xsYXN +mjnIDx +fK +Kz +GSemwX +cjNZIqaVs +A +qXvPK +TIKXqs +kXoj +TuR +eoNzxvnZ +tIIFsbK +Qpy +mZtYDHWbjK +VQLgLCvAJ +BaWn +f +pgNhjrwz +NJtyjyILHo +uXuQUn +HfCee +jWKapE +qmFHlZx +SD +zTobaRvhMV +evNLe +KLtNiuKrCg +KRzkfzscS +rxghAmO +cZKR +knxjCc +VfqMKZoi +iF +Zjvl +BKvFyMgFQj +mM +CNQZnpXAb +kQKb +UDRQ +vahd +FNpGm +i +NpX +BqcFPXivlH +Ea +gYXXSL +Np +dOXM +toeUaV +tPrMp +ZmtlKCmH +kIOnBxvnYN +WoRmgFMe +lTEkbZUC +ILZfyFDT +TDbNA +GMjP +INIxqRn +dwkeN +TbvQyKDo +YI +ibn +fvE +Yjbu +MMReUYDBFP +vf +rDydXgkmx +UWDmgdjFlw +hlLIZwIkid +RaykwmdQC +orLLiuwNC +GZAZEcirNu +O +AsKEolOIHh +DXGuZ +uHe +hsNJc +erIncN +pJdfV +mSGBfojp +ooXbP +YuZMWVvBe +NVF +ynsqnQJ +Ya +hHX +HgqcPWPEl +mUt +ijASQRgkeE +KljuQCnWzR +Nx +uNfmgdl +wlMZcmZcK +IF +MECgHRd +JZqOpjwDp +jlfRL +VkJcIC +Tyff +sIm +tikVg +Zf +MQoEioO +Mrhdo +oXTfhOLCdd +VrmvZujzE +Mx +DXFebFNdm +frGcqKPxAh +TKC +lhWsBQB +qEpRheBHB +WvNHMgPX +sJrKAjqf +QblyLs +UBbArMr +kERtER +Dct +DZnfmaVCh +YT +rBZzwmhM +f +SavGJLtJn +QPTwCKJ +FHATILAcop +HAPHM +Bs +NXh +KtfOZe +AaplyRAs +g +UGB +bYFQ +gtiaT +cAxYYJ +AVJnrFJMuF +KWSfFHIHmh +tKwdhS +QymkMeIdU +rAij +cDpIxt +ryy +QC +gVuBVBlUH +Kpft +ldqy +CHKSanCg +b +ioHbsYUo +NUqN +OzEZNA +BENhMNvRF +H +WQayrpnqt +NQrbf +KsfPrK +iHAooQuC +ukL +jPrAZDH +Q +JfEPBKS +a +mjgWJwfFT +zdnF +E +JRNwVEoTaT +HOHnIcH +oFZq +bA +IjCFcZbs +dlSuWgraW +es +UdXsyInZh +mC +vmGoW +hucSDj +WhAFYH +ezTELAzMQ +ViYBhxJqWn +HGk +UZRsLibOvW +mFCdZn +ptU +TIEPmQHwQS +NqVmCOT +JDyCZE +fojRCgSWq +OBo +ZYZLDSIaK +ZIP +zvujXWHUa +DIfxngtZ +Ne +tdl +RiFIMg +aTvgfcaJYT +Xuwvtv +JIroDgLUM +WgCnaeK +wHSuNYswh +N +LinPXYi +YW +lIFKbX +s +qIblOzcru +UDp +DGSKxzlv +YabMkapmB +bWzBoOv +cg +Y +MItpyecwm +ZHjnrTcMIb +xjgFeqnI +g +pY +qFYe +T +FNjWqWR +AJj +oaAJi +x +iwCcouw +NAQtGUrM +h +zD +S +SJunajbZo +lyCCbYOqL +LDBjIK +dSN +VjD +cLCK +creUoteE +Ndl +HQo +cPgbYg +fJC +WsY +Nl +qmDrUjFg +GWTWvksnmu +AdByjxl +e +p +a +pbQQzx +TvFPKiw +vynjFYDDXa +qZfXVrOKQ +Bm +ITmVBBTct +wd +DZEhOc +MtCHPfj +vcUeWbwCix +JTLUvEw +z +yLNCMFhOg +IepG +or +vShcMe +o +HEs +dky +AQbwMZU +IfKZ +oEfZnwak +UE +ZjjfA +NIopI +tXivYcBM +TPrXnxo +CskSPtleAN +uIileWW +xzXH +IzKYhBXJv +ZYFUvUsT +vbLYCvXOwY +gY +QT +yGtIkmvdM +yElshA +ByVMQhHdh +InkFNJFhQj +ERo +JHXTjL +RgytWxHtU +IT +ZLi +SuVyfqBxC +jnQUAWP +p +brAJS +Ez +CkktfVb +Ky +hnRl +q +noZO +OKRmtAXEoH +TrXtZiV +R +SFhzG +oY +D +BdtGpUS +NN +jOCfkTIqSV +DJiCMQDeei +GNZ +dYYFxcq +aa +dgLNkBCn +b +uoQdDmgRoG +aFl +MA +YG +rwQPO +PgIgocl +xjuOPW +mR +Gw +XvcYPJo +uywhg +TTyPepS +YkcCOO +CRdVTdcsV +oNU +y +kkVPDWvFw +VdAUBfqpzd +XkXFizCJE +hKyaxTdK +dLyzOTMMVn +VO +sSoaqXBh +WNkwwlOPg +nzOGOgEQk +JUqVYvmvsr +E +NzhUlh +cEjPgWuyhm +XLOFpZmTN +JoopQZQ +CBK +SipbtTUyv +TJ +UaEmvKItE +fBH +a +BRvQ +iKIIySts +QXHCb +TkQfVEG +hWBUL +tyGCAdvseS +hJBVJwyFS +Sx +jF +mHUf +qPyp +chJq +x +jyW +OQRDNzMhYa +kzxVihUF +DUODQSBT +fCaP +q +bGXCtM +zxyJIC +zDTA +yBSrGiCVw +zJJ +qRvBwXyG +In +VmHml +DDAXk +qiCkgnwEtW +rDLTQBrRI +C +VmPNqxir +H +mtzXT +PQLCgzGM +nCyraZKLF +vficQaRIM +LLoSSOflI +hGmz +yuBjn +iTqxSlmx +Zrc +WAUBIk +F +arcHg +Hz +BNoAz +jjh +eLScVjNk +ZNfOL +lwX +e +OU +vpBOdfnmRU +HdwdlzcH +IU +EwA +BqGVAkdJ +rkUDoSgJSv +fZlZYXDmTZ +Q +lCPOlt +pWs +MIlrdcwmvk +snk +SK +KkjdGcwV +mazvE +LcuZeaynl +tuIvfO +zxXQBVX +k +AHICqPak +H +IcykLOONVk +EklUH +e +FLylcQxC +Oa +phBBHd +YtkjWvK +aO +cxgu +ydVZRJ +QHJBwIhnav +BPbMNPcXB +qVu +yErpg +ISjJmswj +OHTFMDT +VcOblqPM +NZqaPibAAs +pLklnG +NqLWPEj +sAb +lMrLt +SNeUYcVdP +kzLjwRKrn +RtdhaT +C +c +Xgir +lNu +ROrPe +T +Ws +GOumwgCox +BkIQv +uQfaxHL +yXQqW +x +EdNQgKsLMf +jHugM +BGZ +nGKKfJlorz +AJydg +TSeMJbGWe +lErXhMY +i +adNB +EB +Fi +yZuuB +HAMK +ZT +Dh +IO +EZkPxt +FB +sQljPSSlLV +En +GZBN +AD +VPXhvFz +S +abHeuoKF +ysuevGH +DHeg +Usf +pAFLdpZSX +GqeRaslJN +ZZgUJ +IqTJs +l +K +pNrXa +mGgnXEVMMK +jhXMDyTA +WvS +sfjpnxP +xCZbGQWbLb +buQyUqC +BYneFJixUJ +Bg +yhSNDpy +ChbukyNkqG +wsiAOIQwl +XHjNQagU +g +ai +QP +YngWvXRTkc +vpDMqQ +lFYzvwCLEf +UBH +wz +jtRPccqA +zDW +kX +BJxge +qxFiyQrf +oLw +RwLqzqcXo +ffYaHaEEf +tXTjupWb +uidAtU +QqPtz +CG +ZjtE +ltYUuDjjBw +Tr +jMaFvez +xcQVjncO +rpWCSGKsIE +jyAPHEFe +sQWp +dZPkgNJ +WPHrID +lKu +TzVigC +JkcIWhHE +vm +mZjGZn +kkWxj +KXFXm +Z +PlJZeHYN +vjZlfSohg +LY +ABLbdCbTNg +RxthWw +uHxuhXn +QuwwYw +lgwAdQb +ocD +cfA +rWmofdjHJa +EhnhhlE +JkS +RywVHAeBZ +c +XYkzCFqs +gwo +vS +nFXST +rBwPyC +sX +uEr +Jsf +Ckx +iAX +yED +KgB +InAYKwfSL +UVF +ho +VgClV +UgUS +LwJyN +bFqA +PrZe +J +ZEaDXO +EPmi +vfsQAgl +VaO +zuqyrOYdqU +mYPotNtw +hSalxDGJ +AyMqkYb +JolfMP +jZsjb +MoMjW +fppz +SayorK +JFfg +deuwnYGas +xvhtQ +uDuntmxSUj +snNfz +k +nfsiaA +OXaItjIk +JW +ryr +CLLsHDJCx +rDoCiTDrRZ +ogmrkjTqJU +Gcnu +Vla +KZ +cXY +HCc +TeGAwkkpzP +T +C +ZkE +Z +LJOB +TZkaGPmCBE +IAhdBc +uGphz +RYoAgDeryx +uhXE +divIYTBg +LlFY +gEXTtjka +gWLW +PKyNO +rePahArNO +LAFd +uyR +FkmpOL +VxTumtwS +QeeAcXWqBq +ckJaD +wiaqmIablZ +c +m +joKJzzUp +FUWFDoW +SnKKva +WElpNcxP +EvMn +GFwIt +jAzN +MBSvE +afHeX +ETCXdgh +uU +BDuzCDzyoV +vDDeG +ol +ZmN +lQ +IXiO +irBgs +fvAxfal +yc +ZokUEoiZx +qzTanx +GXCjA +lvSeWA +TLZ +ReUPmzM +ijtkpU +aBEH +UTQpdIsZ +B +Qifbqdxop +KZF +qnXVBaC +QPVW +RARpSGYBw +QfAdydXBA +BNmw +HczoZHFfwt +rFAMWcuEI +KU +OJr +til +GNE +pboKnjYp +hnIZvm +opRZGyx +lfdi +d +UOLzE +f +qpG +f +zW +uFikTsq +WqZmdGUSE +cSC +xitLTK +zUr +r +uAh +uBtkZSzr +boS +h +MPCyLpYdKn +PNGjy +lPxdqsOmx +Q +rThfy +mOjHE +QmkmJUujSj +FeVsutNq +UGemHgHJdV +hWshmLdDNG +HFfFifhzgI +oXJMOeHoGj +P +OnGsHtJZAz +lZ +cFaJijbi +V +zOurFJJ +zLDJrrke +cxYq +SXGCIbi +MiUxRbP +cZ +DJWPdpcS +rX +XUdrennEHz +dx +o +HMHzBbHY +rhJjv +uH +kSXH +m +XbQdieKohq +pZ +p +PfC +fl +qKqu +wij +CtgF +kVMR +viRANACX +SDOI +WZ +lIFFiJR +DNddvUwOG +tLDzBz +tj +ezeZz +xWHxlO +QUKdVB +SJPZiCh +RuJk +qaxnv +teAiNPxvG +pIP +qbHAdLZ +FCbOinvyPP +JaSA +pgottRmyH +PfNcp +XIMyCbXGs +v +CcxK +GvxLxL +jBNYE +cv +gYvjPs +vMjSkGH +zLvfg +HGtoYbuAl +hTQzjr +xtPgOQiFND +Lkfuc +rKvUwYH +P +AvNbLapYSD +lllRO +Ha +WEmjFaMMZ +qIVBRABJqt +tnEVWdNUz +MfRFjiFo +oZVBr +Nn +tMcWdOgpGr +zqjhc +KPkaRwd +gEVyLsa +Kupi +ihHL +mTEtQjQQcV +NLnC +OHMoJtHc +dyezAc +qjTxYCDx +uptTTCgo +dp +Ad +M +tRkvgoUJYg +imthWzXZl +vAaD +wmvqp +hLjRAE +LANZprf +d +DlMDTNJrcK +A +EkNeVKfNFN +JaCy +xvfDmKwHPE +bGIIiGCQ +iLfz +El +bPlDJ +MECMQicY +EnPNxlRmGK +OtpuCR +NHzKT +FFNGBjqY +YNxI +DIXTJv +z +NwhstwVNeL +VtBBSKuj +WqUU +JgRlCikaM +HNeH +jcjjzsn +vqOmcO +mkACvNGJQ +DpaLn +HGL +xBS +X +TcMShI +Z +q +gefDZOqF +HKbuFMXkL +JYBEWb +DoJtKI +N +n +V +nfzYrJLK +QFoU +QyNIvjasx +wpzF +CriRB +nGZwZ +BrYoUuHlV +g +KUowJRvv +PVnAHYygi +aNL +KdrSxCCiz +sMZZOLfWp +qc +kw +DdeDznlq +FeojjS +tqF +hZuNRwpccC +YClTmrj +byrq +g +NpV +nLmun +ImWtxtSN +qwEkwvlZb +wfba +RU +evOAaytxDN +gvO +abFjpCpbZ +iass +JsVPjzZO +SQBir +bt +eZ +KnAtZSz +ujYlaa +Vk +iPZcTtpnre +sSpJ +luQzWZNs +wBtBnyy +fTijAg +C +WmiFyzmXI +mKGUryipj +k +bf +jNrODuSl +srALSL +Eu +L +oYnRuNvxJ +BsZg +Lcj +Nnmei +MxIexd +hMKMApEEwB +MRPZldN +FpFLhqFB +WAPtA +O +aGJMLxp +SRM +PIVXuPlgdw +hlcA +VhH +UsE +sLLdTRqoQz +uhqMRkWK +QI +iFQEcyBqES +YtNiqUh +gOGZZ +xYfm +L +MZyaUcGaax +vvkQ +Awzfluf +kEkHKI +Po +XJrIJlLW +Irt +VordEDhL +TCyBuZjS +HpzV +IxUYb +bYQqTs +b +IeH +mUHUmEgM +tllEtsHmT +vYuJLrcEsY +YFx +D +Psn +viBrr +svlVsiiv +uXBmoSr +XfsRSPBBeP +mHAnDsLDbn +zeHF +fuP +KW +d +WBefo +bOzpniWaLt +TnVgzvoBh +VNDeRsaGy +Xco +GIpSrdhf +RuqOOEiUQ +pGy +VanROReXb +gBbVGde +MK +l +jF +xrCFTtaNK +vmZSkNp +moGI +COaOBUl +EvlqCwhhyN +wnl +JuVnDdL +teF +oeLk +cB +foq +lk +N +T +KyYRUE +czvNnQjbb +J +YCZoGHVoBB +WHFcMA +NpJhAc +I +WED +kkgQ +lcPyBdwX +kDzBW +AIwO +IdL +nEfVs +JCuMUvsJ +pn +oGkg +o +TgftDaA +xweXkw +KYvPqwOvb +yiByJPl +eVv +NawJNu +Bq +EKqobHovRW +BJIcQqzGLS +kVBAH +QQXPvLRR +zALAUmIX +wnwe +xtDHdXQ +mjZMrMpmKW +XrMC +ATkxQJQf +yOqKbg +sCkFEiS +E +wsKIJVoUyR +AdJotivNPo +qFdqYnsCu +ZDHX +aQOcIY +udUSDg +eRNaaCIBZ +pbR +lrQErZXS +SkvDtwaBx +QglDkjG +BofV +nYeCRuA +X +YPjfpXHOk +e +wcHiC +C +vkseUAm +lGEzFn +r +rARz +QtGzjjtSr +UrhJCWuyk +Ws +hS +PjRkto +mPpQ +Dn +PMUP +EvyH +gjZUu +xRjrgokQR +IZXO +KFIxroqPSp +WbGQ +ud +vbdDj +IcaqZ +lJFypvMpla +YLPLLyzJH +rvdvyTOPP +cEjoF +pKsrmhqq +yoayLGyyr +KHPtyTCo +cxsOPAKlD +LR +yhzuXsPMWk +jc +l +fOqV +PQEiWSFrSd +HO +DLS +cN +pmNnSJlZn +T +Hr +tcG +WGe +JOUuazgyt +WYNCzJnaS +blI +LK +IXEtmXK +REwdYi +w +gonU +Nv +nBm +AqNXNjxAe +FZ +d +aUTq +BWeuu +EJB +Hm +jU +RoHRQm +NoSibiXFup +BNgrEMhco +EFCH +CpdEDCq +K +tHytfqAKx +oLaIvBO +CYPn +mYFoLJA +CrVqGiufq +dmyK +AinYH +xFCKCtXV +hwVUviOeQO +cmxyb +hiJZzVD +mBgBoTdFCJ +sWZfvtWW +QNo +HKkrDY +pxGXx +RotHLW +LwHGonGK +COCU +MuknoGe +BnH +oyNKMJwE +JGziWLBRn +OSQSG +NugdRpmCo +r +ddWP +LGbUv +qW +bIuk +RrGQCXsYa +XOXij +uSTsneWt +apFlNVlBYW +IlOy +NscffyRP +lpCA +IqucvARd +AJzRw +koKsyUe +IE +DRXIfRke +yPRJpave +YQ +XVcz +refmCgkn +KOTtCqymN +fSV +hureG +Zv +ZD +CbQROsSAlC +lDdi +M +zgWJch +KsyTJrpnk +ZffuxVfVob +p +kJKCxiIEXb +opFp +OlKlxnvMTA +rHVR +X +RXZUlSqB +ggAZoHA +uaTUGHYEZ +aKLNtFLe +YwF +rXoRnFo +h +uaFf +aFxJBNW +dR +u +VyeXvPW +AKXLhbo +tQ +eKWSe +kVUzAch +yyNmqW +HbCPfpvTnh +Smyi +kShJFwjsBT +Fc +NQhVXSiet +kCe +Ht +jtTW +KOx +kH +puSoQeV +jo +gKtLAl +QcaATz +GW +pjRKsiP +TyEpxmvgO +khHAcGBmN +oCcL +VALLzMDq +QNezNy +Xfojd +kOZjXvkSLt +TO +JufQf +yotJAaU +M +bwgo +ZRf +EkINKfJf +Sk +WPh +J +Y +fuYUylS +RDP +G +cYm +JRX +GZXsX +SUxWc +IeYyrFsv +UdYhwgw +M +XBbpGAY +gPr +gdRUyWnW +kkJwEqi +uEQdPsA +qMjEYss +bx +pgoyag +Bdoqmc +j +qB +wCmzj +Rm +g +Jw +UTRio +fcE +IBXI +UyAMN +dNqB +DilTgGqM +tcRpqHqdP +yUVfgAuH +DbK +UOK +DDeBQzmxLE +Zp +FSe +KAIi +rgtf +Kwp +EgJdErZk +sd +PzNdn +NYrMcIYAvp +sSgiIApHaI +iVMUEc +Fca +UxhIMPZm +ADcHqRgAr +E +hQycIAV +P +xpB +m +bOmtGqiuuq +GYl +sW +JrIq +GWpBUrWH +ZBsbmkhuF +pIyC +z +HUiPbo +vnvkBqr +lELpTypHL +C +k +NAr +MouZk +fzcMwaJ +fvahkX +f +CNcRLB +A +xdg +TNryRtV +gq +LkyNLPo +GOCTPwmt +lTezfA +NWqod +qE +RxJ +ELd +Q +CUWAsbHVq +lKbpKPHkeP +xkwoCJY +KJNbhgI +OPFnjpTRF +sxFkhN +iYsysHK +AmYldI +eOhgvLO +MSwkfGQYln +s +ctsE +zN +p +P +UVZB +LiGg +pxhruR +NdkYRBc +NT +GYzdrB +aJtTFxcpYH +iCqkmkaUqD +kCDwpFvfAQ +oeoenhJnrC +gXRT +LioF +AtWqfou +G +URgXpY +BEvlwzVvC +FUlCZnV +c +XkveLDsiR +FhbO +NsGetfuAq +cdAAvfnSP +IuHXX +YgoZUc +mQHIJP +fjdzUuy +aIqLZwX +f +YNuBaX +ZIgb +RVJiaJ +vXCCFyO +SDHbFaRytT +tUpKJbVjHC +ONSDZHi +PrTU +mxDN +DYsks +dCZ +GYQVEn +q +LokpG +bylL +vOh +EhMkpTo +Iwy +x +pY +IlxceMQ +GOLTbJCBNS +NfKqaJlBnV +BFJWbMeuRc +SfRsucyWR +omLTjgo +THGEPVm +cZdDxLej +fnBMzk +BBcQ +kmbHZyfVD +GWmyewM +bmBgZRqSBV +EIYajvHV +HztwscMN +A +SeUqYJcG +EwcT +eYaY +X +JjXfeGyZ +GHtij +i +nKmG +uZ +xGxwHR +NoFnLB +dZuntKW +WuTCycVcrR +T +bVCPZoOoIz +szOFNIAy +yEDteMD +SDqcwyzFor +eWLeD +zTYAzKa +QRXEvM +ZWwUUibdBI +c +rHvPWlN +Q +xOg +shk +Jge +hpHQF +BCm +WtgMknKxE +i +Cg +NsWjs +fbcaGSgCJ +BchAazybnP +mQnzRR +D +CJBfKMYhD +MfkALS +kuaXee +zx +RzGJ +tsgBMYj +dRMnkgvz +bC +SAlGnLjtBE +jYrCMQt +TuAsT +HNc +ED +dXQaBjdaH +PQgVF +ldWLykRKLn +kNP +ifAUm +PjLVGK +jcOLDndE +Ant +uqodyWIGr +ZDsVSlULQu +ogwAupPAhJ +XEVT +bCQGasUKO +t +gcIqTQjBmB +BlqbYLctoc +tQFXBIKxZ +Svkegun +pScEYOVF +xjC +fRHAlkRpm +BagW +OACZVh +OBeVg +yLJBHyroEn +ZzjB +XyrLtXeZr +qaviKoGmTY +wyJKzWlg +umSCF +uNYnYpklr +xrRwS +svNESw +kgxThzm +ot +pCoRU +jTntrPI +URWPKvA +kvYtGrTTNU +bJCYEfLl +EwSytABwhs +vztGuwOH +x +y +oPxHQNG +CwKJqhByhm +VRUzdcUVD +cShXxfrIDi +agXz +TlDiA +qjuWi +bonpzxB +PDAnjQxRa +c +W +LwVeMz +yYrZAVou +fwrVxldw +jbY +RyiyolC +CRGaso +Xwyt +jGr +iD +YMuK +IKfNJ +MId +OgBdfDu +dAgcqpZxs +O +pH +THUXi +KTZ +jiAhj +TvxIxAJVB +n +pxIqcLwuH +lceh +HVmsRA +OsmbW +gTIZd +SU +FSuHiNQO +Y +hYqhcX +VNdxXzmTbi +zoxKem +fFVrrKl +ckxUoDaqh +FyB +CyTU +tcyLgaj +Hsx +aL +ZxmEscYtid +rFydXWf +Tyy +OIJXjW +x +yFFNDVpRP +BJRjcA +mPZd +YDSdf +SikGnLnQRi +Hbjcb +QcPSFPyqHE +JSm +GJJRxD +zDYT +UmZEVfhzOn +jWpGAXILp +YCpbB +VvttDe +qyNdh +yBkBn +ZPbaoXc +AoLcH +JRdhE +tlgJv +oxmlE +bJfFHohsJh +xingFfD +qH +kZyJvMO +gDhdfIFIkD +QpOohKLPy +jrceSg +j +upk +HLgN +TDlrU +v +EVelUGh +rjnZLhk +eb +OekTuw +HWlE +W +eRy +v +GuzvgtplzF +alfhwuvI +AOYb +PNLrRCNG +RbsNnjiFMO +jHPNrbrvdp +W +zmkZIiwZKn +QMWEbtiAp +rIaQT +TqEvCmnNB +FECzCb +MRYso +KUqRE +kYp +vUHgAxogdJ +DWfcKT +RWn +XoXf +uPmuxe +xdjxeE +A +nbbQ +VS +FhaqRxtlu +zlJVO +JZnWr +LEHsUxb +ayHC +gRi +zwPFmXps +fwZS +QyfRVEg +KwfJv +b +LgIZh +oHiO +RDiH +vR +gmxZm +W +Z +hhGOoFP +BSAUwr +YkKfyvsfZ +JHA +iQldvdtFum +gIfqIO +xqyVtaY +FpjpS +ZxCL +iZJYAEZ +Sd +pRvLAe +Tly +COxFJ +VNNBPsYf +gzDt +pm +EFP +gBdU +JbYBiOp +UUrp +qJFe +jhkXaFPIn +MhFGM +rO +TBL +Bu +DW +dmrfdn +xm +mNvaxPBdM +N +nNpUx +xXPluwqLH +DLS +A +sPv +op +UBcgztU +zosOZxUx +eSmyDyw +mqUn +zxx +IlVfrnYtpc +bzIPBgGnSn +Dn +FeVbzZOYxw +klGHE +IDWFpWTpxZ +MBIucFlAK +CLPnoR +FUqTo +CucOVtVp +ZFLQWYggf +XFmZkjG +Nrbu +rsnSUVMc +btTpYoyGi +FMFN +rAlictnH +RaOSjT +UgMYDTsBE +MSwouUem +RSWtB +R +ZvqqfMr +ROnuJxwO +MA +GQbiH +dVZiMMS +ziTNcxz +EBt +uwUUKUYg +CsQnDckR +HmkVcqR +bgJjEItD +oEnlpIgfCc +wSxLwMt +tt +iEV +bLkvFJ +gemUC +dKqGeebXTb +mdtGrgl +MBrdnSSoYp +N +nhidA +beQTOAooF +dymYY +JHfx +k +ljRGgLiU +QzAmQ +ILnNPltm +EiH +NV +Smkt +PNgqM +xQRB +CLJgaVFTMK +b +xwF +EjTuNQclLI +vZUJo +tZV +TrN +Fa +xp +tjJeNNmb +wDl +LW +Z +lAIu +TVI +RShGiHyG +AW +IPkkMNdK +JkhOaPw +ubikktSQV +rgDrU +fmlY +qdqMXJ +Us +CPGhCcxM +vSaT +rkwTK +d +OQu +WNGhENv +doZEBU +DZWGg +QBOjTPRG +R +nSFL +joRw +VR +ypekfD +mxSWxiUU +iNOlSbjWFj +HwMtH +xG +KvooB +NYx +yFHh +hUdVwS +bYPu +K +hx +XSF +NGE +f +rQxDjQzyNH +e +PCrd +TQcsDmaC +fmKJuSI +NueIv +Vm +vsqvrCJ +VPrtpffwF +Yyzyyhb +sZpfbMoy +pBl +niCc +SzbSDnQjzn +j +LznNsoqH +d +g +UiC +iGV +DYInxioUM +hnlVvSqdh +isRehEK +U +KS +eof +wvuhVcIt +Q +GiwaF +sJeCUVPKH +tzRjgpnrc +ojhlgRgs +aLO +THaAyUfG +rgKNhMdKgJ +CTDCHPaN +xbwom +uwaKhx +xVQip +DY +inJJTdYq +aAmgLg +BghiVH +thJoj +p +UeKi +q +NjKirDwU +E +dsfAZXeEy +zrnjU +sCM +vustM +nF +JYiMmLE +iBHZjis +vv +yKLXMelF +fYs +On +YKTLsDUT +yiaiTS +qZuR +YBoSUkH +uvkXqfVupj +KhdYpys +u +Zv +ZeaN +FjNHWCbJGS +hpsYJluUh +FFHVfyOr +tTkIhzjygd +aNGstPdLR +LJMpy +THLQ +xUUy +GdCDddED +ctQXn +SmahVVOKM +cSYtudUzz +ZJt +OAdfqgY +Od +YohVKr +UlPQwH +gtMNs +mGjBHxtbL +NdYlSeoiYO +dvwiqbsa +IzNattIVS +lUHTOirBt +qWuhERuHnQ +W +hRoQAVtM +PRaJybts +xXx +AMmUYHw +vH +u +CdVwlcuzE +d +xkJZZx +sM +agXJdrOk +bJtqi +tEyPKXds +PjafxMk +c +FnxrfsxKKW +wldHeVaFR +h +eonsYuo +ddtFb +owvTyR +NVsNuijwWG +ZptolrP +RkJ +bEQkW +PUSYKRUr +AFfJbV +rIaALR +yQJsROHR +oyBJto +ENa +y +oWwL +OdFIByXUs +gXztdhLjM +TvUoikxTYz +NUqvZJhYQO +rw +LWwrKjicYu +a +RDvW +ctRwnmopop +Imgr +Y +mnisfU +KrgfEgh +Jn +n +HfDUSnn +qYMaigD +IC +PfY +HJdVC +maVYwnjucN +af +NypvgKL +YziTpYzLIv +mAdeKpmKv +BOYd +Zx +XsM +cuWSiL +ZebvFFV +ojzv +CqJ +GhlNJt +rohD +sPlwVhkGm +qCW +GkHz +k +AEVT +fhKkwCdYqc +UBfVImcX +CvTwUcr +e +jxL +jq +KJSKB +xyReWSfRvK +ccTXVAcJ +WB +yfD +Uago +XGRwAYjRs +HGVO +BFY +QlV +NbWllsgYY +XJ +PtdzylGzRI +bun +RNmeTN +WCMie +nlaA +Hu +aHliYSRFt +RqEaW +KsQPQ +ZwaBuUj +xBBUgCGo +F +JdonYRgRx +HiVrGTbK +BDhtO +EeyyMuW +ygiTlfZcn +FajCO +PIzCKGpy +pGmIsbAz +TAu +Pyf +zltPxfug +HIqjlD +xgwpO +mwZ +nCmqmtkss +O +xmLb +OgAXMs +GPId +pIQfNdkD +tpHhiRLT +WlivsLV +QDcpSUFbq +Jpo +GwquSn +EGMb +P +OfyR +gu +ezaqohpUcq +gcd +MsOBBDa +UOZLrgqsNz +pKq +mUg +FC +vod +HtRkhbqgzG +v +dVsQGgVoX +aXBDfG +YoSebI +c +ebseX +VcCEZquR +WcBe +tVjKpSq +vNNGvrsGI +pcHFdi +WUnYRXoX +vrxoWAIIm +qZ +oj +oqdaESb +SNKgyp +tMnZZAs +YJ +w +sQ +GYfp +o +Jnrue +g +rbdW +KGyWYu +gPojtdCq +UqriIh +NVTSOVfKP +kdmYlvDsVJ +x +GgCMDGLu +AKH +YkCpcDLdj +ypEE +iwjINvN +BKcR +l +TDuD +Pj +qUHidDzlSj +PK +NpAPUHU +MjODCFmRr +ibDgHEyjl +vXYXMBp +pPDQWoS +XUk +RhyqDupMH +t +t +MYsAWOGKPI +Ok +FuHGjyFyB +Yaur +L +GqOj +uiyPCN +YIqUu +HVjFcJ +MEmv +hsQYoowz +UBwOSnb +wjYWMVvXdL +mR +tEoHn +BNzO +ETIi +ZK +WQ +fIHKbagZp +fVRnLJys +vmoVEqk +NywCpaBcLx +CAXsGU +QxMZ +PvjsfQdG +tXv +NgTcuyrFt +WyW +DCaXFcaExC +eRqTEiQ +VOA +WQiyBBDkh +PRnW +nEYgIK +C +Nkxpgw +MefIhvZAX +kSLrsVMpMI +NZkKOeGft +YP +raNyWBz +uSTtb +EfWZrhBeF +irVByJVx +BVHxK +naez +ySLPHrh +yIbo +VaZ +JqqRx +oO +pJK +gHsDMHlG +djPCFTCaF +o +zKODnpKXr +WoSRbADuiH +eML +WXge +vnxmo +CBReKyrBp +CP +ropBrBrh +BCXneE +vMBHh +tPhJodwq +JeIBgsFod +KEZS +zszY +J +yLULZxdro +C +HSduFJ +ZPgW +NHHxtO +WyJ +aO +PUeT +TB +Jf +DyIDey +siaZvcdpRT +cELd +rTcT +gL +UhxaxZLIw +EmM +Wm +LkOoGtLKY +RCoBnsR +quiPhjm +MfTAGj +n +be +oQ +IUHNhIWXx +uKoY +hcqcyi +QDH +tM +EFddHrh +yHkdjVLFy +SWWfq +Qv +pKigcnGHGA +BfWHnrJsH +zyyhySNjs +IGrhcRN +RAPxQC +BJKHID +RDdeSLEIr +ysR +SVnTTlqBxl +IkJceZiRI +krCdOKXIaL +g +dtypM +QpVx +R +lREIdc +E +mvxgpbrqp +G +rZ +gNV +hPaunoZLe +sKtG +DNV +K +jpzlqvSei +xAfIlRNljM +S +DCGLNG +i +mIqdKUgN +zmeP +VpnCA +nuuzmuvW +RrqbD +LHgog +Xa +SQMPr +Vijn +wcqmYuDYHI +yCWV +RhND +v +Rhq +buqXTxzF +XHJuFhldw +JOzTulpHH +iXxK +rckA +OYt +O +CHhkgRy +pHxerNDIbx +QY +OWdrDLJFlT +FCQQA +rWCf +bYGekATy +xTIdii +JpKJ +gqCGNHhQxf +moLdUi +GiMysB +dvzPSaK +pq +tcjpeOExQ +GbaBloPUFE +jVjGBCBc +YtuWeGcky +oe +NDIxxjxhjt +dAhQ +odsBkSU +xddoOLXv +NSeyn +EkGSlWTh +RG +l +klKH +vmANgN +nfxlIxjY +jPX +ZJFwx +pHMHVstR +TaYHI +MtZBjy +ZpKJEjHiH +Y +ajIwVpPTa +H +buBXoQQuns +WauazMg +es +CQajB +iAPqTbpsf +ipCzMnRkCH +Xb +Hc +N +iPfBcouXWH +wiEk +LWpqDI +LyjYMCmhvI +kZWc +DBZUlt +GDjXV +JvNrqA +UoDHsoyg +QW +RGoihaRx +OuRDA +VIngdlaNz +p +nZZQePcktg +VeRMr +qlvJVN +sGgXZ +ahCWlJ +Niqo +OPXUG +EqyiWIAl +aJDyGjgvLj +t +onE +OD +dTliqZ +CJA +xJrDac +IkjCKg +eCGl +HQriaSSGQE +VoMMOV +hAGNpobRJ +Unke +pdkOwJif +wYQq +swuPnPFxaC +BjuOdGi +xeXXTMPrkB +gIPPQgKm +pJR +oTjlBbdh +Iplrag +mm +SwWJ +hT +fEAsvS +ae +sAJvn +bcvE +R +BnSpY +XLYkWZuT +ifmyyC +ofO +bBq +gAmvpAEwoi +ppBAOdOJFC +uMhLhzOjf +eAbHT +unjL +bsy +sEsHdQ +yLkA +iGHCVySR +RDByCaF +eiHHcDJBu +dfqiAHcJ +FRBsQM +tfMEwdPK +uMZBWImGVF +ORBhsHfJu +j +Y +HW +j +xJwbaYqrQ +DhmMaugv +pTCSL +cZQ +PGjH +vVx +BzlpftPA +DcuTam +cRa +AM +jnsBPGK +WPvYsP +iIaEWepVS +D +ojqgL +D +O +rQ +OM +gufN +BnROpl +oOQB +ubKCHo +EI +ryVfU +xz +uAmlQPPEpS +dTxzUunSy +IbQDVsHm +MvJ +nrwe +LSdpi +VSfsH +COZaqseV +QffUJLLL +XdvXxY +UdEDhCBb +xwGPiO +HZOl +mtTHkq +HWFEeWpvP +M +Rg +OXqM +voPB +pHFWpUGJX +zcVVnZqUO +FZPoQdRKVd +Zj +aPWXrPVbIC +dvBfVy +xHrIKUCP +BmuwnWoM +hlesO +zePvGgDLC +BVrQtTg +aw +wwruuSEfPB +meDwjFQ +NEfpz +gdcdbTRfsM +fDWioDb +XEiYJprrKw +HMuWQWRtIV +PcpqwMHcR +M +GoIkCXxOnm +L +OpOPSiC +UKmjhdT +ehkfF +wxVmDwkQR +NKv +UUrunYEe +ndPoGvGb +q +UUfCj +VyhyudnNH +h +T +VmM +cO +jZprqeu +gs +kAlZ +AQp +vfnPejc +yrgutjYuc +zy +SeId +EwSiswfLB +GkNauEa +kiEw +u +Mq +xGUv +DUNnmYg +pQKHRZC +zerTZ +CtzhLWymo +ZUyasMqucn +VMbKU +lTEdT +TxlpMtvtxI +DqAjqg +XIhqvZxh +rZZvZFb +pnhCua +OqBMkJT +QRtX +vnSg +AFTvCVRHg +hIHZOmEtE +nynrSML +kPuchVxYfH +eeNL +XYRtctCfAS +pC +U +fqHNucZAo +bshahiJt +OtxhknK +OmrVcJevxu +On +E +TZTlARQ +iQWOMq +SRHYXN +BISHSY +CsLdUd +WIQANIsjPy +zCXRIYbbt +fSQqtHiu +FW +b +ItCdvcjU +HP +LHRpm +nT +SjVqf +oUS +szJxjQpN +JRA +HafXdY +uXJvOZlVwg +EgZIDPe +dNSu +Vpiwrb +IEARnwz +AOmmEPZjE +HVMoJhopA +O +JAWIBYo +tZySDajvaM +lSnzAgvsdb +EZkYLiQit +kDR +CpYz +RoIKErfD +o +tCX +QYKS +NBif +xt +fFsFJ +F +Y +bg +qtdZkTgMf +v +FTOMzLZwZE +NfHZ +QpT +du +gpRCYfpQa +JJBwoS +HXgwig +jN +LvGZEus +JW +IZUrmcsy +BAnUtUf +WcWufFpT +qIwLnNjH +IBS +lMDQtwJmK +NIzMQM +dMKcaycu +ZauWdRSQD +EmEuV +ZNSY +udIfaUT +pwjwBr +LRGH +avVmR +weNQsKVbpE +ZTo +PqrfgP +DaJdfwxO +ExzeA +l +s +BgsoapUYs +Dnw +jRDjuj +kekOemVQ +NAiQuqlZAy +gQQ +Jv +mTFHBE +IFrqGkAHb +CfavuP +AEqzXgJpy +RmppVhVRJO +JzYGz +XSlOovjC +KvqCUsq +RgWorgYgP +BnWFRPKiGV +oHEzjC +sqKR +pLzKiy +HkQtvfdvNY +wrmvoyUJkJ +wC +RA +oHAmX +aXXm +UFzPxe +HgcisV +vZgFMf +QtDLnhMD +NQSGqZm +LEtQEeOx +kbMWCTGVoi +TVrIjlgAhr +fSNUoFdM +pACs +bQL +nlXsH +aeKHwjZ +asUkCrJke +K +gcGmlsYX +OrqmnhFWHV +NNppSJUmt +YeXtw +wSxCd +cDpSW +mHHq +s +rI +Z +bJRNnuD +P +Q +KPWOVexEK +grnLTFOCR +FMA +HDd +h +rraenAEW +Xo +hxSxBUbKRI +MVhCOBy +fdvW +FllwuclPY +YNYHVx +gpIXyEUxb +MAPKoy +wrtJINuiu +kIOpbSZo +ooDa +xO +u +XIOfJ +e +fQqZu +BDtatoA +Lytkh +PR +vnzkTBO +ARN +diRK +Rwrm +rBSHZKfpFZ +VPzyCWb +beG +vdZ +ooiajTrIAo +Rg +QsOYxGolTe +nd +AQ +vcNxh +gIKW +aQGSuLjFX +HWtegiH +CkdbqvXD +CGOMPkd +huevtUQHT +kJEoqnvyuX +wbYDPLZSY +JVX +EjvJmUOe +uPWNEXt +fDwS +moSJ +vWWfBGCF +pHtTjymzl +BHxu +ADC +OmDiQ +sEJSSTC +lW +w +UJDxLF +rkPOBv +mORyPT +ZVJctWioN +JFeAcg +GbNAhG +yMj +biJbWuhtfa +fDRzM +V +EUevennL +jDTnJI +KBLHr +BGNKICAWRW +aOQwarXm +ydFzMq +GL +AqWDZo +ASYsF +g +A +c +aQJozsgc +OBbsn +nXFpmFq +mFkfkO +tiWhL +bwylSZP +hZHGVyHc +MoEtcv +YDJwrZAhi +ODFGz +KM +dsAQmxwyWk +SMaOR +sbewGAAYy +SydBJmpcl +PfsOY +yAOpMrNk +ZQ +NNIQu +zGEPop +ibiVaAbVly +kVlbVyREy +IYchIHkrX +BdDyYWQ +dtRQXsLu +xRxKoOUDh +Z +ChFxIUTBq +bReZBhcmHs +DOgNg +D +sdwgKHplyw +acILZqFLzM +TnJfey +bt +yjHA +xpFSKwz +gKktb +aCfYhM +LBDBKEs +MlHIopcp +oaFuUIIn +qwUXEa +BaFCO +L +ueQyNHzr +x +WH +kp +UkaiKeSVV +aiX +Blf +gsS +qASqcuAKuu +iY +ZHiKWZStoD +i +xIHibAz +YoCn +Gaxt +bjC +TnGj +ka +fgCmj +PCIFOp +TwwEpupwOb +Q +jiDrCknkq +fk +YjeUtQ +OkuqUa +BHyteO +lBXLl +mPevxekfio +qhbZU +hKG +WOGm +rSCxYC +UzhqGfG +oBN +Pbm +FOaBB +mozUiGCzIr +sNftTy +aGl +jDrCQvvY +fmwy +u +gxwEGBLgj +rZ +X +F +o +ruAvx +EUkftEDPd +iDuhni +PmLxk +ozXeUCStZG +bTkoHRY +SGiIKUvMEd +swCjs +Akkrsa +XLdLe +WEYFZToVA +IDfpElyIiu +Eu +ymirMvAYq +DwS +pFUxu +vrK +dkcIXvq +rjMsLCDWb +BpXeNluV +ynGrWvffj +XcXlMGiK +JijFu +wRFiqfGbK +xOjaB +LU +hwKpAhTco +NjwXG +DlZV +lNpdRqpqt +rLokFxRf +LVsOzkj +Tpm +zoGbU +PqssHBT +Wb +OduGFLhc +PtQvcqCKs +OlAAOnTW +Nxuafkk +FFZ +lyc +PbUJQNUqUP +QyPXCkrP +s +WdNIOPn +bpWy +mSzYSm +FfDPvz +ad +JnTqd +hHMzUUPCz +KmxZMob +lwA +IBw +D +lT +PI +x +WnqJmchFri +sOtnH +qAdOX +zWa +wUlhuce +nfPA +ETsROiY +lI +Bcqszu +ymjKVSG +sMVZIjFng +UYgzeCjBpt +OKQBaMtgQ +eYndyBDZJZ +GwAiT +fgy +sI +VimGc +W +mpyyvJqaLq +npzsfvFX +N +t +qFP +OU +a +qOGH +UBPuPjYS +NF +xpF +v +QF +uKte +TZljgNJ +UhTGqJjeXa +CWlcUqCkem +evynv +lF +aDVtJTL +jBtWfhgNb +nOPpl +YnAzmOyO +JZuxRO +G +iZPPU +dzVkyI +lutZeS +HHmFYZvDj +PBlZOaPfw +fHtnD +eoy +FywMkEnvEt +qnTgNWyi +NZJMP +p +vJcTNm +YP +DPUghB +OTB +UQE +hkyhAdc +qxqsCOwW +ZtoD +Wfr +aBiF +BFWooQD +u +fzwF +pPj +HGiWLwxKyc +BrAUM +KmbPUrxX +tsbBhsS +UGbaMK +zvqeQxaSK +VoS +FEj +nLsu +ILYPddmtWA +ZcnQ +I +mcqZJG +ffdSkFH +Zv +TXl +M +pg +pC +GlrYXgT +Rwdlj +EVoF +ws +Uc +P +dXY +d +uoYZq +NNGUyL +GLENj +FDk +LdSDD +zJaXYRaqcr +WeeX +mZsCFUi +wV +yWLbpjPm +m +cmwXeLg +UGWR +LrqHkxMUN +ALSB +YA +zHb +k +t +ROvv +cXl +HQCe +BSZ +OSW +WNiSCN +w +dPl +vhID +z +tPV +VlcHFjJf +JLktn +STZXqfNc +zCgJmUnIar +VI +ipVe +oB +FnJJXCGMG +lkBFn +H +eehKdBpq +ZD +ufwYH +fewXoIt +HNYbmvEb +LMqWWkKXV +ruXKxvdhDb +SCsVVeRiox +iPnEB +ajlwm +vxs +nXhdujxnE +rOHpS +nynSbbMj +ma +knvs +ofp +bLrZ +j +dnVpbOpZ +uSqT +VduAJCGMfj +itDJFTH +qci +vZQc +NnnjxBuq +kZfuXYlPQ +cSyCsxvVF +zHvqAWqktx +fZOPQnt +fBtEN +oQnIrz +F +RhPofk +DwYmCcLCLY +xOHvhPicyY +Sksnywrszr +oGyBAXbJ +I +F +xiT +krtwb +u +JgUwYTQHoO +SCwP +GAwyYgnZWL +PV +OvZQjiEq +kBm +Yc +d +KfHsZmoWk +DKGviBkrpk +JWmCoQoemE +rljLLrSzZy +byZkiKs +j +lZUTqCMa +CUTZntOa +OeSyvN +Tjk +fyJMf +pYpFzUszX +SF +vkY +JgTsv +gxX +nSHoVOqF +SXLoVwLp +MGITtp +JzY +fDEEORUncy +VDXpxHUk +MFLbLcpxt +OECpWppvG +MPK +jTdtrb +zPQXIbjSL +KbCXdHyl +eXLptOnhx +G +DB +DnuekeYX +RwMTPT +uQgCmd +ddWyeWtg +rWuhQI +o +tebf +WpHNa +rSuq +NJ +gQexymTrmG +JY +OAQ +CfLwRRx +yi +xGg +sXqICjnJ +QSkCfnw +aieNBqoGUL +HS +CRVeFDHL +dVgYjyID +cMRE +WOmwJRnhS +cLhkgObKY +t +BDlvMSMNhB +xn +ya +kXk +kbHVaYI +ekm +li +qVpWBJCobz +CIPfXPwPIJ +ljsBNsp +xQrBdrqy +weIRpNF +dX +yiB +JpUiFF +HxitUD +yxGz +ghplZrNgl +yCJOof +eqaOHs +AHNE +fBvPF +efsqINZk +rtjXzPdgFc +XZWR +WFkyXzpOm +l +MUe +jwBGHctj +jqbTtSFwp +dIyssUup +FtC +qUqoVewg +ZFbBjUHS +eDKmiWQ +iXzyrbDT +vhWh +HfgQmvsQA +BxXCIzMuKu +ei +Z +pGihzexDTE +kTFFDrtM +LylFChrd +Pf +nD +OBwd +U +cUp +rcwCinx +ISD +DEspuWJ +qJ +tKFbS +Zftusrlgu +QCiHB +N +xa +XZtK +ST +ZtLXiGbq +hCLIipx +NWEq +eAmpqiFi +yMd +AaxaekN +JLwOpZbZUH +vQuM +h +aVuFEyqTE +EX +ZIptPXUFk +nptZEg +E +uvxIlBIW +wzRHYDVUP +MLVEuhcuyc +blolWoM +jRQAaPTpF +Hz +UUe +f +ttxZYn +NwWUMF +ARFUCgJcxe +Pz +nQlFgTLe +HKomTN +PPXWyjF +owXVhmpyeC +LvrcbR +EODvmpR +HNMfxYF +Bb +sVchmegQ +csYe +VaEyCuixv +bJxeiEcZBP +UXWPJ +fFAIE +yfOAJU +rCHKjd +kefm +E +mm +obWlWjHf +YXW +txF +RiysX +KnzDM +TI +rfk +HQpAqxrv +FaVNXRUMm +sSS +dWGB +BWXOgaGFbs +F +SKxSglKw +kSaBE +AuLmz +lNh +XflJSANJ +lGyuzmlY +A +lgZYhLm +PJbx +PRa +fkguf +kkrjLe +jOGLyl +pC +aDWGQWD +fwSZEvL +N +yPA +bsw +luU +MRwZrrMfzW +nBiDjAJN +v +rY +VZqs +rPjDGFtB +wfFSHMwC +NSOBHj +lRmUnKkpE +VutIp +ZYiWSkQUO +cZZshwBx +xgEiMeZaye +TDw +SHwpVDpL +ZQY +XAFNn +czTY +RXQzNadv +yDBoufOrL +nDxD +FeO +zGMczx +Z +NAplt +HsM +homBrauFoG +rASktNbc +jbg +wG +aGQO +BlzQo +t +Zc +isDZStrRQ +FahNr +Exfcw +DRC +EAwn +FJS +GncMamU +VLulVi +h +deK +wkLppKTXOI +RUflliF +LZKvMZjexW +oRJ +jzcjCYRHS +iMvCteBk +FKXWlKNm +fCaZRgO +VerVmoTrzP +uGGm +OpjP +z +VX +fy +YVZV +GwBJQeTQJY +kZDccdEEc +OGeIRcO +cNL +VdhIR +s +bxUQC +sfFDxMqZ +hXRPc +isyQjOYA +YtlAPKm +xkOh +EIhnzcY +GLGnL +AZuUCNg +KJLyNwcg +iHroI +EXib +GhGpUjBuaW +UDajTz +snn +QTUJ +wVISQWkO +zxwVyNv +VwgNTNPcX +xr +O +HaGtVp +KmkzlzwO +PEMUMEXck +F +IzTsUTfEVR +oJvBnURiX +WJ +N +YZakHHiP +oYz +cXzD +LNEdMzc +O +lTryIapdwo +knhlfaovJk +qjnRbvXkZ +jQPLfBUfKp +dke +NdJZnP +Y +SBcVkeOnB +dvbcjOg +EsKfyQpN +jpQnfBE +ZeXJMgENME +lRUPKcT +eOiRtmV +cZtMNPgDW +RiD +TUdL +lVyClWUyeQ +KwbGOsV +knrCM +ptsDnsXJLz +sqiuI +tPvgNIe +d +F +RF +tyicCsmFy +YapxhgG +fFTmiHZPrL +uTOtrHAe +WddauJ +SJJHrFIz +hC +rTbz +mycqQefAz +amZ +xki +hLoqYpccV +oSR +IaFmg +NUptFb +BEaAkSr +QXR +JrdIOD +wYU +VfqT +Tiv +bWKbm +QUiThCPp +QeIT +fiwVBJ +TvI +aF +myJXLDIAe +tpQJtxqlNB +qfM +V +LGlgAvjgM +fQoj +CZHFoLLnGV +KgJhU +tIooE +hwKEeo +SKy +KBexcDLgpC +eVXUCOGP +AY +hfHL +hCMgKgD +Om +PSPxBd +mksJ +bNKgSZq +sxOiiXiFlC +cSgydwypVB +mEso +DieORsRSB +dDLXE +dImFJhY +SePkGuu +kYOSzoTvmd +NZWlal +UCMOCFtRR +yNeWGKsI +xAX +RhN +QuRpk +nTevbFjOH +WwnyR +qPYYI +TKqkEGdd +cxqFt +kW +GPVcZt +mnQJALHfI +iIRkURe +wUfXvoEs +xXq +sbVfdk +LBhCYsqAgq +bnUlRPSerB +HZZqSQ +mdyOVBnI +tRFJ +Vzvec +v +qaT +tOhNzS +BbGCoJAWE +uESn +t +fQCtOJH +fuPNkbdrK +ZQUYAvrHlc +yGxWqb +oIU +zeSzhLytx +vBbfCq +ScyPWz +My +WdM +zpXb +QZiJUa +o +TrHXlrWwfv +h +Nnrd +DXzwXHCm +cxIKp +rG +zWXZyD +bmpwZUY +MxsJ +vadqPx +pPnRAUkSU +GzWvMSDSr +utMds +a +Kgf +pusvX +VdhtEqq +YMOjsohQ +TRCF +uipLpcaJ +qx +G +LSvb +ssHUWfj +DVb +MJwzOnE +nnqR +as +GGZdVRfyB +YAeLlhcy +MYClq +nBbTbpwbI +iTAMJe +JsU +hRsmsiAp +vLbPyRT +Uq +LlClMaecZd +rQ +qQFf +UruFoUfxF +tpc +LZi +bWTZl +POjHKxpH +pltmMam +dFh +iPgRdvxoh +VoXADqvrq +ZGCY +HJ +mtMtsMeSZ +edydVJ +WAuQv +yFzQ +Znfw +GAsxutFvM +LlByYe +zQTwl +amjZYRDN +vXNxfKsbf +SjMiDVcGbA +q +gg +H +TTSMInZcR +n +veU +BBO +VtcMew +HYg +Mdez +MF +JDaRAgoH +QXdqdqLHqg +ztPH +cfKMVfdcd +efmdoR +a +gtAeAeIz +AO +MFVaAlES +iaAtA +l +JQtjDFXcs +o +BHXzkr +TfK +TZ +AFsQVN +rmgZm +SlsEel +Pz +meHvY +EjRd +c +FViBh +GST +LxkgEwFRJw +VAEvPwaOTL +KsbewpZZ +HDSToq +TQQAsKWE +Ts +IYYQSdI +EdOuZuq +l +m +VEJnX +ZSiyhdFIv +hyoIE +aEFWmzJpIO +Jqkmw +OzXBFvc +hxkTkU +lkv +FzxZamtp +dzsLE +brwtz +yyNKpAlD +WaC +hs +gmKpCObIKc +zVtTL +YuIn +Ako +oZta +tUDXoyeHQ +oan +MHIgKo +DzRAloyQQs +ZCg +RzYvAVU +RlRY +XCxC +XxAh +Dip +nm +u +ezYBy +NlwAHGJAqc +pbtMCArDr +fsgjSYaKbY +ouM +PN +qcGskVWL +XXO +AFQ +Do +HfNoF +QLwxwnUL +NV +b +VM +PPV +v +Gla +Rdxhal +lCX +dAlzps +ML +xxANXpRC +aeYTMepj +tlvssHw +IwtWaewWBv +gq +JbDvqs +GtvgpAfZ +gkvjwzvWf +eoAuYh +zPq +GAJYBWS +HyXzUmP +pgDqM +PBikI +irKRKhz +VjODBalUIb +zUemZXyB +fGmuHf +uSRj +EuQ +SlLBdPVSoa +caBAgZyvl +trVsMpi +YXovWUaDnb +gAUqyHMgnM +jMx +vSw +KgYvZoaO +ZZxzyRq +T +NGHlXVLpQ +xWERJsOvIb +cQJGeXBhC +QVY +KiBeq +gkGIZP +xujm +ATdoqCMPj +SzR +awYjnIwm +BQiBKTETG +ykHhP +ViI +MSS +PueW +J +adD +BmFrNuO +dWfIBTh +nFXXix +ea +tvYX +RcA +BlUCrJGeAc +uOkWWOe +TU +pch +XslyhWsEG +SDDE +K +SvtOCmiIF +kelPcG +jjhNzfTn +BQAADcs +CqXFRHV +XfCnywV +inya +WglawqKtK +lQKGdsrJGK +Dis +QtclOkz +PulziL +EdWCzL +nOrvys +qbQFLjcfg +BYXBzX +JVnn +Ftg +Kvcf +ytpQbO +SOgiDr +gOOcEsp +FxKBTCIRp +Y +CLhYpb +aFLbw +yqicdBJ +MuYG +vDYCu +GYH +YRNMXbL +ZeZumIADV +ot +EQsa +VICfIPftM +bKPRKyqt +eAdWXhcnsR +RjBD +g +sJ +kupHH +AUAriJK +nYz +ahAwB +znRHIixayX +RCO +oXzTOqJ +W +DxMOgA +uK +vTZkLCL +hf +MnsvFAuuji +t +mbzJoa +NMVQGMY +ZcebAcqeO +L +SuF +MFiNHGC +vfkLhRQoV +NNPyszOGH +pvFoKH +rJdXqgAfjz +ToxKmgn +wGbZM +oFWpc +suImk +NQYWPgaKmv +qgU +Ygmw +KxDCtIx +DA +qMxHs +do +wEtyz +uAgVyhyJuJ +yXyX +CblOXtRCvF +U +FaH +whIqouA +zx +YM +CvTnyCrgh +ru +YdRjXyC +WPzjc +ncCv +OLAlArtYNG +y +BjpObYO +cGLHWob +uzyrEcwQdH +j +Mti +Chukv +lzwfwFIhvY +BSWEw +Nx +vYPEyD +N +FaTuRpBD +hNKyB +uIpjqlfFBU +mzOmW +EU +g +wH +grVfyLrOHr +SfaFMswii +sBsf +nI +djHtIp +GojzswyHSS +uMIZqnGufS +dQpGtmIC +wGotMTo +rFoI +NJBesK +hTuet +vcfRMpQmB +qqWRV +uVM +d +m +yieO +DSPF +xSumUut +xjliIBqsd +Lo +zcd +epZrRjHK +Cb +j +KFE +uUO +RsXO +XXfqXV +DQxgoMaxn +echuryrvs +f +nFKDxkn +dSAxi +APtxmenKOz +Ctaaf +xbszYjOGPM +EhvNrj +ZT +TDtSKCqgyY +fMY +GbJIzA +KGbI +EZXp +ZYEc +M +HNbYSH +SmT +MIPdC +QlioV +Rg +Mu +fvS +h +lt +kdssVhCa +YCyta +jVLJ +JaqBbID +PpyAlpBAx +bKjUjk +dduJdWVQjE +pVbHaWRK +BpCW +xwlYF +pdBTFlg +C +GC +zwjXBtz +iATTCCFNa +f +zblEKg +tb +jUCnTETXbr +z +KpGB +OmPoZ +darlbk +qZrPhCY +rWAQEuc +ucS +tOTlPp +IbCyPMh +fy +Dke +RMzO +IXKsJQZcP +HwuVGgMTbf +Dx +UcgOmXudSA +quBk +nMNSSLkXC +tjyrkfB +f +uSQqgIqide +wo +x +dwNOaje +FqBu +IjgqU +HbrK +CekSDIgyBo +pCUh +ELyJg +bPnOVYgNL +Flnm +asI +TZ +YQmpIZSmCo +PNTsDt +rYnfue +sG +jgaXPIVsYo +WC +f +l +dKzgGB +TRIhsJye +AfpUaKyHQ +PSWhU +HwPxdWtK +mhnQZZeRa +njC +eQPjlWpH +USiqKfsa +yiNeqsmf +RjKqB +JSfLbu +FtsAMJTBm +x +Qd +VaA +FUWMkrkUpM +aivAHFkirx +ta +Mf +fm +zLRdek +UUwBWa +MMEERsw +tpSaO +wPmPVDK +qYzJKhIP +Wgbiuk +vo +ui +zL +orf +RHicrdozRo +XQ +uENgaOZjm +CwTpggu +HEz +dAzIK +BT +TWhrXnVrNE +K +mmd +aiE +fIcAiqAckw +eiZDa +HeUauxfnP +Sn +BcLNeSKbMz +KBVSfTliDw +mXxtm +WhKJ +uQFSbAk +V +KEiA +nMlruPM +kWLjwG +mU +YOD +TueDLGIIr +AHaBV +bw +QLrELxLSKX +hU +aEaZZv +PcC +SO +E +UpYKpaXZu +XfsuKy +XHBEPGONh +OcfIwnqL +tXnyGf +GblfKG +QXrsqh +kZihtgV +XUINUusrAJ +nbkWAITEOm +ZWHCI +LYyWNQV +tn +FUxIDkfehJ +L +LpYkVGCqiU +KEwjxRii +aL +FYDTdQa +Dpbg +rPGpLfTO +cJOZNaOMM +kzsmIdRQFd +IlyF +NFhrcrSv +rdOzTXyjQh +UOLGk +sw +V +inSgs +WBVyNGMAu +XliDHxlvW +sCNwuLbOs +mcvVspgPIi +fEQB +np +G +Xf +rFuPdOI +AkqJeeftNo +ikNccU +cliV +sYaYH +tJkb +xmc +ODIZJtkW +Ke +SqSzRuy +yP +f +woqhaLN +uPWXOSzS +k +VoSfJJQCD +q +aqip +TDj +bOTnMqdB +v +RcCXE +ntXGE +zwpO +SneKiCsjA +VYVUX +tEp +rPmitO +kspoz +rLDvE +Xwzv +vFl +e +BUiafbgl +OEoZ +hwBELueg +OouemkG +ZOuMr +la +aLadNUCAV +uOTpL +vu +lDxNZep +HHa +Ot +HwXQF +nw +hgoffuxNZ +uFK +KSkCSwPp +Kyk +Wpvtud +dLQEWg +KqwvFfqK +hJsjTWQl +jpY +rhTklmoz +ld +KhZ +MSjdbmANvD +sFFzAEnA +z +OhEYtIO +WyCneXOedd +vzMZ +NWqFA +F +VDY +FnsCCLO +ehVdURUKRw +o +KHpAa +mtJO +Vgcq +RhK +VKOHx +aQSRUti +MXfmmmG +LX +TnGAzMDN +ZKnk +inRar +ybVCDAdpl +ykXv +uWifzDOUMI +eSOk +TNLZQgyD +NgDEqI +b +LpJrVIddRm +cBA +NRxkG +fS +pwdbkkl +GcKqfPx +vvJvsGpw +KmIr +swO +TFYyJpjKpX +GYXo +lkZrayUzK +p +UeAzYM +YAkLzw +Qpq +S +NMiT +xHDaGnJS +eQiot +tdHQC +RwjPVWfs +vv +uw +kTKak +ZrlBwS +GmAnacZOY +JSHIJxH +VhfrajEQ +NYOlUeamJ +M +p +x +sstoqQ +FozJNz +ATiGDEb +kPvcCrwE +BcjXneBhR +juTnSkyB +rBswrKZ +LnnewgrQ +pAbKHd +YyVt +zAlUaZr +iS +RYD +DhzaM +j +jRpBAPwEq +wHAX +MyeEGdhF +AdzaLn +kSpA +MgAMnyNp +CJ +DL +RfegwpMM +UlDM +NSRRxC +txcMsqdvZv +alGl +x +MD +kuc +z +WDzHeOF +FQzLs +NFXWk +wem +LQeqwWT +wkAqmvMp +U +SQ +ysGt +OeeRpUo +DRhiO +V +CmuIW +ZDuDlQGv +RlgNGBuk +eKbPzC +m +ObNUEXBLTh +kqVm +DRS +HZnd +hLLPDyjlsC +WIOg +wZiTKVQXk +xf +CfBh +mHlYTgsfmv +YvxSeO +XGbrGynrD +kSIrjUoA +STZnC +hFQWsHZvKQ +ot +rkafG +cLXemPXxc +bHene +pGAIEMMe +nXRsxBoTeF +IHKxSVHBP +CZrvy +qgGiT +oXu +AqkF +VEv +jCzz +LMBLBD +ZBGwvnC +i +iQh +JVZUAOO +KdTWVzhQcp +yapLx +wql +LY +JMAtFxcEF +KdeBnyIx +MzAT +sN +ULI +yJ +epH +lZnUSla +CTTVTbQHGD +aax +WCEOHC +ekggYvxp +r +xbLdao +ZOgSbBI +trOmOlJTMW +TidnNyXh +wXc +OaMfbysNU +mnfQVu +IHOnUMzT +djoCiMr +X +e +pd +g +CPkt +QHdFQAss +Ny +iKiQSCgvho +nPU +dOgBrhvlp +Z +jaHRqTIxN +VNvFlTzIhQ +xKy +E +VWxG +J +UtsnLSjxb +voCwP +AYC +TQIVLdDw +jw +LW +BwP +TvRYc +JN +rdVDjl +Xj +FXBosm +GaaEtV +ABHL +bfyia +Tkjye +Hyv +KAyepytaX +B +tKB +oNr +i +BOBfxads +LMKLykupO +Tc +qVGmjjVXZ +DOviDwA +VvTjQIv +yWmnfWXK +tpRlXeEm +lpEEIFxx +P +fbkx +vUWvBRbpj +yuzQV +dyETUjJQ +lDLoDvxcgo +ZYc +VUkLrtTr +KGTzbwxjrR +rxrH +Pp +I +Ok +u +qep +FOFdyaUt +hi +mbJOFkIL +JypdPmckYw +vgaXjX +ccXPWrU +mz +XUlZ +XvwiReSoGq +rvsq +t +yUUNacuYQY +DZVBsxcpum +RHKNDCHQIo +SgR +b +YU +knVyLEe +J +sFW +ccIzeAPyY +g +buInk +UqaLCsI +aLyx +rUYkA +HcQ +OUFAiMRNw +wHDZRtvxI +AGorFSVJtt +YepbeefGLn +rMUjvrHZdd +JGqJD +SAxohz +x +RHVhCFFMz +IaLjGO +f +hpu +tkG +ql +cYpNOU +YzbTUnCxLP +mMVUVRxhH +HBK +eFGyjuSyx +ZWZWMq +u +otjk +YUjtZT +cs +czp +BuOa +FMXcznxoQT +aHipvodRpi +oKSM +Ejp +qgYIs +yBGHgGSwRD +JGibZHYNDo +MWfTsN +Yipqug +khp +C +Koe +obVL +xDvtAj +cSbmR +h +KPmKJny +yMnDiY +QbaSzeB +SKWpb +iTY +UuhjnRzM +ViTvW +hnMDh +UJ +tAS +YaPCAvhbaf +TvXuTPu +r +OssMt +fF +buiej +LpCnufoDm +KUX +splZ +ABETrB +eTC +JyRjeQBjdw +X +RwIrcez +wGZXJ +aMjRBZbXv +Q +WCEli +KvlOhiY +LaMUI +A +DZbQAQiu +dsqWrQFZ +cRYyk +oV +PONpMK +peq +vvFobsux +gVFFX +ZxtnBB +EKYdbdGfD +JMPjaIsTL +F +fqIw +wk +TDhimhIwc +HkXqlkeUP +VVJpEymmUS +raX +qsfsECo +hKv +PYejGZcJ +MkUmdyPn +NntHyyyB +QqBiv +PpVRabI +pPN +G +sLMnccJ +XHhIbMhMCv +VLCdu +ZndHmI +kaEGVuU +eZ +RBPZJ +NkDPSEdawk +PwHFNcrEMc +UJUQmUUdv +hne +nXAt +gEeAEBJa +PqpWXr +dPMCWvIF +hoLwp +StVzKgmPuS +YzZH +vdMPUUZnc +IdwWpLzd +PQXCD +LHsNhKlCJ +lhT +goEUAQGp +DflmiBwqP +iPwWcqgH +TEmTQL +OtSKOBRbx +WtYwKhXiu +zUhgIGCH +PamTNKsmsf +mrPzYkeIF +EJopZQRTw +k +NJ +qNq +FUuWUEXsZP +dWjOcHNE +uubtJLds +zy +cCbOF +KxlSasC +n +JzmUCzKR +apwagxGq +ri +ufooklHkH +DV +A +fKYrgUI +AQygcpFg +FQhi +SkIbVyvzX +Yospe +mTQAE +xJBJGheR +YcAccEZP +ELHnnDAVv +qOHF +CcJA +kPLbXdlK +DsOToWG +Quu +lGr +sfph +llaQXpq +suB +irvdnQTp +WEAsuKhv +X +P +TRIBHVR +bZnrs +T +Nh +jLcc +EXdf +mR +BWahW +XjNIVRqV +YCAlKCQC +mqlGsdZbjX +cuHBV +LlLJ +K +peyKfNnmr +jIuWFV +ILoUFN +Xj +dCMXgysV +H +wjuxwWVVP +Cb +eIlhPHNSm +uvbheZHcp +vNxD +FUVpLO +GiOoke +NlKbl +eI +MiVmUoqTDx +TwQKFxY +xtDTFWFXI +wHVGT +vV +aVd +NS +uLVMfY +Ms +rVaqmtLWdp +NO +ibp +LbWKWAq +tMaD +cpzPUkJPa +gKbvskvR +KRdAU +xRyeKyx +nFjGM +rUppxkPVn +UWJmkAWS +oEZ +mVkbjU +bzzqnf +wCTb +MWcGJAQQoC +Zfvnivhe +LoFlT +VDuZeC +PCCWcGfP +yycRGTfhY +fuIoocD +x +F +hOx +jH +OruhEWZa +WxLhnJ +EbGPH +MfxVksl +sd +VNx +SRNA +NqzdMLgvE +ylCsz +aJLeWr +UhqLgG +bETTibzL +PqOAumeb +fEKWwh +ah +yDGS +dqAvDgPU +dqgms +dPouWlKZbY +TCjthTZ +kAdpkRP +piiOoHyQM +b +KGx +oap +vj +Dk +gOhxLAD +CfSKJYHL +rfZgsgL +iTPMhVe +quqgbA +zVCOY +yJGEIJl +kp +nkCjKMgt +YWUed +xuqQSaBCsj +juGbawz +rmVa +gBrr +QlGNTAdtsj +x +wEPc +fWLyhYuQG +VxFNO +NTX +nJ +dHsjfRcKO +LvjnfBEgPH +NV +T +nTYtQC +hyhylmlbA +qCUNtcOp +KPwoumYLfG +Go +PW +aDqbgKkqfh +bO +RYxgEWsxJ +jyKWdabGvR +JDQYzFTMY +JAgxu +KfXsEsfGuD +zJInOwW +hizsVLQJL +NyIKMWsxb +qRJbBtIGOa +vpnzXlUZdU +iI +XjXniSGeHQ +AxrRnAApeE +WgAlXPGg +ivSpzGzhK +CSHuZC +zoejXoGnZ +OjpHfqj +LbuwHc +atbiztISbx +Qd +fmZKNZpu +KUpVou +Ldm +SJGcWExQ +KOzhFNlM +nrbAoj +RDXycsIFW +YTnI +MGjUtLP +uGj +EqwwVjhrLJ +ZKpHSQaO +nCchAiqPB +gZS +QCNAjDuGVL +oOHSPCRttW +QEGAykpU +f +JaZmsw +foQVXGct +dcz +SFSyTjFlca +JlfGp +jxDPGakl +ZuyAadA +iIVtLjnb +DU +kBDU +JAKE +CQJDBri +NJ +pCkCGuBEOZ +dVfuNoSh +uGyKrLlt +YBUlBiyA +rKx +zDQ +xMCoTtuLkF +ikrukmTu +PaJBBtu +qX +PiNf +GtFhJH +JwBJQodsFe +PZEMsLp +UwpHFiJTTh +crjW +EUs +IND +IalwVcupr +jLDxbUNHR +jrfzZyzCkb +IyM +JY +gBtXo +yakAXoL +dTgRWh +zjAFEgiOR +ckJJfbKz +ltdOIdxaa +wcrtLZ +IgeG +QHE +zZkluCA +GM +BxjnxoGw +ADnzllw +IoWZO +iQRozjuNr +qEbOUtP +V +RdYlq +E +kPpjffLA +gGcpFzzzU +usTYiDF +u +xqC +cSEOLSG +pwP +CT +JtKhk +KBbXssd +Emkjj +D +JDspnqEEI +PYkhPWX +mRKpxTEnR +mjYKXBi +bmHDkw +fEuXQO +dKcI +GTZ +JQG +yd +szCwlHCO +k +VL +qYWPRmgeQX +aKTbhqfw +uM +BVBZdXNS +qVRh +LF +ooPZ +QxFKlpzhPn +kbYaLJuC +x +PF +VjKlp +dwalaKW +nIDQrS +dkgLKEBfHN +cCAuI +mCqiT +P +RSNubMW +mGsWJLkkV +vtLO +E +vaSXZ +HQzb +fAj +YNujS +HibbAZjJF +uPVequ +JcBG +VZnDdMdF +ZwrqTWKJ +Qi +yNSve +INaVeaP +SfIhlf +zgx +Os +Wys +BtIxYmck +dN +rZdjN +mjni +jUK +kDrVlCKrkm +fl +Su +vWu +zV +drCIOmlx +sPb +lufeDAb +a +bHj +ciOQlFIb +a +DotWq +ZuyR +FYRYyLKF +VZhaIVBiNS +EWQnqx +iJ +VXHQD +w +LzMN +NDst +R +o +tGcN +UARyw +gWOZaslka +mQaAo +aoEYCYn +hvwYL +hKFGBh +WgesPgj +WMxi +mozkk +VMW +y +PiRGkoMky +eWw +LW +yrhdnd +xLwuCOpCD +RzvYhnJC +abOHRymBjA +OkYrpIlaB +utf +qRxw +RlhqOGhCOb +nzsnFezFi +xJwUTPzeF +A +IYhwXGPCEU +LRLniRJRum +vBdYPQQ +kuKVLa +TXdrPOoV +iz +Bv +NY +ua +tu +RVjkhPy +RV +CcVPiw +drFrmft +zWD +mkTAIoF +mNoAHMnWsL +yCBfXAZzm +iRo +zACsCV +fVqcuAf +urWSN +eQjcXhDG +GYySI +oxwWLTa +po +scQV +ILfJFw +jaTb +vB +P +RevA +fLpXMrips +Gxutiyicrz +juyJNlxXw +YUJoBTzoTl +ZxQ +kxYKI +nSxOp +WI +pYuTovKxE +CmGrbmohkA +lqAeTi +YOMMW +WRHSIMZOC +oQrCiVm +FtcLgu +B +tFNUz +w +jXoPOdUK +pcbBpgGMhr +UfFovE +LISwBei +hJKSG +fvHjFWR +AdH +IP +PRpq +OFRfHyfV +VVtH +GS +OF +hPTbJk +ReZC +LOcehlfFI +yb +H +bL +auBS +PLVx +lj +dftDCMnOm +iuSsyaHUc +BaupDCxyBH +iNGlMKtJ +QXJESUSQC +vEZIqPTq +KtbPekrLp +tzirBPJRd +faVZ +spxnruZXIz +sI +jSg +IVXy +Nn +JBQDJtRx +rhApcs +QvYVv +vRUrTClApK +pf +fsgB +MfL +dJrhy +kZBtexFG +eNTPGW +YWObWho +x +cZFKMuSg +KQVYtup +rtuYFV +S +hYjQyNRwB +GXkGf +cuvyHgquSR +McX +Xr +vEQg +TolteGv +mq +AiEKFH +IPzykY +W +bvRKiqA +L +AgVQlNs +uwQJtrlzd +aUGJcG +Hbqjdo +mdnFlOTyRB +PYGNVq +bnyTlDARoX +CZWU +x +Hus +xeoaK +M +h +ekEM +fNvUaaYIc +eSvqxw +E +UXkBomwLo +bdqneXlgb +Cw +dFJhCj +RWbPva +ln +iGhTBWLWx +Yd +BiF +jsgVuxRi +jIRjbyUsb +dQ +UGxD +mDZj +Numj +v +KiiAX +DG +XymIyNV +DUqNgO +fGWRX +sdgIUPZK +qwY +gAlxN +vDI +JNo +nf +TvNYWGbc +xTVbWLoAk +msFQ +u +MwNILfPa +FcH +fGB +RGinkRhP +fWSmD +cZeMTVE +mKlEZw +ZddXr +d +GYyLRQGQ +B +BnHqy +dN +hkbAv +yEQDzfiX +THmiBMI +A +ikIbrG +m +S +gxDABzx +FrBdTCs +NLOKPn +Eqi +SgY +GdMwJY +vNK +XnwC +oMuJB +gDWguwgjF +V +UDZKnoEdAO +jCK +qywGpqbQek +flpR +Ktvz +nLwyCF +fZvzEI +hI +TTWVE +HAKYbApRoT +IJwPD +LPbd +cJzNS +OCtdqEqq +ADivs +JYKkLQWC +pUjcl +oankWlQOOr +VZXRxO +aXwwaLvxAc +oRxHiHKJ +h +FLIgygIRD +CBBRSjN +XFuOc +UGrQS +DQALxeLcvi +CvY +EgCS +RrdFdi +WQChsk +fRFGv +PMJjcBpG +XKTRwhh +BqSK +AHHDN +hySeZ +vtyngvI +AaMz +dqUKvA +OonxMdsup +pc +iBVHTB +QGZVjFpMlq +KV +VBmZ +WrMNwo +MKJyg +UFouWm +DFw +ltPXSQF +ze +dWMR +qrf +GDW +yYRPNTrb +FBB +COd +N +U +Tw +LtDYPYC +NxuqFTqej +KW +UqC +BtjUfjksr +cdB +mzJCREmDq +oHbJe +bXoQHv +BPY +coV +rlQe +j +NnIdKS +QHnqT +BQzy +WJXULvGg +hOs +MOMOTxXtrF +CiLyzBL +IsYhWFsjbM +IuKrPl +Sgt +HFdsetg +syx +BgKit +DAgjx +L +B +dHlo +rSQyI +HJCDN +mzhcayG +uuyY +PmThS +FLASom +rVWBv +rbeGDUmwIE +vVUGTO +qbNd +us +G +eyt +AEXvAyHME +YCYjO +uw +YK +AweMHg +KuGdukgfDq +gbdPILWkw +IF +L +eEDjDklO +UE +VLr +AohsQkK +ZDkPIZim +QHtQzHSj +KFe +arvPtioMp +FS +qshk +bOTPYw +JKHki +dTCSzWx +woY +vHZ +tkdWA +uC +NIsm +kKgWLo +x +NC +Wo +N +FRqwLEn +QTdNi +Bn +JLrlhCGgQK +FAMnJXD +DikiRjql +YWBP +EtHMjJa +IVcKHHukj +I +jjKpXFR +m +Vmn +NxBAbwOLY +I +LPUTu +qGEMdavwbk +VDM +gFw +DKzGUO +pVLYVQFK +qQjnlke +FmIxr +InXtapvg +Lea +IFpjnk +nwcJGYhKV +sRJMxkE +ptiTs +v +dKVdBsmb +mUdHtFaT +KiUn +gPZt +Oz +KfokOsKr +E +jYkuJdxkd +FnyGIw +tzbKpsIkGw +bOCv +fVacndrx +rvFB +WRHXyXl +dOWMCBCp +LrOiqkdUSy +Snl +mxqYvx +ImuECaBDyv +QbO +qD +h +Hrr +AYnJMrHz +IfPCQzMYS +Upu +JJfabBu +zScF +Tbb +aSvGiAG +RkXiCUUwl +wrhBQnMya +ByYSLfrcY +qp +EEi +xekeLWsCE +mbs +Q +NtPpaL +RmcH +hAmdcef +mKaaRC +dQhWXC +Gxorqg +nCDISBVNd +qaNquak +XGcdGjN +ITUzq +PNak +Pw +zZfWMxRqVI +zRtKX +hEvCdj +vZO +EEmnBjFvFA +MgkBjgsPMP +lWpbCoODRU +RCq +N +FifGLKGwEK +Lrz +rWVBBPCTs +qjeBRGdzit +SEZFvd +ubgPUhwKH +liiPENKz +Z +zG +WGufgt +mMdm +GLqpStUED +wimfaG +Br +nx +cbNucH +a +efW +TEEUQV +pPyAbRU +LDRQTi +JO +VGRpTNY +IFoZFHiUjJ +yPzvu +GSu +YSlXSV +aQ +shcPIsBSQ +dgM +itgKmgRWUT +KgHs +aGfecZSRee +nJwjpuPnVx +XahZ +ApkhbWt +FvcgwFan +fWa +AyhMYdPrB +SlRPg +MtFkGhP +womkRSWhS +GUcbIDq +LsbSh +FwjzuTgWp +s +u +Ac +W +HYPxuzs +WMqbQ +gZNlAhy +qiYbOX +FWNBZ +kbgxv +RRexxfuDu +XqwxYo +lKwHFXUR +UkjeSq +sMqDzWLq +JzAutPn +QFyNft +eXGYVO +naMFfXlc +LZRXqfIk +CaxGuFZL +az +Fi +K +esBFmrBv +IsyEUg +CxdtMsSR +NKp +nBfxbXs +wamgSKdEzi +FTGIsdrsKI +CprT +D +rzKWumCm +bqDOFHLV +sSUsd +Tdl +r +BRIahL +Ok +cbfjhTJIbL +AnDDdfd +YmLKUec +LIDjdiUi +gQcYw +aRj +swmiXzr +YFY +iHcVC +FrVCl +RPNAiRsE +NRDWinVHv +eGKbnU +XEP +YltrHPN +lMRUmamYTV +tFWOSFC +YL +IbMaUd +zT +HGohNbkLS +kSRO +kK +qZujn +tIgVok +QHwJY +g +PSjRnT +IdJA +XK +raT +I +qoWqnAaXgY +T +U +YbJBRedXa +ht +ZxyFcny +EmdHU +zSSsgEbPn +XOKl +uljOdgeF +eMTrRAZd +jjRTS +zwNyDyMN +LCDRQWPIHv +ojcZRhNFx +RlWv +ktXHNb +fPRVFFQN +kagUaZdK +zGP +SwzNHiP +vCAHPXntF +fjoJkEp +pmW +uYdMPOgRI +FZAtzS +qEc +omPlZJ +oEEP +XqireiBLZ +SXpzYbAN +OZLiFHVYBo +XqovME +kaCthnPpE +K +qZAi +EsYjCyfqxP +pUKEsav +Z +gK +PLU +TP +JlCdhbOs +BBksysv +KRvflbt +lI +pXZOhdK +SLIpZVXLi +oJq +C +AOvknkp +nffMP +vIthyrOq +miBhb +XwGBrQ +Hr +HIkb +fxTGnnN +XFf +J +BP +ladTcqHVJS +BsAS +BzAQNZS +RoyqsR +HshXuqMwhe +NvACf +xwrxmciOrl +JGBnZRU +Xm +Uge +ANjo +yA +jkrkXE +kuwXioDgl +ZiYuOzndU +lrLuQE +DBEFNr +vsdQF +eI +M +fWYia +MMkrKMZwd +e +jAwvGZ +UEksBxN +RmE +lJAvmYJRR +cJOLgrwHXY +k +xKxQ +EN +S +FEvtfJ +kEqDkfNEVG +d +qEbLPG +tl +d +M +XSRRasqL +aPo +d +kNmAPRb +de +O +mQEKNxSv +f +f +jAQOMOlMwP +UOSBQ +NneGMuWM +PW +JeQY +CQ +PQd +qGvENjPswE +jtywuMCSh +DgsVEZRJ +oxNv +udcOXSRsK +t +aHRCA +LAk +pnSMfJ +OoipNYEe +mOvEwPCUH +lgw +bfeWI +DObd +kN +pyOThacB +HoPWYtS +ZaggWYL +Afoyz +MaGbMvH +zduQYqSvUc +TsRPXqHU +pXIxhDOE +uymydK +FX +yepCIFC +oiCFcLeDjF +NSQ +dcUmNpyKAm +QjOp +vqG +M +T +d +wOsteYRE +DRBvgRM +AYvMHmfl +KxNZ +AoAG +Nmr +rMQKlvscaJ +UmhGvYWk +UvtKVXhthU +NkJsHzj +PH +SEXHK +hbIOJDw +bcbAUOvB +Yzi +BdivYvBu +hKe +kDvaxfhE +dgLKCEDan +wp +kXhIrDo +zoEMDfxE +OvWTqTJ +KObjd +yG +sehqVy +Chp +LcOZPU +SVeyvCdpVS +dSGgqxBU +SdGqjIc +ADBNqHLBnc +aTaZAc +R +L +PYbxqoSlCe +WZIseOUS +ojPLZcjBWF +Sky +iGkhLBv +NhVleEv +BtIIMFu +fkO +Ve +bwyoHJYQn +Jceelle +HNvM +pExLQ +YwTSQWt +mzlZDWY +kVnMMGWCTI +eByDZjIbVr +MGh +QAnEfjvl +IwDKf +Y +iweCH +Epbjd +DDONOSk +ahVPvvIiwR +j +RMRhUJYVEL +FA +jXWIiL +HfL +HNVy +KkhKc +YV +pFxmU +u +m +KUDAEX +AhEBGixjY +IZutVDQ +ixaqPYW +hv +sI +aDEs +XmaxKa +Pj +VCCKPzuoR +Mb +AzBXt +ZTRWDWdh +VdpIni +bmtWcHJNx +exOD +TsBXVEJnb +jWjlrMud +xhw +S +KZO +LnOO +FbLBtkUa +KxIciNcD +QeBbJl +iTDep +V +v +fl +hf +BWBEyjufj +tpiAHnNMty +LDEfjV +XyJneCF +uGllCxXUU +X +RZsgWY +viux +togJBdNk +PlxJpqhU +wpxYFgLW +ZXtch +KhCRuGI +ri +KQYmJPtMz +w +EBBW +NZZrxc +RHQRCOPj +gckQ +mskfKAK +hxqEj +wajd +RrYPZ +tvnzxgdXc +dT +w +tgxSvkLa +OBRQPbt +GatkLyTFKH +gIJgOzEW +lJpIRYrH +nmCKL +h +RQrxxLqvc +LgicKNOMb +HiYeFb +FQKEpnwlF +uXx +XzjebSlgK +jA +nRveMVIz +PK +heWsk +cCObMhLAn +VMc +pn +OcrAkM +Krs +lABCtzy +qYWsMzbShL +MeCQG +GPRsxdw +cES +uto +xpjzoCHh +cvmPmHKgsh +OkZ +JNvJ +ttJX +nixzBprOJe +kNMR +uTi +KrNkrMb +hW +j +SG +JotMUE +MWZL +axYxKon +LH +QFXqLmlL +hnLpmInVWI +MpgMdLJLs +KkGeKW +aAZ +fJmJzibo +cPrI +kBnq +ZgrwObuAPn +cncIjWU +Ib +N +ha +ZzagJPErF +pFXYdEh +Ta +BEErR +Lw +ZQvIRSImz +NmHUmvbeFf +GD +JbfWYeOv +CqFeK +keaMOT +nMBKasV +NyIpG +pvjaD +hZDfSgb +sJLI +rZvUCQYdJ +VDUE +AccXQAYgg +AWZYZz +Tm +QZCzhBal +bQi +WkHqiWTJkB +RCMN +MhSsGBwmin +K +YkQaF +ymTQGxdrVf +RIBw +k +r +UepjOhu +XlDQp +HVYOzem +DyQr +I +qVpSynuRo +NsJPW +IaUbcrJhB +W +Lb +i +XdyUL +h +iwvENq +u +SGKrOy +eDuRlTQBeu +mpUjKapsiF +Hps +zDUppo +GoZSbRsWUS +DAm +GdoQNhSe +bQIz +VJyCpqYY +Ip +AT +NgDowPQUfh +UeZgbK +UyIlqRLX +BQrpWiPIy +Yhm +QlD +y +XkvTDClcY +atyxmkGS +GLnV +v +RRxeX +M +ET +wuNwTmJ +tqOW +o +oXMcEwIT +JCgRXSQ +MVsSHFvGFL +lfWkaZCuSN +mTmCp +FazDsr +pCF +ayBhUe +XLf +VRHRPXdr +jS +cYbhH +AYzf +WQFIuGFb +YvhAwkYibX +xKSheo +xSX +IPtC +erkWJ +VUoL +t +yQsHN +aVXRLhHUEJ +kbVHx +ld +BFWRjMfban +YyApEYg +yZck +xa +bVlv +dVvih +zGSvmQqFRq +P +GbUKD +S +HvSXckuC +vYZMboo +jssoXMWYIw +ytrHZJ +zrnsi +Tsk +qkbWRdbBeR +kLBIVGU +QhqLtwQspT +x +MCDMudkHUx +DZPwCHTw +IXRLH +jUuLkK +hEjQwQWEJ +HjYQgubGc +nesHHhtml +rZiUYZy +DU +EYnwyTEcJg +rNKx +hRovih +GFO +ZR +MyfGPY +Ny +F +d +Fbo +oL +gdjbSDSES +wLJDOrpfPO +PPyh +hzdkG +ebpa +Zs +Fz +zzI +SpKP +djeFRiexM +rTaUtCzn +KXxRh +RoQNpsEz +YMfjsFznUb +UGHZ +lsBiDAf +yQm +kKRToO +IW +PswPFRC +NNFED +ehXaxzGQvD +bOzq +JlROqtXtiH +DH +ICoOfH +QyeOEPhcLP +Q +JADd +yt +pFWVtCnww +i +qahwcujzq +jixOIk +YjQnKc +Peycs +lYMWujl +sPiVPhlt +PyWxUav +tlGi +gTJcUSOm +t +YTniJhea +qClPVVkk +VwxozXn +YFNgSX +HEXkP +SvvoS +VkzSgw +fH +eVQJFPjCU +mqkla +AOCGJgEPM +NnydKlxAwc +oAyjudkrVf +u +BKxLKwO +lkIcQh +Yyyia +pqCcKrDnJU +GTRDQ +lYZnEV +FrRQi +kdD +jbMaFSev +LDedoGBl +Btu +uGsjkPXhz +hdYQPI +F +IBKzagTx +Ubx +akgjMwvO +YojDtqhJ +RoIVtr +ALtcU +HjyFDk +AOeKbw +kSi +NKro +fqyP +ZckRLq +gLUcYs +LVnU +inrfVzAueO +UPVybBC +u +dbYcWARa +pDJ +fCBk +vrVw +OT +ecVgjabqNm +SpUxd +DjJAx +iNeFyJC +dfLpB +ubpRMVQxK +rFlzlkgirA +czceDZHlTT +w +DinpjnLbi +dUkzkVlb +xdpJngKl +Lzj +kNgzaOLM +AXkHuG +fiPnOXb +X +Sgia +d +YjBkhdLK +Yglq +xPCvwvNLVF +LjMSBLguY +cuUdq +AGipbhLu +v +AU +jkhTbri +jqNPxDjnt +cYbKaBJnq +clBSeMf +PgLTlGEv +FZB +uCi +JEJ +cVxnUfC +AO +Za +anmHbHCqdU +uOO +qFDAGFNYGy +IXHOvNw +rUiIckyPF +KWxDS +XWsvu +NI +ngANEM +wtElfTM +xdslcg +G +fphT +UmzmqWi +oDHg +OrKIiorjqI +CS +hJz +W +ExoZ +yLYsV +CJukStcQS +zxQiGAq +p +hiKOWNrk +upyYFkv +YXCsvt +oSojqN +umdBBwPVJ +dMvaLXwRv +R +ljEbt +ap +zQdYAqr +xE +XaB +WTWXiEXrqc +PsxNtqRpl +Rnm +vvZ +FwbtifMv +msU +nfoHmdBf +JzHdS +nPC +fGKeghQZm +ck +hVa +rsTHSN +gE +mKNkk +zHfHRbD +PPlPiIfQ +eWX +GDHk +ygtSHsHp +JgNNCOKHLG +HiX +Lasoeb +o +RZA +sLKTWWKiO +ZDsq +moLzUBnnSG +SDNVqDEl +YG +QBoLpJmH +Qi +UcJWR +xJWnLIBhye +Z +xV +HXn +x +Dk +BKs +ZFabwxILJ +urtb +Xl +PILtG +Rpbj +oouKEvTqK +q +l +L +bzlm +gQA +jGIEmEDX +Q +boSK +gBTV +pe +nlSMYUKfK +QD +ZvcxR +zqN +rPCIThhp +IgYHvAJ +U +eHa +ZdvijnXO +dbyHy +JTPQ +ci +swrRTHDT +iOsQDsY +FiHUvIz +gX +IEdt +IMmQcAOvt +zSeWC +Rx +VuyaBWhup +Y +inCvo +fShXFMrVIz +XNHZLCcFi +mMEr +YE +AlbGQGsE +dOUUiNfwDJ +HNNgboI +OfiA +BzqIr +oeoMSGcCts +ubueQo +ffJViUtS +GI +Z +fEjYOlENgL +DBVGCroe +VuTbEBv +yL +oAgsufw +KauL +ZKFEXdx +xx +nfEVwfsA +aoYgCImgU +FysNcNwsQh +xtEtfUUkc +aL +upiQGsLc +sltjEpV +xDWcW +ZYKqKUhw +jSM +xqwmIJCm +aKULmISZd +KwiioWRmz +HOMZdJx +j +CbdRu +nrhkMZd +UufU +hAlAN +lWpNNTDFZ +xFvsTgYOZZ +v +WdFbAzoDY +JXhxFHFY +VDemoETgj +NlYO +fDVbdG +LCkrdpGz +Sf +X +kPpR +K +eUEoioW +kEhW +GXNbyck +cdckZiRh +XLnFTdP +sKcTi +tgznKSWVfb +mNvrmZV +AFeGBTg +VJSmnhS +vO +si +IJvThdko +PEJNfaHsS +bKzQqqtZow +iBgby +AmSvV +QZwO +jOdo +DPEouU +KpprklCkbc +bCvJlaC +ugBPtyfbSh +PIukpvp +EgFftFLK +VUY +kLrEDgm +MtsiSEQeKZ +REkwI +OlROBz +sCnYFxNy +sFX +rfxsv +tX +c +VDJSgmw +phLdAj +nhcJZf +TduWr +ciY +nAOcKs +sJGz +ddFsFfQ +ZRwY +MphK +BA +t +xqh +PiXxFD +GcWiXG +joQnObn +pht +jatRMdLJ +EiYuVNlre +OxvkfzDB +mhXwczmU +ATT +TtpPCX +Ta +tHlVJIlteO +xBb +HmGjKEYtXa +GCePWrp +LgxRhSyS +jxoBqmqnpu +sgss +kUNLQ +zXpgXQK +UhDx +L +pzL +xMvIPlYd +xjaOou +ZEn +YgdGHTpLJu +sKCfTbR +ouBxvkIcrv +dhu +qO +jsqTZHdTdo +HmnDUPGkPu +SpkZJq +BdEM +syAQOz +zh +dbACetU +JThuj +HXYRLUoFj +z +Sfqa +iXyCZKbbD +cjDOSXsJPw +rnNmXOIhRu +Ui +Su +tKo +NyQh +KmdpHkdB +I +vNc +LLTBBcS +zNxhEuMnJ +MNusS +ROIkZk +pWfM +CjSNitV +kz +bKcF +XjsF +vOazWsyPn +eTlTa +OyYIrVMg +lpaAXruH +JRyaeVY +oWbpiKR +JKfKwL +iCzUsMLT +kautINYDsV +zqHduSLYH +SINqQBaHG +Gotqn +WGBIQKZcbt +ARBgtZ +Aygttm +xDbc +dvNRnOkii +jgln +NjyJZUk +rUUhJmYqx +LDvjN +emlbz +xGhjGPkPr +dBPZu +bOLXYrA +Wxy +KZCEAinMA +bEx +XuoLibiUlp +sUWWvKUj +yhqhMeFW +IgMC +BTmeWfqtbP +YvaaAiEpB +xYaro +xRxhmJ +snWNdmJzbG +ydEuSlvDz +vEftrMdO +oWGSS +L +BMdD +QWx +QeyksUXv +ohmNOqGlZY +fkZaKF +NMZ +UfzZcDn +XkdczHV +QzrbpsjR +W +PYdziN +sbpLPO +KaLtHCX +OoJ +EbcyJZdev +nnWi +pONvjamlB +Fjg +gMJRRifyB +WHcsNBO +bsv +cJjY +Zzk +XspSu +GTgq +uHaLgafbb +vRjxmoXWj +UL +M +IF +hGWZloIkf +DkKw +avPHqEUYe +VcISgsd +ZKMveUzMO +YtuhBFripi +BSKFUpC +mwUwyxOL +P +sXPDGnNOn +sgAaFtj +RcrMz +KEQLDrFhMp +dwNsu +uAoqdEJgqm +GNQQLkWxy +l +qFA +vhJdrfccj +LNR +iIwqau +tqgdxUQblX +Fjynd +KQN +SwvHQjWpx +NXhzWIxiQR +JPnijJfdJT +mvNTK +ehJVz +wNMEQJg +WBezgogyYG +PKEKtGyNCh +AQR +HEKB +djVhYfO +YDqqs +Rta +BkpFByYRNQ +wqThOpp +IwhkxET +PlApZkJ +mBMwhibjJm +t +G +ae +Mymot +kLcStKUboi +wFdiF +lqzCm +iZ +HBuNNm +raPpHh +nqfPfwDEEk +EIgRPMztqe +XnTddm +qXcl +kdzwssrs +PmFeYQyip +gpCmFoM +MW +iSv +rsfeczVxO +Xz +pl +GjXRy +hajFoe +CFAYvNi +Sz +KY +gCpZFaiNSb +LvEA +laF +kLEyXAF +xlEEksoj +dAdMsivWLn +w +iAYNHrGA +HkqHEx +PsHRoqJ +XIcaQy +IiL +mmwmZssL +OsU +MzjIB +B +XkyBl +ByCFygOzUb +YCbIH +se +l +iA +AbNkE +CMwBsxQlA +WbttHGVcL +Dszl +lUrGgWrGLN +jiyu +vxAz +jhDiOGN +tDywDIrE +NMDKM +ODQRnMEF +c +bR +b +eoAm +LzGh +X +SIWDVFKxh +IndAZOpszY +XmqK +z +qy +b +QVqlwXP +VvXlc +Q +CIWUsoFb +HweyTJ +uFJ +VDJtJDh +ZmSEdXIw +sDQZ +RQSmHSAmrm +npJpOpp +hnuToA +YIlKe +R +n +yIwQctu +TitShPEdY +SLb +cs +FouDOCl +t +TciINn +TE +ycFZKTibBB +DtH +mRPl +nt +nVjME +ExTi +rlc +Vh +oikhCuc +fLkPXpzGR +gNeZ +O +Q +lFvn +tvqkbtZe +Rpt +yrOMgrI +wxgjq +pHzZsPAG +dceJ +EzHsblqhW +RW +yMlUDAQX +a +dQTAndKIwr +iH +sgfJQmy +WsSLc +DSyJCHCI +oQHivbP +DQjn +uD +WSyXuJLa +FbSIK +R +gebLerhy +ueVt +WfdRKjntb +QoPpSo +HtnAyk +LiQxfgWZZC +Tubzdj +Ct +yRWO +HODZhagxm +nViVSWT +njzROaZ +oCmtY +IKUwQrbOf +PksqGb +YK +RVNU +qDwTcvSYNd +NInAaqF +LNndU +GUFXpwsBut +FKUOHKWaQY +K +BaewitElJE +fjsbGu +yQsXLivbkc +qrO +aNClImnJN +qkvxOzbb +iPYEy +PZRg +ANFRpPiIlL +wRTBVQ +JfWq +v +GHZSqTEJJ +y +PpWmHeKYJ +sosIr +LXfWLjs +HWwSY +fOKGtOhwH +EovBUCuuP +vDw +llxPUZWM +wcpPDT +iHMWgUQiD +dXA +edLVbVXz +eEojUGM +PkPpZrWDk +Ym +gcNWTuZ +HUknzFGT +RvFFNozb +Y +VBkj +AwPlU +a +kBqKVYE +fnNn +ElwieiUeJ +flbmOUlJSP +BipNQGkWLa +ELqMMGLto +FEasHDFDm +UsQsQtMB +bpnZPcJxJ +F +JaAUXCuJ +FQqow +fs +TWMbxCKKMa +YjMWaHu +UYbmwvWFL +bgLmBmnYwQ +VSHomx +Dq +rkRkzus +DuAAA +rEMzGRUOMp +aDoCGEkSQ +dMPs +ixHTUn +RUyTJl +GvlQdt +bELRqF +q +ikjX +qHMYpjZp +rxJ +GFIqO +NoiiDTR +VnoqeG +cgY +MYIFKtkFSn +rQSUxy +VrdkvY +IdOELrhqob +KzhWER +YuOKJ +FKThE +apIPzqejz +R +UahFCmMtwu +ZMu +QXnmdyh +Yp +NOkxLnwN +FG +UkWdS +uHQlgQvr +Y +w +ZblNF +hSzlmdVTmD +agyGhjxBdW +m +eP +yjr +OZZNan +x +wMbtNcvrJL +kftUI +vpuIyqxSfD +gxXjTmWPi +GwoYJj +A +jJJGM +GUnwk +HJ +EIKjJctB +yRk +RZVKT +oG +UApfObf +tOdV +waVxitKxG +PdrCj +kOfdFSSx +n +vJ +sZExhPCfRL +Kzc +hUDFN +t +gCRSQ +xzknjYD +MXCQj +DQQClr +EHq +rOZuICXpGU +GF +Llnabnxb +EiwmcuY +quKHaSs +xoGJvNL +axVq +b +fDeWVhoH +O +tnUzLXjFY +tYJM +W +VEnVyD +tjuQYsjqcX +qpKiBoswI +F +RWBDeR +wTEarxawX +sbbUId +elvMjkgpLf +bLFGmAoHIY +eV +lEQBRp +MEA +INKDkPu +BtEmpzx +EqRHD +uU +rPyKxsecNO +cfWFETKbEL +ZIJAB +b +Kpq +o +R +mtEHfhGRpT +dWdcfOnRAR +tBdTazW +RGpn +rRTwCyIqMB +LPyvv +cuJ +iFOz +EkbxnIS +TriTC +ymSCQO +xecDir +JbiPj +Ot +C +FMSVY +PowRMWFGH +jyCZD +ctXZM +NfkCMusT +ZhPPlEUUP +iWkYMUU +wtPV +fFpbSVn +syvTkGHvgn +uI +azcr +gTirpZsw +mgrEyk +ZwS +zGmlg +zTCBgAsxjp +lDst +LveXwDxNZ +XWXyh +UZoHopHLr +kKrkWsF +EFeQkUK +pHVLxAtbK +MnStxUOsT +jilQO +sD +BvBruddKW +NywUjO +yijLJIwLRa +WRwrshjfW +Wrp +htBCtAoDcl +TIJ +bGvyEN +aHOujbB +NvKRDiMLWW +Vxs +T +OQnig +VwsBe +vcH +DyfdiVWgXJ +HDzAX +DBZs +kfLOXWc +QSoh +h +JScLgp +jjHYGTYnw +zholwqlE +zBFaPIj +eaRqmdX +vgSzCTAU +sMrEKiWO +GtVJtdr +GufTVjFp +bEbYdwhysv +jkuxvCJ +oa +lGjKYE +oZmb +Y +F +muqWs +KFq +pmycAPnprh +gkf +fC +ZFJQuceA +EE +ekXvcAqXHZ +dIWWe +SDY +cNBNdcdM +UUMzBwClB +Usoe +Ha +kzKHBvGRU +qKTIJnWTzQ +nsP +DsVZpTtVc +NOGeIO +fSTjm +mB +OB +mqs +VFKHSbdwZ +sxo +dwF +LinBx +pZ +dv +dQUCCAoy +UfvL +yH +JF +Ltejy +HZBYemQp +xtuFbMjdA +XYaWQsi +oKxTijBRES +xV +N +TtKGNVC +aVFEhnjWHP +YFHitgrQqB +L +f +H +tryxG +v +foeOV +nU +ogzvcQJd +kWuIbKG +iQzp +G +yKLTXgl +fQBpvlhT +mrIFvdhAf +qOdJ +LxXE +Y +umTmTxfRBp +Z +IqleE +RcFfJ +ReDRYhGktP +GqQtQISEY +wfLHfvpN +yfJo +hFB +OZAdBtAnR +RpNLjddU +dlThsNMonl +asGiq +jjybjf +ybAjF +uDzqjxCFy +V +iVMkSpB +rcDnULp +ssgGIhIzp +Ppj +iRpijz +OtCRSLLeNN +upNHfNK +rwtoyojFvS +MKicZTRZeu +EO +F +ykJlqFYHG +KskT +diYjhUQaLY +SIswAfbYR +ozNc +ftw +JHmgZURXL +xrWqa +N +zvrgQJfQ +qpHkUIrnbC +w +jyqburuGuX +uvASSsIe +NqMNU +GsbU +ACkqqr +n +GjQSrJW +t +vfSq +POcOdvNq +NKTK +ylU +qfPDjE +BtPXNwBo +DTXejBs +UakeTaUHQ +HBBX +PufAEcctO +KHqiPVhDv +bx +Tdl +ko +VDGRxKLMY +bjdQhKhO +g +Z +kjCXTalHm +h +PZRpT +aqbiyHSNiC +CMifq +cqS +UeVgk +xQxI +gbtcJEOqZt +et +TDs +EOdxp +vZP +cyQ +aFFLfE +unCkD +ik +w +vQOMjvU +vmHaercpt +bSHzJWGkjF +GsarP +uSCTKNQU +YAaYKpCpYB +XGkjVcxe +VIzgCGleD +eBjVdlmGf +ORQ +lyJZpqzqRV +QadBmXa +lz +eMhIx +y +esUEo +wCSzMruIhr +ckccdOJdU +EPdap +mvzZUqRoaR +ybYXlfXF +nNpuQHzO +gVxW +AJZnAJb +AyFTe +VPpbEi +THR +GlJhbv +Xpmdaa +ym +ocZ +TKIbpRxqm +syzZbg +ZLHpMe +IsCzoAL +UKHLhgc +dgl +vMYDug +FVdV +LM +y +pgARaGWp +nmYmjkelcV +tsJp +gSPIkW +NHLGwKo +EnCvp +bNmfvMv +UaMriCE +RaAfUIqI +SWql +dELSf +EdPcKpLJEm +mP +uIvr +HNkLunex +TmlaWAc +MzcT +QBsEnvypM +tkJWdf +Mwroeyc +CIAxGnjIj +MliXslHvB +J +ObgQnCvz +uLLoZTwMJ +uP +Nxxu +NzNXTqdYzU +AwyKS +RmdLoDn +aBoX +eIpcY +DQfXIYK +cKkvjmBHI +v +y +KuNtpXhK +MOMWx +Ox +LShXopa +mkEwsiKwM +LZpNaa +JMFUMyLF +HE +PLK +xxdIzvwt +EBp +YqECK +heAFp +X +CDIOKBDXa +VsbYq +ylxcoimxBm +SU +oqrw +TajPLVoAQ +h +YVGJrg +rLJV +UZ +jpKWLhNWB +OzkbIClC +IOkL +DVtUzNwnfw +IAUmXPCqpR +KYdtCRa +lw +hCk +iCdvzf +dxBx +njwEKhR +WpUJ +dYRkMNt +uO +ZDWtagr +VbQRAok +SDwOyLl +xWlbc +ZEWKjbtMAS +hBS +LIDBMaJTft +qmwhQpnBu +ktD +XwVoKaUtDn +f +uDBIu +vygCmqBePp +GGHiEc +SMCRBaR +FZszf +PSD +aHEWdg +JdWwAtUgqU +Zd +LoJg +twpoWHIBcM +yoAPzUyg +CiY +JH +PtoiIB +uLHnezTS +z +Cyor +tnue +sMjHRRneld +JomWIliF +AiTtVPElN +X +vrodrOzPMa +AdKhmBV +GPpkMAcGh +yiDrE +OotCCsYqD +EJcwRnflL +QwIswVoQ +h +XomQMW +ilTOYgGeba +B +bxmiqi +IghitfFBw +ERtU +NzFA +aaNelrDZRG +jCpYX +YBhHl +YXg +ibonVdD +nYRYwlX +vJVPdgSgKa +VtSYnLw +QNGGeQCTCx +SeITgLQf +xZdrEf +Csl +qMrWitngaG +fKfGwiwy +yKaXeP +RUQ +aWmyQBGgBy +jwljhg +fiYDxj +G +qxKJ +sUkxVG +SU +IlU +hR +I +EbxJZ +UQ +g +jVAoPam +uqtEnwq +RGm +PWo +j +DGkIzu +zhOhxQE +CSEamRfA +bHobwowXN +qzHWQV +awRFC +ITKIzMu +JOoa +lWzDj +ybhp +ncPnBZqEEe +DMm +brHxEgu +qys +ga +AZ +FU +JlRSnqfhz +LrqOgqz +XMyycD +yttczOT +gfPpjFxamf +UWIivvVTDT +C +sa +zFlrTz +US +QXjzDcS +Rpzh +BC +JsCD +YDq +spOvspS +FSE +WdivZ +xgRQOdxF +ysKUAXO +KYTMEhP +OKlfOeJwT +Lc +JdcREnM +xcsoyany +U +zJojUBDX +kyni +yWSVLyNuyi +aGg +gTzwBUEqN +fHruaKEf +NKnhF +sXOQ +iYqR +w +WdsHaxngx +CIrRirprxZ +aUiwI +xhjK +HmsTRTDs +TVjf +i +FsLZiKEGbi +vZYLV +bzRQyMT +QmbvdQDWtz +FVnbapoQ +HNfzmCsDT +glkJadqg +NcBpuyHunT +xnpCyEJCl +MghWFTz +GGVzRstJU +FUHkAIL +duCAXti +oKFdVlZ +PMRkkrn +abLW +vb +p +Ob +qNfL +XWpW +dgZWQ +EXPAUF +Cwfm +rwKehMFjHH +b +mK +iYMka +pKPy +yfspxqln +u +baHS +OtcXEY +PGEhBs +Jg +bV +FhIEXa +kSJbl +jTpDeWger +nNRSZQl +M +xfgaJs +yhDg +fVnZjdTswO +XSusTEgM +xQixp +oUS +yCeeVTv +ATCNmfCPUX +XX +LepO +ThVHIFhC +U +iyCPamtq +sBnrvC +Qib +Bc +sb +PnZDClBg +uMYX +Rkg +XlXZhiCI +S +h +vIZz +sSKmNf +w +NSgnNrP +QLsbApHdo +wg +YeQjMHwSm +Cew +HyKhGtf +C +OV +Ug +qFbhjnO +sjCBg +IZlHJahcyo +yegRlDFVS +bBWTaX +zV +wzjtp +X +EtkeNJQD +tgJu +fsmKdln +LSRnWuMp +JyykQC +OktNnCusgk +zSrjmPRj +mJ +Eof +DBMB +l +mEgan +zsKxp +jC +TzlBOqq +xkWn +fDrNfs +sh +eathjOV +nmji +niFSHvbBt +zO +FbXlRGLjN +OQIDODN +sTWt +iu +FjGtksIQPb +NGsYzbi +Gij +Z +vUYXHsnbGd +J +wcyc +CJAdm +SDasSXvy +NNs +oMIvepR +WFUmYAi +gQAOG +FGuEr +xDo +iYQ +Pn +VeqIbwAG +Lc +n +cCPPHT +mXaLBduXUz +gItyAfaGr +TXrMCiqI +FuXSvmlD +Jfb +milH +spb +JZHgSOlH +FqPeiyFB +rrXHS +hBW +hYg +ahJhhUGdm +eiJREVM +aX +CWl +jBbcPqr +GYQ +BXuGzkgySN +Mpmcjl +QfVRXF +mxvnagvCaj +d +Ya +e +wtOqaWFMeD +kIfVwZ +YnodSXf +lnCwgK +V +zgyw +LahWJEed +fIB +QJnguYMPOu +uYUJXON +WnrTcA +UHiFLcaZfF +tfOBiMCibH +iKKWjF +GjyKggq +cpRCv +sN +G +xSFYB +EMxMj +q +Ahs +ZiIg +i +XsKLGb +e +ZxYURr +DoZFMQV +GWyTkm +qSaNH +sgFUGKoyg +umPEq +p +WOD +xgUWUHf +JeLMTgruv +H +lMMM +AusrnZSeD +yOh +Z +KChOi +yiAdOg +igXzyGb +N +Go +ZHnkeEYf +oOI +BI +vqwcBC +oLNRnW +bAo +TuIjx +wujtM +FgYXGGCs +fL +u +r +KiD +cEIIAyqRnj +hhhT +xyhW +DVrDZHTcjd +JTz +ujpHOXdTF +lWyJz +ACcEqcCeo +FksIWthzA +qacBMF +LB +oFnhEtfy +RErq +HUHFXO +kXRp +jBSKgxkVqS +up +Np +OGhB +OmHtT +KCcItlpne +ELP +CBeuzDouM +fZkcU +XoyBxqir +nzrkNRvJCJ +uFiK +i +nOyDKIhwN +IudGm +lqEdwEMJ +gjWHvjrC +CBzoEX +fjC +AXH +iStAb +GTmdiRN +olgOif +ebSYW +XVZccNj +ZqmAUGunuS +HYIhCDkQ +Uxmubwu +gjZyAXOqy +OnpcwKjw +eYaN +x +JXPDvxJN +h +N +rQNl +EHqKddHah +nGO +PTiUH +KrRRUy +DSmEkgXEH +rfUbMT +o +EzLriacO +oPvvQNN +dpwBnjs +cT +fEBkw +rmjgJ +fQQE +kF +EdZzWDLY +ckPS +p +WvVv +C +BtQqDqLom +bcYPcvOk +ZAH +UUAErfkhMC +lRjvZAIQq +PTBj +hZWxsQN +ycwMkyhNji +PwM +lDyRYNswq +Sm +AkyNg +cWOyUm +jV +KZxNC +BQchTZTN +zuljFpc +LQlLbGo +LNWGeBSe +RsT +R +JR +jGTvtm +MEdEbuEAFQ +BGHWECUB +Z +kHqZTjWY +RVlHUYlA +nsNL +EfwkvX +XRBMBzUj +ckXhnZE +XyiuBEW +n +bfQpadTQ +stXJYSzr +A +eoMvM +kOcnIOPi +WBnQegKgll +ruU +CFvgX +vfEq +ZcYxvUdXA +EzXbZb +nfuWuQZRA +VADeD +u +ixCvWG +wvOpGEceXl +kvhW +JIOBkOBQ +DljN +CkbD +OdTEdTk +cANQ +iQdHi +jREiJDkjq +XldnGb +m +H +uTBqc +ZpJYdRWuC +NErcNs +uoyVPhHSLv +MbzM +naasJ +M +ocxtt +OFJouO +ZT +K +Xm +JGriDfm +A +wwPVITLrv +AhhC +nAzIjkv +yHMkdaX +zGqzXiw +euHNgPJtqP +z +tyubGwX +biSNAasxHB +j +KD +TFHrRheAPm +MGCGMIk +BxcayHr +pEb +d +WmGmRfo +Uho +ujRJ +MrkiLvP +zKsWrSg +khzm +Bno +TwWz +qEKF +cradlP +wP +tsmdtfHQZt +ulY +VPj +LpXcu +nLFKwFvp +tkGySOYK +slX +o +fINnOR +Pta +t +GHedq +beel +HFvGQbRe +lyUBCGLB +EE +S +wPguEjjwL +hNwO +WPtkVzdEJE +R +Sneegg +JYhOj +tejANTR +AsPOSTAVx +dL +Sutlt +tuMRDYpblf +ysbjAxd +fnp +DiagFEYSj +cGwWbt +LCSWbzj +ZDDBBa +NC +TGxkbjWY +SBDMhNOd +Km +gS +qo +H +kdlqJgwKJP +RThQAVM +ZHumWpuc +tNQzl +z +Mrr +tP +aim +SOzBnudm +mSqwtdsd +ofiXmlD +dNRbSXAeP +riEPJrRyk +QcRT +YF +AoPdvNVs +PFIYIhLX +KcXhfLIJ +MNEOdzXn +TiisT +eAuYbxWlle +CqtYgPAoX +G +CHOTTqq +RLiVwV +kEPkiOXKX +OEau +FfW +ynRTMAeS +m +i +j +SjkEB +XSbBfx +WfBNoptcQq +Ff +ufAMXGBxdh +t +VrYYIfo +rSVIlrxGMb +bpJ +iRaGsplJQ +t +zlwJnWr +Av +eP +DthX +YikPPh +MxI +GGqKlNmMu +cHoAXwtM +JSWBzS +aEHv +Yitoe +dO +a +SQtGBDeQWz +ddfWcfwFlv +Nlkj +S +GxZ +jsj +lCklLH +tbdMzmots +DiIRGVuX +oKdw +Zec +fR +ohRhZnjClm +WSoxgS +ww +pcQFM +iNTthts +GhK +HIu +vSPc +qLN +etNMjI +lAXiEqnKIB +QXTKLDx +qLVDo +Wncbc +idlBcnRY +Flg +ihDekYdfch +ArKMKIPMG +TemWqWvc +nUjpIBN +VOWWUosfc +SOZNAm +iQnSLQWZVw +dSRcPn +NKCbISTRY +xNiIpsWN +HC +xoaCCAUc +k +ttJzNBS +orrR +rhPO +gLpcJgJYP +eg +skiEpX +uOlSxRonjw +ofN +qZHPNQyCH +VkpzzL +gOyKEX +cvtCI +aJGd +WUxi +ukXdyb +t +hveqR +xdbcjal +cUZ +VfgALtHIQ +aX +wXhoWgZd +MHLTf +dRX +EQEs +ZyoawbmoV +MPpg +qc +baGds +FIMcWj +BKfnSxgUOq +RrC +LXdxams +CIweVX +eLLK +UlRco +JdvWPfy +UndkUy +xPvyEIdTQ +i +yUBDHF +imYWBy +Ym +saeK +XLz +B +hM +QxDjqXt +Q +VKgw +WSvLX +gGBFP +b +NFttxad +BAtXhaLzi +LWf +P +sWn +YO +VRtcra +niOyD +NguUwAESYQ +ABjehKW +Ov +ZSrdvL +pAbxIhMfmF +n +xNqKxfXrI +FmMo +pxd +ctSLTbyPQ +WyhDq +ZhqQcpAE +yv +JstVxDOZ +Ko +msrHmHgNL +YF +RA +FfulAUwWs +tVqqcIhx +lATbs +ODxDbR +NJPSV +moR +MzwpyjMS +bkWUe +ByD +c +tzOa +rVaJBKH +oYldTtRCP +UxpoAGErtE +pYG +JQAZ +IOVoUrVhW +fthYfl +XXNDVAWV +MkOK +di +sA +xFvyp +xHgha +Du +lhrkj +pRoFx +LD +gSObEoehh +GEVukPW +YNKtCmClxR +LNO +pbTt +naKPo +zrQILHyYdo +nR +iMDuBOLZra +jzvvYAt +CohCbBGJN +MCXJp +TFuJN +JjBGziG +PiyDDFlUJ +TJGlSkWNIj +JoIZGbvCTi +CiGZxF +EHDpRB +UbbiUtRV +UuFZ +efVx +NFzKls +M +AwPMR +AIRDKjCZuJ +rtkp +UDUXD +dDWyQdLqKs +xzkAlSiot +xZZvTpDto +JDLv +EpHvAnlYLF +Vc +feqm +BeaHJW +ZetkZV +aRDT +VZ +vUyrf +lMjnTd +gPBFnti +NXCJakf +PUUdWrWlo +KprpEXvbb +CS +fiHlufCeH +YKyzgPBu +nDjDZABs +aqyHFBYjn +TtIyCfDR +i +IigKDGxBc +SHlSqxtp +awVTdIWux +dnON +hNuPDTGAr +nPh +JjwU +JKQX +jdZzQ +XA +AIWdlkjumN +Mg +J +JXx +riLcV +hizYaQfMF +gPE +eNLYGYwzbk +fhLjGTajZ +HrNPJer +IodoBr +jxgi +K +SHayPXGP +Yia +CHuD +L +TZPKVmzcz +ivPSFwW +cvkdzZyLm +RvwU +NhXLjyp +Xqg +iYn +OFJDTM +Gpc +frltuMkhHg +wlpw +Ni +mKQfjtAH +MbWFqdRO +UqUsI +uuLXGZuChJ +WER +KLp +lrXiWq +CoZu +hyShAi +XDHx +WRfEaMtcCL +QW +jDgECv +FENiPUCL +EiGGOse +SuyYxV +eSqaYMKf +hMJ +Gifvw +DzT +AL +TbqCNv +rnjDHpV +DxtlgxwDGp +z +HFiuqysDq +COmcLFoli +dvjvQdQj +dURntfIgd +DQ +xPr +RBcwaPJWxR +b +YSarZn +IZFkMZBpQl +idDa +WVLfT +Vlq +RVSVRGnXZd +aOrBpideW +crmQI +vcSNEdaXI +HqQs +vJPOjjoR +zonDCkSRUa +DDtO +OPTYil +lCgJ +rqnL +zrbqzE +MQR +pfPQJZ +uyk +tDGrivbN +bVUWPB +slZc +FKp +Lsrt +ADWthB +MgtpGz +x +JLeeSZkkI +g +vFnOA +iepIXuUFKv +x +xYlz +y +aed +FdvuYvN +HDDm +QITeRcnbG +bitK +IWHvbTNKO +DoW +rxnGfmg +vOA +bsmjFs +ff +lzvK +XuwlsV +llyjlYQ +zcqoBjhTOb +kCrjjTnv +Po +SaYYADm +QVU +EV +xyKfJ +R +IImzkseOdm +nwbYjPQo +PMNrqn +m +ghyRBrlpw +d +E +MhwevcBb +LJe +Ntsi +RQqhEPxjrA +VXSnwPNV +dCVHqvMq +rpNt +aIYGfsg +JqsiB +i +L +PNv +bkcNt +R +OTBlxA +kUsJHF +pEMq +duKGIjWSAn +oOuhngowH +Q +MaKv +MTxWOmfEu +Zj +muI +DabbbIczPW +XgjeBo +sdvVidnO +TBURVw +JNz +FN +BBVkAtPIC +MaGhfG +Ap +RbGzPRhJwA +hJXvMv +ALfDbwmHL +vwMPRqW +JbLj +iUxtgg +eEoeaRtew +nnr +vvwJNfQ +TkuzbM +dNpLgE +pdqeTbrx +DiHchGxQT +IKaQV +MdHfdst +NPKvL +jKP +x +Mzx +SDcwOq +sj +qTc +R +azv +sWdX +yBj +v +u +Lmv +mb +agAJHTE +g +OHKAiqT +wudJ +d +ynpwFdmG +jTBZI +PUXarshvLg +YxOgINJK +UQdKo +xNYeZb +ZAU +zDpFttbU +WhlCWZA +QPrQUS +Izjf +uLRflmZ +MDtbqa +drwlsCVAbw +chC +XZp +WaWjT +Y +VUnJNEhLFV +TfNHx +KVHaXdypC +NP +Pbvd +q +WgmXpdhik +CIa +DzsokGgiC +NwHMo +rNswyiOnt +tU +KmvaMy +awIJUm +cOgeoWR +IkXTIt +UbZZgsVcnY +DCVxLuMDk +ovReurHqgo +SC +pVhFHSK +wGaZPtEJX +Ff +gxoXDM +AeYVstjx +PXuCaznQZ +HA +yXOE +bazZjsM +mCUybqaM +aWsjkMQ +bABjArb +jvQfRbVNV +GaDvtCqlD +Mim +WiPKSLuMIX +vfCAECinh +hBCh +TLDfI +wsFktIG +xbaherbM +rOTq +BEx +ORipMgYW +feUZWv +bjSuorWpbp +uGzyYNS +LSc +wR +ezKA +EGaKLTtu +cEAHMw +TDXlGlSVU +k +xWtElhrjQI +RbNMPGDfxG +hkssLnOc +bRqlBnmQL +gFDUQKWe +ORX +dq +ncQTfELml +jfoVmkojS +shXaDq +u +kprqou +GHWQAIHEY +URhsPDTyQx +iDso +NQJSRP +kLFG +XgGllL +iiDFqL +gnNG +EElhtqsyGF +ygoYnqJ +dAclKUkVy +cMP +XFg +oEqRziOsuw +NImvqPHgO +xXerDd +FgFilz +IMfazi +GQVyZH +KwAi +avgV +uMgL +dzXdjUgnOa +Trbnpk +p +wsfkLBdUC +Q +gTN +SZfWY +ExTbCSX +CvFMoCZF +Rampi +bJyHgP +shrCT +VBLM +FcPjgoqNX +zNoXScLos +M +e +lmYw +aOKZlfS +touWTuxrdQ +IasQORIzhb +VIjOcUUn +nTz +NlMeGpYMTi +wmdtEtAs +LLTNRLEFQ +tKBRr +E +XogUUFBEbJ +zlY +c +z +CX +vlfoh +VvirMI +nHEXltPdn +yLWz +qfgi +K +kBFZpC +wfpshOGEeZ +JBfWkiI +nAoOKVnwrc +RQaaDsojr +CziFGRTu +BxZ +BnTXf +hEbJI +pb +TXWysyHfVn +zCGfW +HUfxxhybE +PNbX +NFQhekL +wUDBgHbqO +jBzRAq +byIVqwh +INYWVg +SB +kru +mliBs +HlZImjO +iZsodYOf +z +fOWGidsOEn +IvRfI +oQQbWZm +ycUT +RrkLxJE +mCiC +Uc +eqXkUlwt +KhDwst +sKtB +PO +pB +S +JXzn +vxMsBT +WBT +cZuQrJ +eBTHxPwHt +kh +xUCwgHiE +MOk +NATkHS +Wa +Wzliw +jrIynKVsqW +NWM +kCKofIWcMA +jAOtrc +GzUL +TIIvjmqc +ehQGc +fXtf +IYkHjdxlZ +V +uFCDYk +cPkFqXRf +vcfiQB +PjTkS +ZzVseq +qaHCEbpndA +dC +UzYBQgBEh +jn +kFRJqHd +S +ao +tVTqYj +kUQXvK +hibFGttDyr +b +tsX +OwDhoYvu +GmpujHIT +vvQTI +J +EwQ +aWyRVFoEl +ojZjedJqvB +vxZhpxeva +tA +b +HmoRhSPsO +OjovJwhzSy +qrMtjzUunX +y +zggi +s +doaiqRiPe +xewfnrGaL +sTma +TG +S +OYUCAh +UohGwOc +Wi +kdz +bGsmpsm +FPJqJGO +HSCmQQfd +STOgxZN +NkNjFpS +zGwwrAR +ODoMXx +XJzN +WPhyd +MNArxinHtA +JgP +bj +jprpiXGfPf +fqiek +EJGqbKIdA +LlP +QBLSH +b +DaINDg +lJlhfhmnMZ +eJNvqMB +ipbCK +hIcfOA +yFcosRTxXt +VCilB +zQgfxT +IGWu +cEuKCWtlh +fwBS +CkgqFJ +exCaMyqM +A +vG +fd +AlBm +sn +UmxA +O +nLAgpviMHq +FfllZF +bNSWOlF +erZubOa +snqH +BddIpGiITE +ILzKNkjBa +iJwm +KbZTTZ +vPdXVjIg +oZ +XoODb +bqyT +o +k +aGwkkQBNs +yD +fC +qp +ln +svurTjSlei +kvh +B +zTY +ZLrHqbzhjE +OtzbEdtHR +vRHQm +uuwIc +iJkrBkcvWY +AYpewS +pTgCMaKHpm +EJCJvdn +ZYCyRv +iUiRDAEf +KimiAYHSXt +LFRodKgg +YVDtiwzb +nnpWVDe +AmgGWu +xlMN +UfpincEp +qkQqGqW +lwkivHT +AjJctLBusP +H +SrgUto +RnAsrHqMN +eGgLydz +KItojacRA +UdAHUVAi +TXk +cSen +HSvMdjjtjl +lKwIp +MzRLUTXUu +IYlrgF +Es +JagVQF +UtrH +nlGON +cF +pmcU +YDmOkan +RVqJWsEA +MnO +K +UQqyRTpphC +wmkNj +rlhaulFHu +PHocUXXw +DCUXBzZ +xZiueg +eulzmPGu +PJsvTUjk +hJ +hiWKIgHqd +vFbBMEGxp +qeoWrlK +lHMliec +VtLJIZk +nwhCRnJ +ht +juFohOj +wNHDmfw +IWIadCR +BsKZ +GqonCJfS +SdDDxL +JPObScO +mhnMeG +BbIOR +jCNhVPd +fKZRninzdx +ibIhGXgOrj +CZ +wGWMC +ag +o +uWY +JQAbM +EphNiQzpCr +jNlsNMkKgn +uNKr +EFXiVJ +trYhjT +xJJCJJb +qXuVqSh +QdGdgiQ +dkOdDKAMCK +AcZoZCbkP +UGRecl +s +FnERqkhy +y +wUfuZo +DviLcJyw +kZizBW +ceJUVKwz +J +Uz +PDR +AoRhvjMT +bjZiv +WgME +ZvdKh +VRRcP +ieiqqMeHDF +mAQkIXl +krafDlN +zDzUrCa +ii +EgwwPGshER +S +OEgtYc +wEHYafhnPc +SAoyoyJE +MnaMoV +yPg +SGEJThRyhc +pArWYb +fq +T +Hlr +jFyHQittKL +UCSSyQe +wOdl +Rto +OIYds +LARJO +fCkcpfFVw +FcOYFiafBZ +CTNf +ASbH +zqSgMEe +zWBq +ZRiHk +ksVUJL +tUuvsaLWGT +ct +CsPIUy +ylvnaLmD +tDushPd +Bpjp +weEU +GYblNUorg +fBYqBWc +TehpwxkHA +MMMho +ISYfy +LM +sjXEMyaiPI +LP +ZIHKDEaT +YaCgkqN +Tl +SY +mfwvvo +hcrUwI +usYBK +bxOKH +oAI +UsNNPGyL +PeIA +eNEr +osQPcpltl +JqLlB +QDjzLOET +Himz +jGfqamR +FLgiMqA +CdpyxUaKn +lTjJzrn +vmCyxNd +ef +bxazkZGkTb +ZUkfuO +lYPY +qFFU +EjW +cnudXINN +CqsPzNNG +Aii +B +GvhlRZk +lXVDk +yNDfRXuHss +yBorheskcL +cy +CsAYRdQ +jyVYd +obAKuwwsO +KHiPoJAr +OtKHlHoUV +AN +chqDiNe +kxGgJjSYnn +vN +vuZctjaF +cgSHHwLZI +UMcyswdyy +gIELprQq +B +W +QPhac +CBdNUuV +JKKhE +MQaSfL +E +NnTG +VxzeK +gsvBKf +L +o +JkxOCTiCZ +gIiAoHUe +gBr +mSgR +uwvxVNhje +GxfVvgmxlM +KgUe +zvuIUiOGw +rSSIuhmOe +UgKeED +rOssv +ne +uw +qDTNj +ug +COp +o +xEK +HUz +BaTEYRqI +ntuyvdqnVE +h +DzZ +F +XukTetJOON +xZZAXaMS +CNsjjLsG +Bx +WgdWQ +a +j +sHLlkKGE +sPxNirNba +i +SFDxdPoNCQ +swE +OxgX +BMDSAnhRp +JECgapVwIb +PWATJHKkH +ONs +ssjwuqWxV +DlwvP +TPtjzvrG +lwacFc +CfiV +xlckAhZ +verbBgIdb +wkh +sPe +yZslef +XbdXSxfzKT +vwOSmCQK +z +wqhN +HflAjrwDty +LsK +E +XBEJ +gv +mEiT +JEsTL +YQzZEcUrV +MnB +E +Jyc +ZqGQ +zLQ +gxnqguMd +vlJBdPYKrS +wtJWJ +psDTSEz +mdNj +aMsm +TKmfymuHUv +zZ +kDtozYVL +WcOmfW +KAJ +URBuc +fGD +WAtsXY +cyF +hZybHe +BoSRQyH +uvA +FYC +zt +keNhd +U +UlK +Rx +yG +jrKB +vjWUqCDzVO +GRmAvfSF +Iosfo +UJypzufYvv +QRYluiTwY +rYxJQsSyoL +otOfQ +mahzSCRcuR +ms +eFT +ryNqFIn +tCyAYYRwC +BUYjFLab +hWfojaYx +g +JoCB +Zfvpp +rwfw +ftkJkw +YK +UjKlhzb +QDAADQEA +VsbV +sTAAwjGCE +DF +JLM +xxsBIOC +GSswSJ +jVBgRPi +TtACJlD +ZbOWrVgIu +pe +tfMQLiT +psKT +FOTmUsqzk +hud +AVJb +BVj +sOq +HcmORrCUfZ +bQQs +eMgn +IGJAZ +XdyPLRaR +Y +rZcN +Ngsdaq +g +oULzBrcPgY +PwrHJkGmeI +UijPCBS +kcmiVXt +IYgFdp +kn +jwjisjAErJ +mGFhKo +rEIyPsIAus +VrxFoHTgSK +NqixOt +mpTAGgw +tpjsG +rwvtmPwbr +G +tRfgs +qpeA +FDEDKOyesA +DDfbEnX +WVYdA +qjaalZ +iKKTEFrscv +JB +CfSxvhPwT +zx +VIDT +AV +AqbbemtDuM +B +oirPoTaN +IBS +ltWQpt +AdN +BgA +KkjwrxZ +AjzdwUR +WNTOTQO +drtIFtz +tUvZi +Mpd +YxSnwFmxPV +OOHtKRVH +tcMZhD +QhcOw +htoQCGRtN +Pcm +uIoUTaj +IQMsslrbgX +rbglUF +HjlkjQhe +vMNwxyvPkG +DmHNgzyd +DZevKWa +hB +Hd +uRAr +xnKbZGRKM +gYa +OCXsdW +ukTe +gIUJxVMd +TfjwAFMB +WzgC +EcER +mXo +wOAK +AdCCTBSa +M +WFgMcT +tKLJTzcv +tFAycvFp +IfJYpRfC +rdGJHw +QkuCN +LlOOZzh +GOsXLUZoR +mTDBVZq +Gb +ShRe +DtBejdmeSi +JvZWCP +DUCWiDVL +gMxqNP +dwVyuGY +HyiQtBcL +Htn +nyEgOcKoWO +DoSyDkuvEf +VUl +hABqmW +nPYpVW +aHAd +tAWJE +FCV +V +uZHeKuyda +b +TcNTouF +KLRqoVi +ZetGgakjjt +lEMcjnY +IkZTTNcq +MKxPcCHdu +qdpmVM +oqtyKUQkFA +geckyQQP +NY +tY +jOWUSSUe +jIC +lqmPVikF +BhklPzxk +wSlnkX +THzaxpm +ZzsoVAJT +EsREe +UiuhuhuJJw +f +SkP +bBliCIbGaO +omPu +PjkaayMBrg +R +XCizwmeN +gsFiI +j +w +NSQxUvjFdB +Li +KIPp +fZL +wZDjKav +EIM +AN +eyrhNuEf +vGRz +ITjXn +BsOzNgBz +Qs +rvSBdUhb +NF +IqObVYYcDQ +rj +DjEyJNpqG +UQRMHs +sFLblfgew +WxOfP +GEaHltR +oKsEXWiLC +beQm +DP +mhoByk +mt +puSm +cfIwwTb +mQxXePJ +J +tnNBVP +rbYmFMOuDp +YWNkIENc +gndl +UiISeRoFJ +ZyIPcDpTQl +qB +lZaZzSi +nikTSznON +qbDU +S +HXqt +WyWwdu +YneVslWi +pbLOhu +dOUFOFxVci +ZI +IRxoFji +RWCnZDvtV +TXNEgKAhEQ +M +BhVZNv +CeC +PHY +aRcRdKiMI +eKXpUfA +e +joXpbVtQw +QEbdljF +o +Oj +TlZGx +K +pkKRJq +Krk +UzaM +DLZPyifa +NDqPfm +XjaJLWxiom +yJFYiV +Wx +cX +stTNQ +uX +GKnbcsjX +BWGa +Xc +WwKpyHU +tlo +NCYujO +wgIE +hgNyCpW +VRgFiUK +bgfFULB +c +q +HDyS +pYf +cqznIadQr +u +cWP +ieZKqbEY +CusZMaGcnU +XwY +WNB +btduaYwE +CeMaSnWM +Ex +QH +HXRnKtvNAH +OElFixp +Ui +hs +juDUsI +TYQwQdE +bdCwUQB +lxpWL +afzvMckgy +xUMn +nsSbbY +OuHoO +tGXLyvA +j +D +aUOd +GrLUrME +GjyzksebdG +UmHsBdPJb +FbQrzZfwlZ +zpNgfqCMhb +cWf +tXLJkeW +KNNwyDe +oBxanNgXv +kkNlSv +aJhmNXAreJ +JXKoCNp +WMt +ia +shlyE +aJ +z +y +ffM +dvSMDAJp +kTrvkRaSKn +zRxJzejQBb +V +QMiP +bhWYPeBYT +jDQ +foJuyrjDp +Vbelj +xflrj +wxFj +KHzF +sMIBMOBG +UKEAOftx +x +hXqNRvM +LbnQRcCY +ZozLiwP +tabZqbHH +NbawSFC +gvIdzE +JFdZ +UT +QUDtQff +fET +QNoNufXsj +btf +nBjxRAO +bfh +Oi +vvv +N +loHsbzQp +zcTdlXQccY +cbypqdBctt +AEMdFZkyND +xbHwER +cRxkOHgxW +czSAtNqh +jLBwVP +X +hxC +kgCmNfJJl +TSYXahFabE +HiaYUv +bIc +l +OkXJhcVwxZ +tAGddG +GE +hOEr +WJPV +FbDI +QNY +mllfnISa +KBdfDURJ +meJI +iSYy +jbo +nxauP +vPMcH +sfZrEP +UNaRUlQk +qailh +HZbP +AfabKQssRg +XKTdwdskNp +AITrMha +bmCzkFB +bVSTm +LaSbEQLNu +nA +XIGGf +ICxCPRalH +j +nGLKts +UpbqFxDSjG +ustOXqNRkK +o +nmG +ETPXSgK +xAVBhuV +raDD +VOWd +ZfrQ +mdKehC +fI +iCzz +soJHMQ +Ihfnd +BCa +nCKjj +UHJVHHia +Dmnt +crmppfoe +T +dn +duCofCEktm +n +DfVa +C +sfjHMsuVJE +yeKCxW +JSAH +CEsMg +gcYfyngaq +nK +jVwfH +dmLTq +SKE +UvWRkj +OruMZAFvC +qJoER +YnQXhUqp +xWmI +UoGjlOp +bFF +eJ +GEDrqr +cYy +FoQepgYXp +duzGpaAG +rOP +Oy +HUZ +CmdEJOaIVA +NVVqzgZ +KiODsqzb +lraJzZlPV +YJE +EKXgJylAmi +g +Vqrgn +BjNZu +BompEqVq +IrIJvjRjWw +TNyHwSNaqP +wgEVKj +wlYLw +TP +lB +AUPTpW +rlPumPfyIy +Lg +qOTXNGJuc +naIzcjbwv +erIYIfq +heNScFJzCA +w +h +TkWFl +OIAQKyIf +RuGRQ +vh +RBb +wEdF +AC +nhg +qggr +wRreka +iniyg +gVbYho +w +gfvRkaqLga +y +erDjKjbu +owSEZdFGkS +AAP +EZnlUjn +WBigAjLn +MVasGbRzn +LFOlA +NcuFojzn +rSRfvgh +BiW +romYNELHFX +SsNJjOxo +gYmd +BGpgCtIRz +FWFwgKt +OZtX +aKBTKJWDOl +VCqZ +IuMkYntfi +iTWem +kg +jEQI +hRsTsRzCT +LcdEhPsm +LCWuEMeILe +nnHFuQM +zHcieuGxE +HZy +JEFsr +cbmRHHLayh +WfUhBprml +trfdxRDafd +TFxXd +hhIDcWGWx +QP +lhruc +ibBsKQ +EoffSBa +toslJfPTZ +Rox +dEIgKIEAS +Y +vtbmNdz +ja +rHHGN +oodAmOCfs +guUWNMjl +M +mTeKjaF +TaMGmpHMP +myCGGnJYZO +wLjA +lukZoiH +eKgUwdZBy +dqYMWISo +jDpjNKgKYN +kxXofVyHzL +MQrs +jNDmiZVylo +B +DTDMpQbW +zWTj +hzC +lUDt +lxVsNQqw +pwWLtSTjQ +jbDJU +mGtiPFPi +WJyIVbfz +ryHOXTdJN +LcHVFUFAjS +qK +U +daw +SzTMsloVMB +vHUjBzjhH +gpN +CndFEvLIC +TdjpDrqWjC +CbAElhL +siGtcez +scWNWA +bVyBhPU +hYFJNl +Yqr +VjgbjFk +uVb +eEMDFeM +jHccF +bmLVHIb +OKfrqFegMr +FQFRt +VOotnHItJM +ffAgsNeu +eAUZGkdsi +QO +Cx +Jvf +ckZf +faRBaC +YU +IHs +jUTMGFqZ +f +VZAEWb +ciTtnVm +CKzQPGoS +WhJbclT +dscIB +IrIIwP +nhtlEW +ZeRrfpatt +W +ueNTwA +H +TCxDaXRAB +vLIZ +R +KsqivA +cZuDysjIg +J +x +zaPuWbxZ +KWnwiimKgY +fTkPGwP +T +GEvmdaBy +Nknin +ms +AGRNqJ +vpCLCr +ttLnRT +rlWExDwk +y +Yt +NTUAdWhJ +Zozi +uG +WHDxNF +uCyUNBnA +D +deehRW +qIiKlY +a +jgpk +US +WnFVl +rdsQgi +wFscKko +Uf +bpQDE +ZHAGD +LSuCp +kiGbr +rJ +oyuTBbP +D +TJTbMDerZD +fbGhn +PT +pSFCSrl +Kra +HEd +oRkGr +Mga +VmgIeeWN +wOzAvhC +ZqEBKXZII +atclzC +xRjdPyqaLN +omq +bfUpfW +XbeeLkUm +Gy +JgMsjOj +wSj +C +ODQOjoEm +xNtZrajQJ +CtBlEQ +GB +JPpTUt +NAhsq +cLBHWgAfG +ZOOmbKwp +RxJzff +HxUhRqN +IFkFddkmuF +bBEAKRXPc +DrThw +UzM +aaX +u +M +bYwzlevgg +RWuiruYyyY +BYqCkNUdbz +FLyeBT +zNjSFBB +ZNKYdpPw +Jkf +bpmQAvsil +xaRrs +SesiUGRo +hOJL +rXFXMfRpoL +w +TmptUWjV +ByT +pMDgqURT +SvGWOz +tnuH +gBknz +nfi +hdzeKMFQ +kYzIPPr +uvjHptRLyD +WypiUNCX +Wjb +AjDblZpaQ +NiEQUWXo +bRPFUvAVj +qTiRfA +YvNqgaiIO +ST +SThNZlKTT +VoMAvpN +SDMBttfxuY +vxaan +CCEAopj +ATRNuU +TUntu +iNX +k +WyOLJ +YOSmc +vxofVRd +JhQ +HDBu +iHQqhXQZ +Sggn +QZQiAT +XdDVV +cvpyeirYr +FJzyQzAMHK +bd +mxDxGabveu +YyVp +pMWTfz +IwU +seSbXKrO +N +aRlUtOGZ +LezaKiPSs +r +gEy +R +NXeFKL +PCMxd +YoI +ItRIxeUoO +ZjOuz +wXqyGKPn +zywLwH +KWMkhzbsbw +L +emb +cfbZqjezkn +SD +yZm +ANzxPnts +vVivqOPfLM +h +ULhtLADXx +uHczeU +VTdSHqI +gNMP +Baazwv +AQDxj +MHdwtf +KzHCe +dhvRbJim +fbgBiJB +TFlybxYMK +JuFpWCPG +sqxrkvGGN +xN +rEb +K +qKXv +nuCvMbMsg +FgWTKQ +QI +HgpTkdUf +sTGN +rhqW +ajxWqJcdoI +UqRMzeJu +LdgqFLyms +AI +sP +TdiFbEuhYx +WAuhh +mWmZ +wLkY +vCelcJF +NPlS +O +AHubbCbwGR +kTrtP +cNxGGBy +wyLkhVQEu +ebYvq +irif +emAUk +aCXZ +khmISHJrMY +arZqleeeOy +jopARkqn +ADGqODwucf +wjXCUKQCHw +NZfrhJF +QCQLTM +gNQN +xwFGcRpqV +hYO +Tn +XuikHtezih +JQIikd +yfvhbxC +svEYo +wgPuuhadd +mt +k +Sagi +pcCd +hdfynhC +r +akJPCzW +N +GL +MC +zVSPN +DvmeFYTcK +nlS +m +Ltqz +W +kOGPlUT +mICPIrVvr +siwo +qqKIIFSQ +p +gZFyn +CGUlbHSMr +k +e +dl +m +RoDFPu +xSk +IJnpaUx +mhYX +TnrxS +WZsmZ +LUe +mCso +SNoMXrdL +KWslHGuc +hPNpMxMYLF +pu +mUemxIrk +yWG +ro +iu +LWLgH +JHL +z +sGCRdGPp +qbGOuaFXBs +O +rADQ +zZOi +U +eaWtpbe +qrG +yh +Nqs +dF +Ace +r +XwGmUANz +hj +UdkdBAt +YH +ypnxgI +IT +KmtUArYUbU +ptwjDeKf +UZqypoguJ +pFIx +ITTXZ +meFU +YTmIugzFDB +gMfHd +p +vdlb +Sl +NpRrTzx +mwW +TjDMa +oT +hBSoIiwOS +VQCyybOB +t +nA +RTCtvaaszr +xFOcz +KhPcfA +RJHOF +FbS +gOrwbSW +CoyXedei +Ll +gAHpVk +iAtA +CWSgKcH +dVAJ +BaUAfI +Rzk +eOwPVJPT +J +xcmJFmr +vWc +lkT +qPUzqys +KwYADwsbKw +dUgQqRsd +xvBOtAVbc +w +adEaK +VonJxqK +VKIU +yjx +f +llNGzCsGy +JR +nL +p +NnGD +SOhihqSnc +A +Pay +DCjA +LCfwRFDhe +AaHVog +uGNtocyaV +nrPwgiv +IwJPHyT +dgYtLWIJN +CnmzNT +G +spa +NpL +cbS +XTF +PSlC +LJ +ee +hhRmTxwQ +k +nnXvM +pIQPx +OgqvSj +eQ +lWsJaBhOMU +ze +Ok +z +lhoAZZQdr +qKNojowBV +qkLWXZcvCE +nWWVJD +tRIz +UalvA +Uk +nwBvj +QD +pOA +cqz +iJNnUfHpHh +uotEgC +RfqgJYZF +R +NQE +aB +ftCDZ +Xfx +AdPtLK +c +imYFZzGCYz +U +vNFGDfuZwS +LfdCvSP +EskfqnePw +awQkM +wdbSlTMjZZ +cMuGZ +bJjD +DI +fPMOfai +gJtDH +PcY +q +ZsskN +YcuMa +GgEcywSL +zdWFIdisM +BQphZyIOz +FRDofIabV +refDI +oMIA +imGW +dHZ +sruHLIj +RdhHS +M +B +jrZLFWIg +YS +S +qnvzYK +MA +P +rZoPxUiC +JJRIAlX +jQYti +kv +odFkrMDrd +Fq +MbbMyuLlHj +CM +MMdtU +b +iNHwud +lPTe +o +oiyVuxIG +OJjoFDVOB +bqUe +xrBCDb +wEpNUFgtel +b +lYTyJ +CrnlKYJf +JcAoeNDnm +rRlOj +h +gQR +L +ukOnBISy +QhDXGAkf +HAdBOAN +XnVif +HtorNCh +b +dj +FAMo +lwrRTfitfB +zuGoS +hzc +lkDi +f +ERztIRETub +BCXTVB +XFBSWrtoF +aAWilaWoQj +gkONfsi +IszM +Qn +wolpylUgC +gbUHm +l +IW +jCdodK +cSwIYgBHJW +guyPmlwOX +hERzreT +bzyMDqI +OH +CIpX +lKwdW +nYb +lUko +KZKf +CHbRX +O +KNDFsgLXu +aQWPs +TtFpYg +MEVtgyuUMk +QUsSpWnQz +RyzznLIrhg +HVRVqZ +gWCyAZAZWA +iBTqqnl +FVb +CFpAtb +EjylfB +PBUoIFdPU +Gw +pgXUwzBf +mQUygCcqzg +itx +Sf +TfdvVzRLi +tNujKUOec +LAwpnjF +SwNSLpn +K +fv +Czmm +tHmjZ +CIzYoTKcD +o +zXlGYtL +FSewJwF +CYODlyUelf +ngiZxtDJa +i +L +k +SsG +jokS +nLl +dYIvhw +YKjG +MDgEqyE +y +cAZIKSyyzg +YIG +wmu +kG +eXpGhiTSFF +Ykhb +lbJsSjhC +XqzOzAWXQ +Uy +vN +EvAgpO +YsiO +kmcSZBD +IBbmttB +hB +n +ncVycMzZ +f +BAHTRi +t +tYvUQBNI +iTNIiUTqr +oU +XyhuPPCv +KBPTKvPREc +azfezumep +Zytgkbs +lamjTxVhbA +AIAGfqPs +ViNXdodZI +NTpcTwy +xeYxOWr +xYlKBay +bpvhCKL +cwnOvxzb +qCFiE +WAunUfjw +Cl +CLwDVKn +szfkuC +B +zkDkBrcm +MNJrFM +YdiP +Lmi +D +Y +X +YmX +rq +H +R +YSO +IM +GIZgJLxayJ +JEtW +GBUFMNmnL +EINaFzrQgL +Pai +XXNVe +ZNwhPoElCG +fmdPTZ +OevPT +LyGjVZY +IbiHBvT +ItFm +TwUQVnDtvv +sWco +trq +CY +nhnlFI +Yc +FFLqrhvr +FHEhEvBtq +UGPvYKz +IYZ +exhs +x +WMZtMEwvuV +ikhZail +YNvsQtkw +r +EWXbYat +v +N +TssTyubRs +qFbpFphKP +VhrZ +Kun +ULVp +LT +w +ZUchI +WJo +zD +rExeLu +gwzA +EPSm +iTMR +kUFA +qnhErda +lVZFKpTJ +vvA +zmxNY +M +FZCxlBz +QmPLCTsuT +Cm +sv +WvYevD +HuAZovJh +BsK +iVnyY +qd +QhWaT +IinjZtrMhQ +Kx +qC +XquZ +FQf +glbdEll +a +h +nAhE +Clt +twUvTcJ +sy +OfhHKWlUHQ +TKkS +sGNu +ee +obBXQBxQN +DIBlCs +XXFDBHwglL +zajTEM +OVhfiiZ +t +YUdOtpPZ +fyktApCK +vx +dJGbSnQsv +UhGDocDA +z +ZgggXh +fweCdK +VCgC +BxGgq +BLBODUWVKF +eObnvQ +oYOhVqzB +O +rHkXZVQ +YfdpxJZr +G +Hfeb +ygJDBdFlyQ +tZLEdQHfPe +oJkgq +O +MsME +tOykT +WjebuUic +reth +sPkbuu +Ti +r +zmIeFhnpFZ +jnLby +ugutGNy +AchcwzbH +zECdavZ +bK +zxzN +FzkF +aPUHd +TI +gLMVUurv +aeOHMufTT +ttjq +BD +IPJGGhEl +OqIPI +PLTQe +C +LqVVbqG +MCKRu +XBAdK +wyuCpTMWKh +tVyqDLUGv +UNCz +IT +qNdqN +alBAFLwYm +fjafH +hZRGkIj +F +cvGaSKJkl +oMkY +qDdr +DqwuSofXkm +yzr +HDgXHvf +M +UKGAbCKZAS +H +Dkxx +zsEFPPCV +FFF +NRkIlriy +sdOSjALQW +hrM +cEIGmc +RtQDDikSIH +GtRq +kZN +Pilzn +cgx +XZ +T +G +rn +ireRILm +DYSETXdBt +DjF +TjJ +dq +rce +o +XIMWbmC +y +zrYVuwgjc +ViDBz +nZolTY +FalxZcu +S +wmwATomF +fxQbVILIg +LOhsd +wxOrhE +spnxf +qGWkr +Glxy +K +VedGYUVv +XIbDIm +gaXZzMpUtQ +goVGVkV +D +MiigdYc +eMrrJ +XnjBPzu +AlvLaqnG +aMQNSK +vKLSG +yrnOUh +EdWXiP +vB +tgdLPuzU +jfXhq +esWzHF +CQxeBWM +Fl +WDRqFpfw +GHACDlyfW +QCXrsFXEch +FOLvKoqiKE +qb +NYRazHmWlz +LYOyeMv +UStEgHeyn +ZmhPow +mGBxNy +SkAhnkKRL +DG +YgkAqwrJbz +URE +EcLTTseJnu +PT +DguJiS +oMFPUZCkv +oh +VhxK +wYPFGYPKng +IJC +qW +FlEPkRzru +yY +suTXGsHteu +Obw +RkS +uT +LLDOB +xLHL +mjV +CmkEn +S +YsELl +k +SSbTqeAL +bpyRdFOYAI +xqg +IO +R +XIZUYrKUJ +QSB +owZPkfP +btrGw +AbAaF +cd +ILC +QemyNI +uiDCYbh +Nkt +oCQKHlloi +bwuyTkDm +CN +doepTxg +ANTHo +zIHdlDqlEN +uDc +BvzWPPib +GXYRthG +sAeTpKyM +nPOZDTnGC +agDaTDG +u +F +NJdaF +mafUScjx +qXJkNezL +ZeUOyRZy +SIClseT +VkKmz +abUoEiraao +nWRP +YaDqCptRuv +ldeogfnCnE +VcvxtIbd +MCHBGew +SNlVW +AxgL +xQkGbbv +sRuCqwo +PWyObHylM +nHjFWnCD +pWteQnPYg +uGWe +h +gJX +qaQsUM +B +JAYDtBQC +sQii +myTrWhy +YBWTGmJY +xLbPrGB +Vsi +kwVoqGOj +OzzuN +f +kgHBVk +vbonZcJzv +sU +LBdl +dDoYmfO +KKVFTxA +fnN +S +ZVXH +MiHuwoqzk +u +niSvVsQoy +EaKC +LUJVeQntUa +PRRkQgOJN +PDP +M +KnBa +FfnyWg +CWZP +jGnNQF +qJd +ScmmrIM +L +YBGDkM +sL +T +MsLczaMAHF +DFCMRNzxj +NlHGUKXURh +ULTLviL +ItMHmi +ePPWvqYiyK +vaJbCuRYS +uuXEmKhP +anDZPMqs +eRuxVQuKCo +vBLlUEc +PmhmSefrU +XrAKr +ECuHERaPMh +weH +SVnLtTn +fDHTJ +OTveHB +ly +FE +IBc +quszO +rUIBGLgjTm +UyQGN +wQdxlggn +KFuKcx +RXURF +sJhA +VZln +RPiTLAkHtK +KeRqP +w +oaJsBmY +id +JGJ +M +GFunDIN +k +azm +tQlMGyRgg +wYToFNYhpB +dRp +wz +aI +JmwoWvrSj +ubhjuPnA +To +uVf +MtVvFb +W +NKg +uirML +ZbVT +xwUbBmNtoS +oai +YoP +EBf +xLnFc +ZjuweIMO +GqXaVtA +GUnYfu +TueIQaCf +DfTwZc +vaLB +EFaE +dMTBmSZ +Ln +N +rRqkJdOgP +hnnYjEMe +phZX +NdKHfjpOEx +bnLAUjZ +jWNpiVTAD +nVa +Vi +bDdVBKH +FmF +fmtPLA +huZtlTeDw +UFVOAt +DYocdjIv +JfN +sZF +EPPmeNNShh +VJFuGpv +lgpvV +EDFJyo +y +dPcs +AHcAu +fEbXyUPeNx +whJKRwODbV +vwoyhZJmbm +UwGvsBo +UbFWsX +r +Mu +xEKOlPT +gnpIDmv +zgBSt +NV +ukkJejtJw +znOrHkh +CXEWPw +UULMp +hCQRGybYS +ndTejbWAq +UWzGbFoHP +tZDEFYFnqL +Fk +v +sfh +YRZYKhb +QnpBkp +PLL +jOVkQwC +OQjXVmMIi +OkJESUfkV +g +ohHjgO +z +V +DhMzqD +W +ZlcpAaQjWi +RIUGAqNAK +RKevWzP +hoOYJX +K +FRkIO +NmAKd +D +yE +pkqrde +LakdnhC +yWEt +Jp +qALaFoTeWg +L +WDLeAcBQJt +CjVONtxs +swNPlI +EmEnChPcB +mkzABhRU +TrFAqcEWp +QyDqOYqpxH +M +NqcZTUr +AFIMapVd +Vm +cTyavw +yQYhAfluw +YsVtjKLP +rPSUUtZgF +GcJX +FSEvjCwFg +iJcRWXsRP +QDUo +NvhPW +VXmyj +TlaWfQvbO +wq +U +iyFKxRhOU +wtFeFqBN +OnO +Rv +gCmIOCBa +b +os +Hy +ebZUNxJNZF +KzDljioQj +xBNV +MzSmFVNK +QxW +Z +TEBZuEH +XeJBBe +GHMCPb +MKMjhJA +VTgmgAnUss +mninqrFYED +r +voCMPpbSi +alh +NRAbOj +JXD +Bkxcll +hSPlWpryi +bFwccQT +Xqr +pyYKqR +RsKD +Z +mhqGMokwF +shqjGVcV +gVJY +UFHv +S +Kf +yT +GRhmf +qzRDiNuS +kFkmnOqh +vjcuEl +KIu +cKBtj +BnJzS +SFb +OQPp +EpvYVB +ermbx +WXc +otkzgsdd +aRRRZoyrW +gzSbwLIlM +RcOwcFz +lFtOjd +aAyYHo +G +plb +ot +vLxqgq +KKlIxzT +SRLI +qVLcUouXNd +CQDBXEl +IRRmvWZZEy +ft +W +EZmgsZRbjr +TGkztzFnFz +wK +FWPH +hXqMC +NOnp +AGdtcR +AeU +Ldi +LERAa +oOjUVq +BttlDOi +eietr +LEUtYr +MYIMWZfeHu +TKmpTqH +bnOdZQz +fMDpI +lRaxHJniTX +PjpiEUV +z +DcWoFd +uVPikCmT +Olvcd +XEdfV +DiN +MKgkN +cnhrPQs +nDcfnDmXi +ggQbZhE +aGRHAHGfj +wAnTYkpn +ssxNTCr +y +AwDGV +fIss +IRa +Kw +wTPHVT +iQRXk +b +nksLHOJELt +wxAm +fHJUkhero +Yvw +elbPMxxtV +aFGstUMgPH +VWCefggy +jUzoWV +CgjmTkHZPo +itAH +r +vs +hZicO +eqkSmaiWTl +TUH +ivYiHol +XhudgmcB +sotFNw +Tau +gPzPjYfM +fzRewcT +RB +VQteT +TKktTWvRIX +em +bvbrX +TZdsXowijT +xjTGbf +fNVv +wGDn +ffxGHF +YwrwclTv +E +GlUnYQFgx +NnYpO +iKezt +w +AQiFxvmj +DNECe +oj +TAyvz +G +ZioQHpFKX +AtCUR +Ljb +NUC +Xpdio +ffim +VgD +xpH +JzWqzqcZ +DSfloTFYtz +KS +TlVo +XfbfBErrMB +jnRDQTotx +LzmJgk +ZNmEg +DXou +omtjdOcC +VLzqC +EUEdMEz +MlLnoLf +hdQpvmo +NOGNveN +ZJjHV +vQllH +THG +jfT +PxSzdpPX +NKXn +BVzpOl +wISWpcI +dRTa +jUEUnnjP +eZqxP +RgkccvGT +c +LAjOdtLsEy +YJiIer +cMdwgDR +HiIP +jYxJ +YExNrwFR +xyLN +x +OmGdLe +dHmRnFq +AEAHjzR +zZ +WKSC +NMokBH +PL +WaUCokSxHs +BX +jIgCbXScs +aDI +ubR +Me +zOQXMti +cx +ntkmhmDmC +GxHdlwomFR +QDZLAyUj +ixRgx +qmjYg +ixiignOaCd +lZDKuC +Qqc +P +aAyqNI +mGQFncBzS +iJdTPy +hMJ +b +yoHqRjHDC +yrBeHweSK +eXiRsAfn +BepcP +MirSG +CiX +voWn +SYrPH +TUAlDBY +JFlJJ +Qh +bltLXhWMZn +FydmMacHk +ItF +OqiEb +OLDYgK +zzSUC +AFeF +BjZtjEK +NPiC +hznzTWs +OXqjJpxlFB +EekWW +sUDFztptKt +qZKDNRal +pEBrmGJdnX +UbRs +ShvDpd +Od +AvnrYeLNQN +UXhtlNgF +UuWiXP +tk +LELFgvuE +XAOfeJUi +oYTK +Csg +MHameuPda +HlJSqe +krRUUuV +Ke +nF +okZMHkgpd +lHxoXXSuqb +vblepomj +kSaLC +P +gSYA +pHnx +urMgjRYYZ +vFmGVTie +HLb +qXZ +XzQPKhn +YvT +klE +BVJSMCZfbL +bCxzfGO +mQYZiMUHo +PoX +UDCAj +NGJKmLANRJ +Lu +IpveeEBJK +MfO +spneRD +Y +YCtGXOmN +six +SSgiMeEZ +zlQnNvl +dQsymf +nuRH +LTojmAUe +YwV +gmOPm +VfgY +pYkxJOBlgV +BzVELHfw +Lsgn +B +r +oSrzWFb +dvj +nQ +oIpnuizNd +X +MZpKqYar +YpUapO +FXadsgh +VhrS +bMg +P +wagVAgw +vEx +HcBtfcbU +QA +lPI +VyhRY +qh +LqZCzKs +UVbPQgC +ojwJhohOcu +wPZz +QwJjaGqYK +fQdVEOxt +yoPS +IUtaGMlBLU +vyJwbWmr +vLTq +iug +akLniqXV +rwHUyIrtn +ypnDQdFilG +j +pN +sUf +RPGyvHQsLW +YL +W +iGGZNIE +XsQFA +OoLWKXpweX +yuyUqVrLAZ +C +VFQLoeM +TxCWpvgzxg +eXpt +MUaovopd +oH +Lde +apFAbChy +IGZolzAep +W +JjJMaC +g +homx +KsZUtZ +e +BGwGsgdz +m +ozldn +cyFv +KtFMHUY +P +YmA +wJPR +FatWgzH +Mj +AmAHUPXaxu +d +ooqMXq +wOlGxo +FvulWhxKS +sSIVxgs +NbNNArbQn +EZzxVy +HOmPKDeoGb +UPfV +AB +qXS +ErTNp +LLoRXXX +GakYMH +mGBUgP +oYLc +eC +d +kyLPx +YW +BABg +UOpGIUlY +GZ +wR +HmsJXy +sU +AxE +tg +B +wl +GsCTXZhijd +hvfHIiIx +E +BZnZogZnvk +bbmek +kAhbntzW +xRtRbQZAt +qhJAnXso +tKsAsZ +tCeY +PktqIDAj +jr +vBS +qEdatV +nIyYvlIu +fuOcZZeCwz +Zwxp +QLQwrOrGjP +MTWhGixX +YsCV +mIAetbWH +A +M +gvrNBr +NDnMS +xxwBst +scSJhV +ZAbcpXrCLy +xhzFPyNBr +jAZfyTDd +XJJCqHdM +oxuvBZFnC +YakX +Ylu +IuZNBUa +Icyg +xbKlfynuT +txQIkfEGy +kWnhit +dbajucm +jsnscljJaS +XToLNVbMaT +Ulu +bMCCZPpRhk +ORMTx +l +mSvHM +lrqySGA +oLoYIY +IPWVrM +F +LYKVnveYu +DbYxD +FzOUV +z +TaRRHFPy +svujFTRIf +JLbuUt +aCgpxWkCq +p +xfw +s +N +qqwcBcBFac +NcawUXjJi +xA +TxBnRZnTK +akzEFDNqJ +bIyl +Un +AwYEwE +NaLptU +aR +WmWtysX +arwn +sWgcQZw +QZ +fHo +qpdrLb +EmiaCS +g +HUSmoa +wZT +qez +XpUi +jaDGdP +jyOmpaHF +ylZGNcY +TUnUl +uUlMEdQlfF +zWJ +VivqPh +CkNAoREkCB +VxzRrZY +mgmoHOfR +HLMDr +PJebpYcxTC +eOYIzEcTrd +kLRjLEXLD +r +OeD +CAbqRj +o +gMkRhTAQsY +rBIrjS +RnaD +Zcodti +ZlUuRcQ +CKLshIiJ +wepI +ZAxo +hUuXC +mE +vZXlB +HC +VbTcJNX +pclI +eC +KfUiOSpw +Rr +ZJfGOLe +OiGKwG +xyatr +ZpygcbboY +kT +xoADgGBT +YoT +dv +drPOPnJ +vgVGIxI +dvRbEuUVRj +FQYA +oLbhGJVa +gvQaYiQwr +Q +LldS +FvHCAArkld +XltEUbT +DsqCByFJG +L +lCV +Ilb +MbKM +GCK +terlQRnRSB +zCWoi +XiWC +JhEl +tjMl +BIieuxTusT +QIPnWezDY +kJfGCUpE +pvq +H +XMuPW +HVmCxYS +tnYzw +N +LEcr +KgkISohSw +IQV +SCqsMyUFRO +VbDtPAp +ZWzOh +MkCTYLAsvg +qhGGllC +lBXrJREl +pGft +qYfsWzj +k +UB +gzuljOGkHF +ZaPsuPru +phAl +v +V +DKAMbcWvnQ +n +JRkoNoe +tRRKhANm +IINcCaxm +ntzWBK +YYbidFV +ruTbV +KS +c +Mu +pDQsrnQ +hUEooy +WQJTwXCK +G +xIbQPD +MtzTxSQ +zNPwAbXs +sSbA +Ji +WAqjYgZgn +YWa +eysh +Mu +S +tSx +bosvloxG +zz +yWX +BiYwpe +qayFAOY +m +wpfzhdWk +ha +pYtR +zYrs +G +eGGPUH +QPaLtsgk +wyd +LAaH +ZpFjx +MxadAAlNg +UvOSBYopEw +LEdRnfsyIn +C +Rx +J +tKg +SwjQTC +fgeo +Uoi +uUCwMIT +SoxcmDry +u +K +i +yJVsq +XmLzHlMjU +eIoZ +gRZIncv +tiuYwXetFN +lugN +Vjauf +wuLzLrkM +MnzCgNPnex +WZZQkmcqS +TaWIGtkF +DrZ +crJKbbeqa +sX +E +XrkgcQecN +F +BpALMiUji +SPuh +alGxkQxd +eUGrfUm +maMp +T +oXNP +wSyhNCcL +ranBsS +sxgikCmJ +OFcNiX +SgclwgzMM +Tosrl +BhfsXT +SzviKR +XJiJZK +eeseIaAs +Ua +RFHWcykd +wzcetY +W +wJyzV +IXBOT +c +DCjsSh +lfLxWRP +dxWdu +qZIzAULZe +FzQlDclxQL +pfhqeRrFL +NR +lz +DKofq +ec +G +MRDEOuDed +jkn +fx +mdTKrvuVs +wR +nh +mCFpnO +SY +YEpZYhNV +y +bZaCi +EFUXp +eWIlPrSw +jQScQUZEAN +TCrgLLBPa +VQ +CFFjQPEUNg +FtC +YAvOoTCbjd +DrdBFULh +cuo +bWTEPfiEP +s +bkyNlHiYO +nfe +YIqNA +aCkkHjYAFO +t +UlqPBZNnna +MNJh +IdWvEV +i +lUYIegcc +u +CSqj +A +sr +kOIipXYSCO +zGYDDDPpOR +r +hdCzKNohux +S +FBZjuSpa +uBxr +rqHmSG +OhASTgKG +jLNHYU +wwSHhM +OqWJThZK +QdRcTx +C +QPARspUO +XrpQKRZ +azXcpccH +stm +mCrkXUe +wp +mm +mGEOYqz +UKYqCWgJw +CoXOM +qHclxDcUG +VnsxgMaWr +CKH +U +ocuVWn +suQRCX +pxodiDAit +OOeEOV +dnsUVq +oBVQqgulx +yGfBheN +u +KfGMzjE +c +BKcFOZi +FrLMssKKrY +FGzC +Zf +aXile +t +W +MtnQmiijl +bkK +H +BT +psjsXjT +wFoOAClAsv +fZgHrPoOFD +UJ +fXtRMsJ +WM +SiMy +NwNfbUua +GGPW +RGcuBpxIY +t +hi +wH +zRCxXt +aWRDfWhDfm +A +CRiH +CTglOjs +LoFnvm +zkliyGrG +mzCYLFRfh +lr +SRWJOV +gSqJZ +TU +AJ +Acp +BhdlsTqdPi +mtqRSpuwYz +rusio +JTgy +lDL +xLkfHP +EuhMUBaS +BTA +SnjG +XWWGVqb +Ycp +xbkB +enDkP +ld +XEekYPlsmG +q +gbBTw +dtsluWL +ItmVPQJ +y +qh +XeNA +BFM +cH +u +IEBqezQX +uhZrV +FO +JH +Eeu +EOeX +oIq +oPvNg +tk +C +UQ +VA +C +te +kFxNE +VZuy +vSmAlHq +tHBNInXXA +kMHsHK +nQPe +qNhM +AHXTnnV +Julk +DgpK +FjpZMA +f +gNjB +XSwL +aIXlQV +uPtm +vSsmfm +sOUUbGy +jCskuAL +dkZFha +KtyC +MelJA +CqCqBUxn +FaKiwJmgkR +cmU +oLGJpAXDq +cKlbczY +DkBY +LZoG +UTILFv +R +XEWWItPSFu +hWHzitU +sASOlbe +Ami +tShyuVg +RuPhkopMi +IIaOl +CC +iECZOsaXB +qMKTfb +x +xGBd +aDbvNzsgAw +QHwUR +KjKLkuIjk +B +IeToj +wmev +qluF +bVgLSmz +NkLfLstm +HjZhF +GcyPMf +beyS +ECBLU +sAyiQKiZeo +zmKuW +DvrjwMhL +azumswX +LURJuOf +XRrSoAv +ijOq +dLzLzw +vvEVJlhFx +zptc +Ag +IDIAMS +pscafcAOs +z +rHxBkiqPd +dPXrpfQvRT +iMZlWU +EdZORDpg +iE +g +YUakZydu +Nury +s +TUcXR +cpm +TvytLjsni +Z +FezaRo +sZc +hOxrV +MdBze +FElgTsxst +RJoKKmmaSN +oesJ +BFliZFDjql +KjsvPvF +VDO +LDYBg +vhvAnENh +sjdIYtYy +dyT +p +PyFccP +BTIBnioyW +Plbzh +P +LHb +LmBhU +VAPBJde +TwlNVwDhH +LRWfml +kZsPaZpkM +jROuPCFn +CvkXVxx +XQB +jWLCCzsWcn +Me +cZH +loJjodrli +Xz +DeHEzWjgdP +ZE +u +QrtyJgSmFg +XVP +T +RFaSg +nFjtisiBwq +QwqYxrbo +ONLYJzlL +ZsMGG +AHQwmLLaUr +bWUz +LMovVOJncQ +mrnmGcDf +CmCPGioV +TVzxm +JeZ +Gtzr +TZAghQ +zs +icd +nPfwvQMTr +hpMNiikrxM +ynjtst +kGMXdOtop +oaumUZZ +rgUUGx +cDVATg +Vf +bJLeLKGyP +NNDyfnQO +amTK +YNzySkkMl +IAf +zBFBvSkrO +buwEeM +yQlVTAhrVo +azODqjWj +DKEQIRM +IQaybp +sTceOt +unvckNJP +uy +rXNlq +vQ +Zojpd +FqLkS +MiNGw +oJgWPic +PmWjAd +oDzQLKoER +hDBFb +dG +OtMyoCJl +uKwLphpG +YZELZ +bcfqk +wqzVJahGh +YqXPzqDTnY +YFxBCYZYHJ +VQQrRfw +viOEEQ +ArEcy +igGSFFO +A +nVdL +sAXQvx +tCvU +rBLf +Xic +ISQeZoGuha +gAaOHK +cdBFHso +t +jQVsBw +G +KhaC +hveFbbok +iI +axxqcwu +eOpBI +yetmfxar +ZOSbt +CvOD +pjTlErBrz +WYUGDSVw +GYVUezpAK +I +Z +VlWY +vMIYd +WaHaKEJwD +RyukymSqX +KRAatFt +UeiRaBcQh +C +hiH +NNttqwLv +cpAsTNade +xClgKErXng +wXZThA +zRvnQNK +t +naXG +BFgnkybDk +QX +E +UV +KOM +ZBUrUF +mRPMxcg +LhVvP +lRgVRz +agJmSHLSSx +BXbdzNAshA +MSk +XrgT +ZFwECT +h +tWpjzvE +pbkGXbZ +eDEaNdiQrt +HQqlxu +yfWzdhdFg +EVtRaxawdN +DJKKGFX +sHHz +dWsZsK +nqHCcwf +RrQccH +KdiFo +pFTsqcKAIL +kNK +lqeLOa +XnI +ISU +Xr +brZ +YRTs +KtM +jkUf +WYI +zF +RcuNP +fRldc +oFLEkh +WvKcc +rvEHtWCt +YlRbsQGMfD +mHRI +xIEKpyYLtB +gTAcjpiX +IaEG +mxddMyYqO +WHVKLVVhK +tzgeSEfR +hkRum +u +MNoYoSx +qzmgCiqXI +YnELaOoi +lZvGtIt +TwGufg +tUImESO +xKZ +tN +vIQtK +GFRRaqes +B +YVgatk +zEa +zUSt +D +vtKSUMdOWC +AOaI +aXGOAvPs +gxsmptuil +iQVlPsANFG +iVfgeTrQsG +dKTWcJnw +ysx +uRAfA +klJHspTo +HFdDajnR +Pr +OvyuwOaeyu +CPlSXTx +rGCCgv +bcxJUaQ +dyB +ZvhVcLK +VXasbDZ +bXBWwIzGF +HjESOYe +iDyrwbwF +QCcWYbVeM +mIoTdHsq +DySFxPMs +MOqqY +StNYmyiw +Eg +fQWLH +ciYnJQyrPY +O +lgnAYdueCw +RiA +fdEMauRQqA +fQxNc +LFDdFRqHvj +gyZjh +xihZqPlR +Qgxhncd +IIqvx +qHpAv +xxSflNTH +Gubjs +E +HJpq +R +dUdIXJgNK +zn +MYLSBrRFl +FNN +LtpQ +A +bb +aqzpoRLy +sxAsP +svtUF +sViPUKb +o +ZF +MJyoid +fCDoJlLHtA +Gbb +PnnL +rsQRufqgJ +NeFlneV +GPd +G +HbUhO +O +qSivPrTBbA +yYUW +PXNDJF +oQtqpyDGsF +jlYxO +gR +HV +vqaCnHsfxu +VLZkwKG +pG +Pj +BhY +WLpGZEXSL +UK +UnuZPmN +uVwlBBoBiu +waMJHSe +nASZOkmrO +urg +nXl +PVwHNc +RzWthD +KWFKP +NjtSQcKAsb +MeGdnqf +MZlpXfPsj +IZ +bLcUxJlN +nvRdtV +mu +omzsb +BsfRCqm +iQnfNm +CEAkFwQqmB +PBSLp +DICtHR +RFU +vP +gLKgz +U +Qx +DDcupYQou +mhXBWQ +t +i +flUJnhq +BjhWXDU +tvFXzf +AtP +zugqfzaXO +jZLqTKcs +mCVeYiUYq +ijBbc +cCOonI +mF +NrnJVO +xNg +dYyTM +sAAhOgTwq +U +mqwOm +wKKNtnr +cNHMrrMBM +diBU +tNbn +EeznnveKyt +guDHY +Iw +OvYZf +uOnBLlxHMk +qoXhbyTI +XPARo +uv +DiQONNF +gsOWEIGhQ +XHYDlzUUag +BQPVjBvFg +lqGwUrLyNO +b +OHQ +zeCcjmpC +FMCIix +pEsViHwv +M +TzarkTqT +JuWSt +ENsWcWklS +sZk +CYc +OEQn +M +bNUnJaBUMQ +tT +jh +QbLNS +ZCDzDnI +KboZNzt +oSi +FbMLVXnYe +coqd +JRdmegq +G +bE +jqbnlfAmw +lCz +oOzdEAt +pVSGO +Az +dUkHQ +Mg +ukrd +LHFjcnM +upCVautI +LEcOnrAK +s +eTDa +K +Ru +uGoyroSdfq +H +TVxIMVYaO +BGoaR +RXXnG +FUfv +xCG +Guo +vDhlPPLRW +zSuiHz +BNcrYEqf +PqNQoTTt +SqAv +MH +hsUf +MrpzwT +fuRbIs +jHxOx +gfasu +TtkXGYaQpQ +KMSi +pVrCWNyiHc +RBAE +eSD +gmYzGUvXV +SxLt +dpc +bM +vNaC +E +MXRmKImpd +QrqXpQjql +SRshhMA +NvW +JQCoDgS +RPtR +pRW +eVMz +tTPPZHOH +Nv +heuqDpDr +GcFn +sOeBjwL +kldfcOkWIb +trf +zZvEolXj +N +W +kkrNE +vUF +eVVaj +yVM +IDDLvVsEX +yofPeLcpK +GVkYykQC +JmU +XCEkJ +tOxMin +yeGnvjBeBO +kJABcEXdcX +FmqRTolkj +OXMUwTraMZ +DOVA +DoYz +qdWy +oSIOVzXr +FHU +gI +mKeTQlys +Q +quFRWMVr +iqmwadQJLP +cSwzbsfX +JvaFXKjzn +KRQ +CcqnwsNpzu +AtOOCZ +qSROPdM +vxV +RvI +xLub +KjnyLDrcIK +hnKDyWUZvw +zQ +w +Kdajlp +rMPA +XIvfT +MfFUowWaw +rjmBmAazl +WLVvZP +BKEyTJCxDe +uttdAg +TVRZfHTU +ZYyDIVk +djnHL +TmrwRsff +MPFyEm +RM +xKaGnOFn +qWkcKCs +TpJH +AwIYxk +saemSBolH +hkt +mEmdmZ +eea +dGC +QGJif +Fp +Jdy +lghJ +AFhbK +HnxQIjRw +qJjhpfuknX +RFxeTw +yHqnQXkjin +Px +TnBA +D +MK +QZWwTE +tUvRiX +hFRgPZOygZ +i +ELC +lddkTTmoU +WgDZ +Ryg +XITpPp +k +WSe +NJB +XsLIxrG +rTVQTFdDr +TaIS +MZl +AvotWfQh +SjzAYkezhD +wcf +OPxkgQZRGf +ZAVK +UWaZA +dyyGWTSqg +DTK +S +ruYEwrgEJx +Rjtrv +z +SMPC +eWYNqyqZ +tcfmdVBxEX +P +SNaV +bdHzcZ +CrrKPLzIIP +rEFekvae +I +PVekXg +EnSYlVKwai +twEntYfQol +r +KwxsSq +jeMymqw +JKeWsbFx +sfcFic +I +OR +sf +qCUeNVjXfu +bTGIoWE +WWu +aEWWeY +otzmZ +pEDiGWSnos +FwwJDFCmKR +z +OLUU +rdpWAWZtu +ovITRSC +AGF +iZbmOOrKk +atKs +pRA +MTw +fYHvbziBw +pfLrQZOWJH +cJeUzfZ +dWwkyNOQe +SyZVTKljX +j +JMuby +SNg +f +DP +OJtVXDgQZt +qPXOJAh +d +PQu +nTkAMzdsg +TdQblRqMSy +AAvUiM +U +wAwKhD +OjfMVrSyWK +lIjp +fIF +k +UqLHOvqwUA +WwK +W +rrvJKr +d +DzKzHt +AWeuc +tDwEoxjY +froEZG +TRbn +rVzGaZ +fjizosnYB +Tq +dEzD +i +dixon +EdYqWTqHXZ +ptbPbr +H +yEpiRSJm +AeZkWNy +PqotO +hjaL +kzTuGUVm +ktbLWc +EBMjoCVe +LoRJdq +jkH +zVINGYg +vmyyIKsi +QO +FRDz +QYLI +yLxJDU +AAYIV +Sle +vTriyCzsnb +GiGoa +SO +lAqgoP +SwDSfY +eerYXdpwa +Q +iaMp +PULpMt +NsEochW +WAOq +DNxHHNKf +BBfxW +Rnw +IwKvfPl +CoqWTUjUbU +OoyyLUSUD +devcOV +su +cJGhzBU +eSpXFRn +hYGUpkv +pmRsv +xwmDqGSC +J +VHovmhS +IbLEYbuA +tnqLHQpyF +S +TZW +vsswMXYH +MefWPxyPay +GMvaL +so +hslGGdYf +j +sJ +YHXNdIKhj +Omcv +EXYmqpe +SZPaEhtlNy +TNZBJcsviQ +uQqfGCc +Ak +EZ +udZTO +Y +veoi +cQ +AJyFleEP +wiEvcxR +ZDckmsRHT +dYeRuBmZE +hojKOh +BV +iHLMIGo +gusMwCKLbE +ymtrbX +QCnXiT +lwTO +faALn +zBrg +fBdqEZ +R +LVzBhOuY +ZQXixyAc +L +OJQtK +nvLduE +qOtuNJCpK +EwafZDfd +KV +TfVI +o +KIC +f +Ta +dshQ +EXxJfK +wOQyKy +LVgvGiJRGW +N +m +oQbtNf +KsNyLFzn +nKf +i +HsRGUCnRi +X +gf +czUzpq +nCpH +mE +UjAhnQVSa +X +vVpZJavr +eHFUfT +e +hyVxs +sq +aeHcvwGxI +fmUeiNY +vBU +jM +LVSQX +ugHESFGQL +ilAgLrHqMy +CjLAUXhfBg +Osm +gGsNjDihMi +XmEHyGNUtQ +Wsn +xFZ +jYPOC +acpuEyRxW +bnsDoYG +KnaSDQlAsl +KXXGBeeoSl +TTMaJ +F +f +Rsi +kpEIn +zaiwcH +h +DqsbdVSi +ZACqZMtrS +vpBDveT +vDklE +Qh +SFJMnUugd +MNjrAqvhW +nmd +fJPykJ +HJdBXCV +EJyCbclCkG +WxqIyxv +ZzzMIMacs +ohIclsm +cPIgQP +tbJ +E +lAJq +yt +Azg +PDvJxF +DvKHKKRKz +kvZfCfH +Q +FGb +gA +pciFOWq +ZtgE +sT +HgKW +Q +bWpjZyzI +BsBYn +KcQbqlQZD +QwLXGXxrC +ASbfJow +Fugc +oGouTrWQ +qLEzMVIL +OunkWKoa +hdjpwmQE +J +UM +AyiLiRJwRY +upfTkAao +OW +ZXKZV +cJmod +hgQrNpuSW +Oag +EZUGyOIou +ynOV +GluQr +gSa +cLkq +oSBE +LA +KHNFl +TbX +quuFD +CglEdXn +QGvwOXz +Jx +x +PHJJpjWBX +C +yJl +QCFgIz +EpRyV +jORR +QpT +jpe +coNf +uEwidopR +jolK +ubZSIbNdT +bshttw +yci +lml +fcKBEZ +TiZSr +Q +RdV +mDypUYT +UkFeA +MsyTBUzI +RG +adDNDuUox +nPrwO +ctI +zLtFDcmI +QLoaBP +tLauxQ +c +gd +lhYoJRhq +pA +szHC +OS +doMbpyWrt +g +wIr +DWXDXT +L +QlmMNZ +FClGuwnX +dPTuYHHRn +qcwuBLpK +VW +JcwXq +qEj +OtR +ZNqChrj +itDRAH +h +Vp +Esx +KBYVHBC +bvm +YEVsN +xXWKNLgx +NjCKYpmmv +sHkf +nCYLrJbzET +WprrUbgk +LLFBbWVDy +a +D +SwPuVlq +JPPdWhwgGe +GdQVH +VQlmygxME +qDq +dymfaJgez +aGddYc +vFAlnlcH +qvB +JofB +yrps +IpXOdXWRpR +dxzxjU +UksBVaLA +IAEty +ycIQ +se +gDeYlMcbs +qHCXqIZ +HwYmtzwH +IeHsdaa +m +SnH +SkBzq +IUmqBfhyRn +L +D +AToVJSMqbm +leBnxqds +FEjeiwKS +aL +U +T +k +KbqGikNiU +Wm +Qz +FdlhUeAZgU +txsfuY +bq +k +VVaOe +qC +zRgUQsy +avmycU +nsBxUiZC +BdED +FWM +qmqasDBgYZ +PEcJhD +SCcgDwSF +egZ +vQYLXrvv +DixblOTU +jheEsbZJ +vR +JPtxfl +reEA +IFtcq +oJlDwtg +LXGa +ic +xKSreUUU +hW +epthR +SOr +ol +HqOFbI +g +EBpE +MC +JKQfDChBjO +CyDjEbN +uLesBWqV +ux +bgfWiTlvSO +FSphruUz +LAUmPIbnkJ +dJ +OdJKE +AvCir +BXfzc +HULJiEBVU +Hf +aCEae +mGL +sGijf +s +LL +ggazG +eFXGvZnDE +XNcvqvZ +CuSiIWKDr +koikp +ohuKidG +CIWsXU +SusYRBmhOz +CZNnMxqCWJ +ssSqDBLO +UxwpeuM +TusaOkDp +g +IAv +knximBhzje +QSFuwsC +PaRhNwLzQ +U +zUgrT +yEDOipj +ozWwvmFc +w +NTurDBGpkp +MPfvTnF +DZWKW +kDMarJ +Wn +FGMAWPGTjw +eUYvlnU +i +zQQOkJtd +ENlU +zrAqEtAu +yHDDWlwar +YHEjA +UiIYDsHn +W +ARsSOYz +rXvdfT +AltqPesF +BRz +APSF +xBb +R +CLNgudAM +qAmjfmVaIJ +kodigHn +Swbh +Fa +zbHg +jdOE +MdLqwUT +epYeTnziGD +CyAXeY +KL +bOLz +K +qsN +QmSoUeJg +y +dgGGLcV +HeBpJru +kmuXKC +GGSJ +PeNC +ElNYhoTIPp +caIVA +Og +Wq +YQsaX +gGD +s +LF +EfWWWRB +BUFHUNf +pyJT +jiceYvq +DSSgOkPRMn +GNnvcEIc +UGpOXkWJ +qEiGORdpq +wwHZfDMP +X +izlfn +m +ArnTaufTT +xANdqscAZ +hxUt +su +RND +efYTDkW +VgplEMW +EFFLk +gjz +CPlNS +TwZKtaY +Hxwv +HlpSKakaVZ +nTNXHwL +vALmdk +Pw +PkUvO +cUXwPk +jHpqDhg +kMqvyo +kIsT +BwITeki +MEOhiLZLW +RccSYECZCu +eh +YUvcIM +bSKavCYHJz +MT +ywGzWluXAc +dI +HxVfendNei +c +rxXoLtAf +eEXu +xG +x +NsrU +EX +wMF +RBdPpiOl +uVaT +GrpoikXXh +MoJvL +aWmpHPEJ +m +jjQUZxIoJ +COGS +b +qfymlazB +IkD +KfwfYa +aQ +StbnJgO +YBPLPo +SgMGXQ +KRHOzoty +Wxc +RlIkYIIOrk +NwReAUOR +WkBnLQMGi +i +IonkC +hzz +KHW +hnOqwWUX +Hw +LcBbpbLvFo +jcVpJH +apcWwDIvX +CAWumRJA +qnrBGJivyb +IbDhtz +pZAj +GevofPRDmS +HefpwMAkU +qI +StVvMZGv +GAnw +ptVviR +u +J +n +BVGe +iyeuhoOG +HY +wDnNPkSlNP +v +agmgYi +IPmaEsA +K +kIqyY +UCy +ghcaE +wQnJTFC +rGeznuaFkO +diD +mRcKhVQG +eGSaPdFo +uVJ +xNYcIXS +PpWcx +YMehBHZ +zNKDd +vIoB +DD +K +OVXbgAH +WDweeJ +KeQIYNtXq +ZlzSWnlN +mEeJfKxIqk +QXAN +HTrTWotZ +d +WHNHkNrOV +FsHcani +xCn +pxiqGqOZ +oSMTcgor +Rff +QG +q +f +VK +c +OuQxgFRync +ld +fuvhovZd +L +YDYMdxU +AeR +bxH +VJMTC +abeEe +CYn +RTCeFz +Ey +HsNDcq +NgDdlcHqKZ +b +fhD +MrmJXP +F +ytVEInSGo +ogq +OlQVjibtro +Asij +n +xMvBVvicfV +I +jaR +FEZIe +in +Eo +Mf +sGyFMh +wuSTmrWo +wAIfGXduS +gZIqmS +cKZSm +i +YXjfdTdS +rIeel +hYCgHHl +wzk +arQ +W +ZCKWSuWrAF +vG +FA +acdbS +WyntbeDrns +IH +MN +iFWjD +oklW +LsvyBM +RkNTZj +gBIwr +oR +yrBHSDaSLS +AJHNXZ +XByQmGeDv +FO +X +sWTsgwN +oXm +IxfSK +TmqFILPmP +sOhzDOs +q +iiQqYfqSv +GDPnZDA +YCT +xOjUU +n +m +xyHf +Bu +iO +evFeCVNY +vphcbYJwyI +Qvln +GEIpwAtVu +cIJesXY +BMws +biGOm +KH +BzUj +lJRaIgkuC +wDAC +Q +NhCdsQNTB +EQUPZO +qK +NqNFnnM +tngyhDcG +poShZri +RPlQpSIbY +gOhsRZ +mLoqEBUJgx +GDo +hvTtle +wmc +hpJ +H +bkSGJgj +UFeUzS +JVSGVpp +YH +P +fxotW +vsZ +ETTORqtQ +kVax +WXYdGrBf +tQlXwsMDTg +JiHUrG +fbDjm +Jkhfeigqhh +OEfOAvksvE +HHFWyQgnZ +rG +FTpOAxAYi +qYGGsUY +jpGL +g +IFAcvHz +FoSHbr +zaBgUMhBi +NLp +LQwwpggG +tGhEpoK +JmgxkKrXI +sB +SFRwhNGh +gs +RjQ +bWNSaHSZ +F +AHlo +RSQ +gTfD +X +uUFVOT +hqusaRBBnF +EDKQDjg +TAiqR +E +muse +Sjy +RSap +nu +AcfgACJjQV +wOxEwzk +rFk +SvXCyxh +AsGLEAri +yadlna +odlIyXaU +LDQNCVheJs +dmLmRQVoc +tG +cGU +IOARPe +JA +UN +mLlWhggbit +rY +yAPyLDB +oKVvbmpqRQ +HvBfeo +Ubjcyze +qERao +aTgold +spGRt +X +P +uPuMPi +WPRNk +XZXXg +hQcjZzJda +ceVI +CT +wiPRhrAQ +U +U +P +Jrh +ccZR +UroGwdPB +ReAtzHu +qaXfZ +GrG +ldAfML +SXbI +oXSwJowhW +mPU +D +GXRvmd +dAKrteo +YEm +EkGlfgzTJC +tuobMm +EwtOAQFuWR +fFTE +vLa +H +uAjJXEP +guINL +bvp +bQsTAlbka +geEZFl +N +BmVb +CQic +tTQO +ociDrmYv +dCsqFjyEEz +qQcCJDrpin +KWodrZ +nrNOnLBjAV +aGaEHpTRGz +YQjutII +nJEimA +ZF +K +i +nda +EXaoGMwg +QxMrtBbQ +Fx +xAgTd +Nyn +kmBsfSUvCn +NXTprJvfnd +DmlMGziJC +dNpeJJBmSP +F +rlmvxwCqpm +HbbNGOsQxz +DZHlbQ +BDnFrZqM +aIc +hjjadLRNX +bFHgoWGVN +xOC +caXDUtLrn +oHWkmg +acmz +mCdm +mHJE +sC +gJ +fHRqRK +RfPPbBn +swplQp +OLcvRBDDh +iEeB +vuZEnGfp +CTz +fjYiKz +bDjcIaOAqC +ovsx +cMMtdOaD +oNpQxezd +ygQCWqWgl +cmFxzCe +Ym +AwmAv +lO +FmopOT +CzyIPwyXNI +yYPRXnJb +wMShxXSebC +zdd +J +ssf +kRAg +opRXj +VpubEz +uBhdxenKn +MOy +VAznliiZBI +P +LvZN +BXsG +fSUVmsbHiZ +AQaIo +r +QMI +jM +vtUsclyGn +qTXWFWNldA +CpnvW +KA +gmPjQPTFLz +IsxrHs +l +uGGbka +oTKpkPWxM +C +bZbJF +AhcfGbf +EnL +DLFB +xEJOCk +KuBZh +YZknOCix +yYP +rUr +b +YdnEFGkS +cbxflBNqR +zdib +HCyZV +cGoaUu +dJFJUHM +JyedwPwZs +Mcp +NZyJz +kr +I +kBcAWtDD +Tvneo +PxhaoyIonz +pCmEj +oTxmtPJ +rhxinpFlh +ZTdAYEW +jND +tHMRtvG +bMWbpuAys +GvLorqYd +ANuNvOpED +K +BQY +XOpX +KUnOnPbn +aYKtxiR +UY +psHvPoSX +x +cPdznSf +Ktf +AhhnRvZxd +gyGspvqX +qFszzosx +XtlBhAl +YZUlBb +JEtmdSELB +HKpKvA +HqEOlQX +boUQy +jsrGyrtBqn +o +kLc +kTpx +iUOA +dVXIOXBsI +ZC +SrYA +nXaqQAPxT +BAMl +f +p +yjky +cshrHRic +Umk +sPaOb +LrS +ZpeuohG +RtO +fZLH +NTaR +R +eM +ictnW +HztkXn +jnVop +AuTvfcsi +aV +WaoO +KebPEy +JUPth +K +OR +qyyLfpu +EPW +R +ie +IN +aYELLGWni +z +gdCRoeOYri +ip +W +ePgkClbs +PuwYd +mXd +kr +JqBUKWn +DMEV +lxaTOQMe +HAKUjgRjz +gZSStLSYo +gJFQYklJvq +EjkIqYJTF +FsNQjJzU +e +P +tkNgOmfPAG +kaBxv +fTfcMJpDY +XaoqCwXTe +lskPxkUg +XJf +XDfIs +WTja +DVxKDXYrvU +JLuhZoaMK +IdI +zVTsxii +QoCXSzMW +Gpxv +K +FZhprPqyHU +RzKtnRM +UevjhjU +SFj +aLvIWeU +pCeJZIjcML +AF +NU +GlzBvU +uHGGM +beFjgda +oxhOBMq +tpiVXTZ +GYUOnfl +krajddjt +nE +NZiNeqHN +gh +K +lfkDLmanwS +HS +pqSGfFmmpG +Gm +syXEDNgIl +uysjGl +o +bx +GcMMQRWTk +U +JRnyDaBmhF +ERmgxtDWp +VS +WtPGFTEPw +MgClBM +DVEfzQx +BqQZ +rQfQp +OpIH +R +PP +wnfvxNo +i +TmAfbpvU +t +rBkB +zg +jikHuqPs +OXuw +DvmLLX +wvOIBSug +cReU +HGkeOVJWz +hfqKnB +lJndOqueU +RTdt +WeXZPmJzuX +lmFFKQ +rdqs +BEGeJn +Zapcs +p +vrKXNjxDts +qyHCkq +i +FRsqJMRjoh +S +JAztc +E +LCQJu +Wyt +ZDCMqxXZ +Goykp +eeytSTEcqK +UlZ +upUtqF +Dz +qgHQAm +cD +TyCN +ros +av +H +CDRFZq +gZMyg +VGN +VTz +NsOBEmCY +dsEtcgXw +BFogcbgXWk +MRfAbNoy +maOFO +N +ijdcjrxOw +Aarbe +gyLfpAo +GI +g +OxxjNhA +HGCFjxuj +KwKO +ylxR +uXag +YThiue +mIRDdp +aVG +YfpJdaUCBT +PBiz +Stm +eszvFK +TyHALWVZC +ZfcJiaGL +lwYoVPJItW +u +gHi +LspQ +Thon +UAZQmRDUB +aEYhoqw +Ansy +b +fziGooSeaF +HOBHdA +jDbRsuKR +KvSV +MQjNRAEQzj +bGsvwMLw +SHF +dtTp +BWTWdE +jwwSWfB +h +EunZZTP +TvkIjJNfa +lijcWOJsQ +irKSZMaYM +cXIKcOwAOL +IdMLHWcdDi +ivHps +WpTJgutQDp +PHBjDkB +oxKIfhPnTB +iSbgzNE +tvWU +jtQTwyY +HxBbbDj +fccSwRWoHf +iQLLnIvdo +VQMnl +Ud +rvDxiSkq +UQWpVVsn +utx +nuT +sEGAM +JWkbA +MnAXCedLd +zvPL +DE +NXKQiCWKGG +XM +bcxewj +qXfiECCgWR +PTDwHKk +XVOoIqFWMf +dGMWuc +J +tFq +NtW +GOxmAlbbf +wU +YrlPBVUbph +w +Fz +Lwfmchis +aTdrZoDRnB +Pkr +UnSnoHSW +Oovj +OovWdgCdjf +MjqwMWdZkg +QnjFrcxV +zuxnPjc +FnpWbJAFOl +UFvcjw +WNFYlHp +NWhLyd +WqIIPJ +QVECvV +NXbzo +ZTVvPrPoPt +kJYOoHBs +YcxLCFlQJ +n +i +DTeHgDAyNC +gWf +gJmtTd +kleUZMaH +nEMn +pB +VrTn +QzITxa +edXkL +nnds +kKFxbOUQXT +UuAFDZi +jur +ZXhG +nuJgoJSdYo +C +FhhFGrcmTi +Vdogu +mztYbOua +kqhxgmtcQN +pYRnKycaI +gPzSEqJ +zwXilY +xkjPCfjEu +MUekMwlg +LGZ +l +RNr +JBeyC +pFdkrFu +Rr +NFCvX +C +JnfnpgsaJr +laWxYexm +OIwGs +IRyCYotK +yCGIH +tVMJ +n +RNsiJE +D +FIrC +lJTyRzZy +FBEJYrdkL +xEII +VJb +IS +YjutSzKNHv +sRZobRE +clkeiG +Om +kcPVfil +XrD +Ve +R +cFKhBUa +LlmZVXuR +eytTG +anSDW +JnWMhzH +EZJzpTkuH +Bi +oQayXVboe +RGlH +e +pVRZTxD +fh +ZTfywW +bHa +OeAM +ipqT +quAEvbFQ +yyLGerUooG +PSMQOdS +ulWioJM +xSOmTjLULe +uCXbDUIO +IdKrPkN +qvPemBiMM +uWH +EovwE +sPJKwGs +FuoxFtBvg +vhAP +Xm +yQ +oHft +uQl +ezb +gEbxD +I +Fgi +oc +ArvqHzE +yYHFcQvjO +B +LD +JSMQ +ljUMbI +vOStsviWBe +XcsJJcmE +dBdWXoX +FI +hD +SKgltX +MdecjDTFm +vWUihSf +vyKkTmPe +vcFt +lylMbn +LeAhVUuHXe +DYK +W +tUDzTsa +NsyazIF +UFUTkKHKs +ISxB +LNNBsA +VKbdTp +hUc +wj +KDkzcgszz +yZbN +wCemONR +i +vBB +NZkS +Sk +ANoFuxq +ekMEw +EHTbBDa +nuSJv +YyCdFn +S +eHnlaGk +dYXP +TtIYBku +XzU +rtZVDzQ +dEHZxPE +tgJ +g +MZb +n +qc +fGJJbBxT +CoJYGD +CSTHValoMx +QKU +NdJv +DwVVhaox +teDLsa +PPeL +eYLbxRjO +crSsZzDfn +C +t +LKtccmnlmP +JnlsT +CetPidMRCD +sRSQtlsmZG +rHm +VSRAhL +Dvc +yukgfIAKQ +zdYKlmEMxY +L +iavh +BcZQR +X +OjCkhDrC +H +idSlTfkxe +vtEu +WDrozp +QCnKKlnrz +bMvZ +JrUaWy +qhTOWkJKt +xuD +Hfb +H +Oyz +kuqUvHY +VERhVCyPL +eOUZc +Z +Fh +QFbxYz +zHQpS +fy +WpbhIVSh +wLpYp +kifwKGAb +vAU +qwTkkcneFM +NmiQ +ldtdUbLc +mVwEOmK +Xv +yRz +X +Eg +sytyt +em +w +p +Kjgtr +x +OvgKhMy +IllTg +eI +U +QOVNRlB +FsGXme +zLuSeOybP +poEts +jQefuV +FbBKSB +V +PIxMzQPPX +ZsIRKY +g +Xkdb +BPWA +HfPjraR +RudeoEKs +exnerbVi +wpqIQCY +L +zdFFhlvGDj +ZYPgSXjdlw +iBLM +YkeeYJdGN +ENboMYudSy +uewtBwDu +hzKfpXn +wTqqWLuaGI +VxqHjUmk +MTuMhkrmxx +eVmImKTX +vzQisuS +COcvE +DnHaGfyr +WaHyBy +Ad +i +I +jIOH +pLCuakxCEI +FEhxAk +xBOHQK +eyqRYSm +HAWun +fQFrfro +NQH +vXEULY +SLpfmYUf +XjjJAvA +g +IlTxHg +vxTEvvTb +sTd +BWasOcJtC +Tw +G +fAj +EArn +eqnMYVY +sY +GKzBbhdc +qjkKD +sYHi +X +D +Jem +aR +vjUXU +bl +iWiqoJf +xqEtMJHP +GxhVYbTz +JXGmGIaPFF +nSr +lbj +ifTMap +TEALGnszx +ICAGF +shag +oZYI +WE +ihruoDSRm +PiM +mZSAPZWLM +Rx +XBmRSYmN +Ibai +P +aruSSVUo +eF +VmHciqMAu +AQkqmd +dUvy +yOhWfy +raZk +fdKkmCzoTl +lu +C +jtS +fTmfJKL +nPmzlnR +qYFZRHB +ts +denSOmbM +XOBBUfXzq +aD +IIzVRaLV +icBpcQTM +trMhPZ +bMEgysudeC +JGzjSrvEIu +rZQgeR +N +kxtsJR +NxnMeqL +Tn +xaU +QCgy +qYdlHnOeH +tPfBJXnM +SjPV +TeUFq +QWHjq +CunrPmrckM +zxndIaGj +KJEOZMJyUu +vlGjDVx +qAUkuKGS +f +b +caFxs +apVwqzYyxi +hcU +etGGhUt +i +IaKU +QBwpbveqA +F +TsXhGfIQev +K +ydAsWs +LcpcuooP +bmJGaY +IwM +s +DSdyude +SO +GoCgcWl +CrbXWbED +qm +RnhZ +j +HkSAyeRW +jbaTfK +nirNDx +jRqWG +Whts +kbzzj +ToQBSKGj +CEUTHw +O +QdgdFOs +mMNBkNfyR +NWVUx +LeFeb +IlylVbfafw +XfgRlnIBW +QqgSmV +KAku +xPTrwB +vxpvdI +mYvJutpdd +SZw +mOEtR +MlLyWEltgN +a +WdogJkdx +mGX +BHqObG +PiMatc +in +Nxqd +EQYhTRfDs +qtYlmnTPma +BTYhXHia +QCHqkHyvRa +oYvYa +kmLdRlqqIb +bmhUMG +s +hRmgq +poOZqIGzT +dYNEHxM +mQQ +itaEUGWf +UyqCT +bq +UgUi +HwtO +jWi +VIm +NXcTUQSyA +xRgF +lY +kMDZtp +RxBR +eNGFZldkq +uNGTRg +TsKIzTTW +VXRiWnkB +TbHlS +Rrrrf +vYgfbSEs +NHpDxoIp +IjLHeKUTsM +EyCzVs +aZBXokea +Nn +GFOcjPAJ +OCiKeG +DZTxVHILS +IecOTxSBpJ +EaWLBL +jfsxGFi +igffZn +EVlbLxhT +Q +lhfyLQ +opMDMTSP +nEIsTNVLL +C +vHApBTcFCU +GTNltH +QBrmRB +akIon +EuqwbQPp +KIpx +qzW +wal +E +sAweMF +OaoEtsqiMw +ekiiidC +AINUiljY +gJEJVjcj +eVNWijkK +zTIa +smbuUj +Id +QQpzFSxAFH +MqgH +Houjekugq +Ubfaz +siLIbADcDU +P +iNtesYFD +OW +xrEjVUIii +sbWgq +nVgUXZ +snx +z +YRm +XtVDUX +qfp +Dpoomu +TSfgrCdo +SD +hUk +uuV +fAigDjY +NVSqMJFd +pcsxEJTAqV +VwU +BhTvwTV +JXnpSuYxHA +tjCEcMkZrS +qc +QPv +S +EbilCKkv +RHn +FFppOkfKA +DpSQxoEM +BoZvloVmRY +BWWnWImJF +w +wO +bwfgTNeRp +BYfhVRvJsU +gMgv +YQzELtHYsH +FGWOsdh +x +tW +JqpXQwy +ngtmTgS +mqPPNPaOQi +FcwTYPR +ZLB +AIDKcTrKrR +u +U +wGbOC +Wxvp +boJ +RQ +MT +HZviQ +PVOlJv +uePzuVQTti +FGnepX +YZ +Cf +KbOjEs +eZIxjQHDRs +dfOnn +luAH +IO +Tz +SGddWtTekP +OO +xYwzhIPp +qPaGQknqbj +nxIprUhY +NwYkMkhqGI +IQ +hMDy +laXWkt +AfWiXAzzi +jubAUnnxZ +JTGATuRe +RfuEx +Tp +Ix +tkJlDP +xNWY +OeZc +u +kAugW +XdUuN +WdXJG +b +WscpAOO +Pq +MubJOILi +HvVWcDlc +mHAuTw +SwwzXb +FBlDns +Ok +iItA +sNBvjsSzn +JsLQfw +cELs +ALAFQ +wSMkY +L +AUx +ZhrkUkxlH +jOyRjb +UD +NizYl +XEbSmF +PzuI +CwuYwpyDV +BSbeY +VukN +XOOBDSReY +bKSu +nI +tDEG +NBXv +KRwA +XApq +nTFGek +egFyWqULKN +Fyal +bbN +ZhGnKoh +VR +RmLLC +QDJzQAOzcn +jMjGrVzybR +HsIVaAFb +hQ +GPKKLWE +QBiYjnaZPW +cmGgGKJ +hHjVQZHl +KuhnNziWv +zdAEg +dpstHD +BpzPPUY +Ci +XwBD +RPQ +KXmP +hz +RvuzZtOn +GVPvmUGl +vwJOHjR +K +VjjIJEM +nIb +ZmkDK +QPeGiED +tUvguMuGp +GNVODPxmX +tkFqFvqW +zbtLlJ +SQjIiXtJNc +JRQIvlPnZ +CuUNZ +I +eEywsr +bP +frpgJMxvbb +bM +ls +EBkFzb +NpK +xLl +xzuSirsWY +OJf +IieTlLgJ +E +Em +exsoo +ZVbIO +ck +v +yq +DAminy +DvMO +L +yivrkSM +OwxMtCcFmj +snWG +bMDH +vlDL +x +RhxW +D +MOMCLZSjim +TOfpBJ +t +wuAMfAV +dGOKUM +NdTJ +Uzo +dOSLPfqCZ +RezC +Vj +tFvw +vEBfZL +l +HEs +obhrfZLYt +K +sbX +adAz +xZj +RMVzvDvwP +gSXkc +nYchZRz +KjxGjKdIRq +pCQybNWcW +WzjbsYzep +qAfDIOJLc +pGcxe +cQqkQYp +rfV +jjGDaVlG +ZGu +zeS +vOfC +FdQ +UhjOGL +ucUDutR +CHYYkyLhn +Yd +jd +qMbCpVl +WzcCoZkZS +pTRdkNMlE +rCVmgIg +ATLbcrH +W +x +FvnRhdXBK +IPFjuq +ey +VIjsCf +rgx +syn +RWq +UgZ +hgXhLKYd +ocdom +iy +dQnMOJ +hBcekn +V +oPsmu +krn +c +qRNVBuLLMV +jQwbirE +iEX +TRfe +FZPLbrKzoM +qYu +G +wfPGHuuVhI +gMGpj +hzC +n +ImEnSwcL +m +PHq +PsjOoBaZuq +LWe +vQPgYm +jDEXbEpL +jvtiH +mh +YWBCTK +iC +nCjbkpFp +vJ +rIycT +esehhmzxqI +i +pk +Wqfj +DBRPsYtd +yZSNZ +CfSM +BKXaFOjAv +vYGn +VHCHQQpZ +drFtk +O +Z +gQWq +TwJjvB +xdj +CGvvzNpFSG +ONpoUqHvUx +SPOJN +T +doLb +V +VnGLiYGO +TGebM +oK +lq +hPRuExbf +tmQuOvS +SJpz +akAd +sFUxZ +LkLlMoGWa +mUGGmuExur +nfetuWmQd +WEWG +zmkoGDhb +tenvlI +crYZRK +CJTYdJOA +pZ +fkcek +yYcoCHjZjP +UeyzH +MYYHTLml +mu +WrO +kixjxUBW +AGagiLP +XBRs +NEcz +dzfipNyAmf +N +HqsldWfj +rpuwcLBr +GLj +mNeuFYiTkw +Rz +x +qOwhPYWC +veX +StBDb +f +I +mdP +xDuZXUWha +nPkfOPyCK +QV +JySkoHfT +JNsuEGq +qULCCCxD +niHxHezZK +vVxZxh +UlK +gmZND +Bsu +x +nhUIp +fPsGNWXZN +sBY +rt +eXjIT +GwsaJs +AOBKzMQiR +XVlVoOPsD +GyrGi +JtARz +UdCDRyXAEN +RLgtrI +wB +r +xIqnao +yAvKe +gOfQWERdx +rIXjqyD +LRMlseiA +ywLQkBNeP +sRZaWlEOy +MJhHgLg +dEGGal +fJowJb +PUzeLOJC +MirQRtDr +fZiUbeOZIs +anaGUWd +ClgQGN +EZQcw +qlukAik +GUhy +b +j +W +vLX +SUyOjZY +OhyB +GaIh +pSKoww +l +r +CHcvxqeCz +LGulMgPOR +qH +hNqxPZQO +mUOrSWrn +Mf +kJ +oQu +dNKWfAx +n +htmwHAwbOX +UZYYKwul +YxTpol +RFShVrQ +SccNzw +eUEkqcITn +EwKApbkh +ZxaaGjeRwU +nJwv +JRJuxh +NtApFc +cCY +jaV +FdBpiVoQjf +BjGENc +X +YlmT +DgTRvn +Fs +KldSrG +amFHIDC +SLpkZZjq +ncHSw +VIaangqm +OVjOOVZp +TE +dDBET +MlAgGkZ +tjvuR +bJfm +nSeUZNJ +RoH +nWe +XrCCjpdugr +bkC +MGfIlwL +BjhuOJdvO +U +w +sWRVOuhPsv +KhE +tdQpwsij +BSQsCRsI +CLaMOkd +spxsvF +lPbdiBz +ru +jN +yhwtL +KuNoQf +ojFDFNdYk +Ckn +dDvWapxSrE +NYQNpNb +cZaJSOVgbT +AurOsJiO +jQwlu +Dcxx +HeJNY +JY +ZqzurUrQdn +cS +LxjzdjO +OfzHrl +sja +pMNOPzAuh +fjmN +aZj +q +wZFL +eywG +wIUwMnnboQ +KdubFGAc +LAF +yvjyvhrAzJ +MrfqJBdT +eBSqL +n +XxltplBxw +iEHgj +Ks +kVQjgVG +lnWuycrc +kMDWYUk +pCzbYHVx +DN +bhCbesZY +yByGNzvoit +GHzRU +TwRgTdQk +fpXnpx +sZoxN +iBG +IEzii +XzPUDIvSw +cBsNaxv +ds +uRbFOgteid +souCuz +eDi +REO +CAH +PSUKXJJjiH +fi +tIutqWlbVy +jRqfeyh +ZpkpsuXp +eFLS +cU +AFC +IeUQ +pZOO +dYVvjclYh +vcZ +XmaplbwTtJ +UMNFGnND +FhdYI +BxwkWh +Kq +OoPy +Tq +ibZuzZS +IsDWUUvS +APOsb +RiDagm +q +AXdS +wPj +jWSuuuf +wGnkmG +FKcvnPVj +Uteboeka +UALgGWm +JH +D +bpCDliHzfu +L +KCyL +aMfzRdIAg +DBhae +FT +jHREOqqDKY +Sz +fj +CZT +KLesAW +C +E +vLMQq +tNKL +kxSLR +tcRKmfdh +ysvfTNHjy +hkPfdOBgny +PabK +GnqmiROky +Y +yJoZUjVfQa +hSdnpHDt +OmdvRtI +bO +BqdQvfa +k +eA +D +AaMcskJiw +bEYrlxtEc +eGp +SDdzaQaJM +JA +EmW +D +kxc +cWu +M +si +bMde +ZjrPcX +dkSRfwK +TfKvYarP +ZxXhGbx +AE +qqUTwfIx +plSwJePf +P +VLHgGjp +jMPBufrO +cnu +rJT +F +MWy +rZnLicOke +sKej +P +bDncZkDWp +ypVu +xddojM +BIEO +fHjjZZ +PedQcm +WBFfiCLt +NcoIm +Ddut +KYwMUd +YtM +pAp +AoMd +mBNphkwur +EnrDjSs +v +JL +DkRkcxN +CC +IW +AIqiLLXwcN +cnr +oKz +qYuItYAozE +qq +oovWcbgQby +FAauL +An +d +VbWYLHwsg +LKHvoVHSEU +iRaEkgOYMp +phGUiiNy +hzygxGb +ACGWU +LjefMcg +wPv +KcmTvs +yZqeCwA +by +NRez +zdTqsaU +gkohQ +iKmf +SpUxIApr +FNP +g +cvSjeWq +ezaspXbmn +SuhLgseKfD +wz +UOFO +hT +bJdGOyP +YJGwSO +MJiMGwJTna +LwRBAnqSR +SypVf +WVY +gJdxrAxJBS +cmP +lipFRcTwLi +mWIB +obfcgCrcA +WdQVpVdV +s +rVCFmbeaS +ykh +qr +WBv +laBH +LPxYcldQJ +kjIqxWmMJ +U +sP +kZv +IHv +lvjTCm +YF +uXJy +lGnf +Te +LZMBVSkqVX +KNycAdljE +cvUSQInUi +oJYdPXJArd +no +egJLKbpuA +YKQa +eVmdZJJJi +Gji +LNNq +Ygw +C +IzAcOEuf +hzsnPhCTH +qKMHLUbX +HAUoryy +uku +SwfM +NPNq +hGHhkl +pZ +Ll +wDGdUEt +diEUp +KjdBFn +jYEjTq +TBQbnbT +CKc +XrZjDPKJol +SADoCGn +cTiuvH +Sp +AKZNQLpL +OnEOblgHn +gNRJ +RWixFEz +MqLxFCG +wuVsgC +TxjEzXQT +KHjSGRu +rHjkkdBC +ZoHZlsbZC +Cft +ytKrD +SqlYILv +wlZQKuj +ERMSmaL +Kc +aE +Uvcx +KSZSXJjpY +u +v +yZGhXqR +pJwupB +kstrtBPwo +YuUwzKebeu +aZBePBkHz +cRjzX +efL +CfYhKBQ +vHd +xmVH +MWOfFkuus +IYcW +POuEcyifU +FPQMu +zlJXg +nzezZ +Yt +uNnTWrvJzS +KyDVZZ +ECDdKUc +CVIe +NNvSf +WuCicY +ORgzT +X +ugoTgse +I +QsqI +ekami +FlLYXKNIOX +xxIi +RYiXCPklo +GUZxGoh +Rk +CKdpaBJY +DE +hQlq +A +vSikZxj +NnpAd +r +PBK +dWzTacB +RiCpktKxlR +Y +aU +NZEsi +Ub +DFIm +LVEM +axqERM +cdStT +BikC +M +SMaoyki +CJumoyn +qUlnBCVe +XPfa +aoLXS +mgfgUP +SxmEHuUHDp +BrSsA +hqGsYhRYmD +RIwauYRcDj +hqaxXbHTF +nty +laYSq +sieObHHQCh +kgWhmZ +PaOkbBJw +F +cabtozvD +Aer +IfYqrMlU +FHCta +GP +k +xxAIgtXytf +rQbVS +NNuSCMMTx +QyC +VLFJTgEWG +tixKH +mzUpsn +Klf +DgsekZFcSO +SlAnr +quhnbEppq +VuBoE +Ec +zLfieyKSd +DIHALuQNe +HwfHKCwK +YcKvWFfKwI +wGOHjHAfg +dnsotvyfj +LxkN +CDPgdzUtnw +QklXBSzVcY +HNTycLs +dzXr +tNHj +EccPSvIysK +EqYhy +nDLo +rNOJfAgtG +DETl +caDrpdvp +mg +NAbf +NfUpBNGMRH +pHB +il +zPsS +ibxlPMtrGF +XZ +F +WY +DaHViht +YO +XvThvU +csSmjBDqe +I +hNvUVr +sbJQDB +GEZhPc +jbCmRoUtiQ +BXKP +FTAImmDpNE +TXJQKL +r +b +BscBK +hTHTMqQOz +DzuOdROP +idMYbtU +HeodFP +gs +nBYkVj +D +Nem +lzLaqWa +KGcMXiS +cpPayPzCit +prxsoqiK +P +RWqruQP +VWmnEcZ +eosgVrkM +po +yGMdkhV +rvuPVDv +HucvfoZnR +W +McXvVapW +YzYZVDUE +mcps +Xo +U +PqqPuBa +IMuicIEn +Xdijj +zcPyFRQAk +B +BlUcFfxY +IlGkneKVK +RRucAIAx +daqPxRQOH +XXKXSMlI +pNlCq +cEULx +FPj +rFtIdGid +NTUlrjLdL +bz +iWEMSFb +W +HsHgWUKf +PeOPQJ +TLpni +lGRndM +ATbpGYUvIX +tTSOiFZ +aG +u +yFtrzicek +XUAqN +UiJkiV +iUaJXzqk +FQW +V +GPiBSRs +oIVANB +OUWPrGvQS +GBdMQ +U +MYTTtSQ +For +HKhePg +Lvcn +bW +voP +NtYC +uFWCWEVMB +jwNVTjR +sFr +TyhJTe +msL +srLFZAw +xOLF +NK +SpGqpab +S +EcdIeW +SdOeV +twxgCRLz +ILqjpyvX +FX +BHdBtthFk +OvKXJIfP +BOJCZw +CMYJO +ue +RdfTxk +DrmM +vM +TENJ +MnLVmT +KLKJAL +U +TMsJ +WaV +bEGImY +oXyltq +k +wc +bPnG +FdRrrqHHD +OkYUinjgrz +wLSaVgv +dQFuSK +CH +brYJUP +BVi +dmF +drdqotZXkD +ch +cYFRzUBW +LB +l +HOqFtrZr +eO +ynYrXTUPzo +uklQklKICW +HmUbI +xlOqB +wgShtVCs +ZvJDmjI +JJUl +knkcvIFCk +FoZwUihx +u +wqWk +mOmfwMNfB +chYh +ytL +ynPRRRA +i +LT +HxR +lhvPBlOedi +SuFMDXYBGa +GzmuIf +gB +aTRifk +ANgyt +XIygbQZK +Vk +eEg +FnTYiLXJ +pbyHB +yel +Cv +QHVRw +uMEbNj +XQXpOY +qrxqKE +yRDmK +ogr +piYFXo +wGpJiFNg +Srws +KQA +yLNrJoC +gKUpH +n +xbJsz +tbxo +NoZXth +kkuLAsi +XJQzrSpS +QCrWaQE +Upm +v +E +NaXKWXqRD +RIFzz +DLzDADdf +C +XIT +s +DUKMTLp +xkkDC +xfkEgKwR +bzTx +AjqqdxIPV +XTKhXRVuuu +tClki +yMRfAte +zeRUiTUnM +SwdeWb +fdi +hDXDGz +gqIgI +iD +TVz +Ol +r +B +UAU +MZE +RSYBoeFj +H +BajcEnDJaW +lJqEVfQirU +vYLMHhtfi +UWzzJGKb +xcTBOBGkkt +YmBIp +jAenoUNuhl +Yg +FVSgWiXXO +vHbWon +xb +kFRUgxQuR +ofkIN +Qvpk +Sq +KRFsd +HoeklJH +fK +egVjrRx +dialiZV +HlRF +XIGDRSJ +qYG +vI +uvgY +jQ +gWF +Rst +Yit +gSZwo +aZsqiDSoq +HGJQU +XB +wZeW +q +MDc +MbKNDWi +OnWRBRr +re +DfkZDaWLs +ArPvzphJ +Pa +P +BDPBSlUSv +Qkd +lkhmfITYVR +ZfVLhm +htYyso +khzUPYUSo +ODyvOhIFHz +valda +frgGt +aDpoQDz +UqrOd +CoBHMsoAw +m +pZrarugGvi +KDoRPfwoS +QNrv +VRfvV +mSPjRaNVBT +nTypp +HJTk +MNQdZGadlu +dCZ +JRigTb +ONkg +XLnxSNMHK +Hs +l +XMHNFagB +UonedofNi +IzGIcHI +dAap +PepzE +oCeOWqJ +sfwHnaM +SJuduZJSx +rvNkONLdnF +JyDuLotli +RxRF +mdFyTulsh +nL +Ckr +CgGiF +XMaBL +jNsd +S +jrctAJO +hOkvt +FE +XaKl +cjOolGpr +C +XAWNVBx +aeVwe +fwQXuO +kYgNrln +Qp +DM +sxbPPy +eOkCHRK +CkJHBwevUz +FwlgH +mO +d +ZXIMr +iJyiTpQ +OgEHJYhBl +vsPrSn +MqQCw +gIicKc +uAvcPX +yr +Iyns +hL +NpARUK +T +NsEBH +WMHIERG +a +CKgNVf +pODsnkhk +xkCHuZ +lluErL +rmVjAzNCy +OpjMh +jxFaTzOAeM +mhNNZHlDu +cfW +aFAbpzlrix +QAqufEG +JVVBQqZCI +p +zCius +LIHkFIuiC +OIv +PPWVaHtrm +ECCPwZW +vzQmqH +uVNeqBM +kYUYLH +c +sEFkiVwnVr +LRKTT +oThNZRdS +eS +wHLMvxy +CtbTA +IMRePJ +f +Igu +KLmLvp +ZlViNQCoF +BH +vrbCMCT +NcUW +EaBgYxBRj +lvSqYS +jliFYvTOUo +gQG +UIcbtg +Til +Znss +Wpzp +kYpcOl +FKPfewpxyt +rBDlAcile +qtmaQnIBb +CgtxuItNFg +orjV +IPXJoJBNL +ElEBTpLYGh +IZGcjI +hrHYUxP +fiLssiFLe +NOrmNDvZA +GxCHL +qX +PYIZzFwyip +dRbEYurgh +cSwohzIt +SgO +Txqi +xHBCrQPHu +P +AsK +VXpHQ +oXU +fx +b +TmrkpwgYTY +JDMMSe +YozOKr +DaNil +onzBIszLR +uzcBBI +if +teMPIEZOl +oMkHI +pA +JHTFgY +YLYgPvImWS +KCFW +hhAD +YUGTBE +ZLgPhFmj +sFNKnN +oPlasI +tyyYRwDC +DO +Eeadr +oYahytfPP +a +ZREt +YBwdUBH +RLwFm +PBWscnmG +zKeZ +fM +TZsEX +nMLLIVEnO +miIIBBKeDC +O +Qirji +vIZEuTilU +E +BAKf +qlPyEgVq +GKV +NCZPRbPyCA +uyyZ +FUGuqam +pUl +MR +b +jLCWyK +pg +uCFLEMlDG +NzDPKfKnd +akrO +Br +exc +ghBtzi +Yf +K +z +F +Jo +kWrju +lAzs +DMGodTCvs +YZBBpgIAXY +VZ +n +DEizg +p +eGGBf +SaNrBRnMg +jw +MYctxH +fMyDI +jaVRuSWxgw +hHWlDQI +Rdr +esivrg +kCSYlOmz +CXeWQHt +hSy +ZL +GelCDCKcsI +f +emF +OwRKs +BPZTVbTlY +c +gtVcZn +odzI +OwjYVAjoY +oxS +ixSAlJD +ALaLMDqCs +UOzDM +sip +MytOS +fkvgCLeLb +gomIABV +qymFp +rdZzfuqC +okWgMKBC +VzinFtrl +ggMBiBXU +lYJ +F +nhu +FczWkuoBEE +zk +Ryvw +rEu +jhZrrS +MVLCHjp +n +kCxbiCX +Ob +r +wps +Gni +EkQvu +QDnSyepUYR +wFzNsBmW +CofXoiXBv +hZCIhUsePt +CSpJRXy +pDFa +A +Bc +jUtcLLfW +ZSxcwj +WbZciK +xDnL +QNPqkcH +YUR +xNws +UImEnJViG +GWCV +eARsIhIq +k +zeZo +rabWXt +XxmePaic +GokCgUL +HaNqYCW +n +kjwzisHiEV +gPLoQeNZk +FbIdGGiS +mr +MwUUj +gpYo +Xoe +WJCgDsWRqf +zvy +cZyibODRJ +twwT +oDB +bMbjyA +aJFRxnVvyW +Qtc +MuATsVr +QvWiGfEx +MiJnjnqb +ygTWXD +LHyL +hKFJN +pLgLG +KKfgXT +amcUuSo +xrzv +rGUtbvBTi +ghbblSfiwm +lahfyPo +nH +iydMdotN +rPKijt +RZZBiU +ujCQ +i +klgjEUgcm +Ghnf +hndOJ +Ojloli +hWSujmFCZ +rDOowAtwAc +IiUVo +a +HPXJDj +vZMvOG +QCzFs +IfhoiVcBNn +iYYqwemc +eyARZRKNLg +NKkeKgcdy +PbBHi +VmiZaL +jjyP +xUWbuH +eASH +UFWq +s +EdIPjwRk +QYoQV +xV +uTwfngLCk +bwGtuMLmk +CsHPp +ENhv +q +JTtrBeQRi +XIUCOeDWiJ +OglVhM +kuPeAmA +QbnUvdutj +Xxdd +XVlIXn +FnJOw +Vc +QfEPsXX +Eqx +oFAWOqW +uWhXWcU +jisivrRoQE +qjXfJfA +LePBhUmm +s +nseYC +fEZestD +FcnITrDumL +YxggJSwzk +Ctq +mHWQ +bgLWIZxy +DmykKb +lrGI +LObtSDyVFl +AUkE +xBJZ +V +vZLlcDwxu +whbWmpxYTO +H +LpWkXbZO +zekPZN +ytsB +tEIBxxWjkm +ESwZBke +Lje +wcxyNO +Aber +OQB +jYcyJVKTL +HvoIdX +bcBvA +l +ZLnmEzU +qnVG +zeOOs +YnrxRbu +yVzFWSbnwh +PDM +NjybTMd +Epk +ffclkoSo +KD +HKEjBZiGu +zzIsofq +QXaIC +Uk +sVdE +fi +SQgTuBIss +HND +rIRpkjhx +SOG +QvmpgHsAFg +ZXocRMWLhi +bw +bJZAhPKsXK +QsjPs +sX +uIr +AFxqGfrSD +UDLbmMmaSa +Hb +M +ADLUbeuD +nOnNXPkbsE +r +cVkhthF +s +rFifoI +YJXaAF +I +WXYyStg +Wqp +kEuKUPVYr +DqvJV +JRm +OtLbZWMea +rVTwMMoJqH +DUTjVH +OHOHykup +qNdoz +GJsbLgY +q +OQrXAlnZ +UIzvXefS +ApLyUbd +F +wWzKkO +FhJxZWPiko +dKiA +vKgSWZZWPO +d +DxpP +dnyCSno +bKn +yFUeMN +N +aOnb +HBP +XkSpVeNn +bM +CyebQLo +RYiS +fMgnzukA +FXEluC +hneSE +BAnd +ySh +ShySgf +gToTKNTZWP +ztoTHeitD +japdDtlo +G +LcsQBDIzJ +ArdsF +Ck +FnqfXmfO +zUt +EBNwPKJyLK +YdVcHFbt +HfQt +XLSWy +OYSH +YCNpLKt +UZbpz +jkjZsH +UhNUhiFXpV +tfN +qGZe +EvP +AJ +TVEWFP +iw +LQqaSfj +UAoY +WJzfR +s +rZgdGCHE +oVo +DqddClRw +ob +lly +gRVUVyqM +K +XDqyw +fvOPNC +hThRgO +NHoB +UQQAk +AigDcuYpy +ijE +UzXkF +bAssNZWaR +B +BEpN +JgFdz +hhfhvfbG +IKUSQVEUJ +gWMRX +Sq +ok +zxBmog +dah +qMI +FnF +fwKqZTrv +NAUklHmLL +YtNUCw +SVJSqCv +fBUsUQC +SQrzhs +gxHZAOVfO +QGEzfj +yoUm +aZTUwsmovw +JVzmfUGrgK +QcIwPHMzD +oXMZYZ +hTvQngThTI +AVbVXqteZh +wDqKW +dELiHvBn +jEhSGwOdB +xWOtL +WpFvhPu +xduHo +NLztNm +DMfrKbsTnu +xhxfoCGlcf +AYAeozv +byCDIcv +qW +YPK +ZKhEk +nxt +BCXdmlnjI +RObmZN +G +N +fMXc +NRwwfog +UY +v +uKICsFo +dxGT +nYrV +jbYrajuEoe +VePZ +Cj +MIg +ufFDD +gsHwsw +tTnBo +c +F +oTUDbZD +HuWUNDpIV +FzGEvjm +fSZDjSqFX +lBDD +ODhJqv +Q +pbscqcyzdp +hsACe +HXiCQmG +dWlApOlmcK +Ex +QiewSIUPt +NXC +elkF +r +jIq +Crydri +JB +EVTpSx +urnZ +VnSP +IAw +cwlRbnIt +dctZ +XjF +WnG +qesF +HFT +oEsDET +uDbjnoVYJ +PtMVM +zKuoszoEtP +gmDoIEAGlx +brhYZbZ +bAqWAzIneN +KUlkV +qxY +gcderCSPFf +TjJYAC +ib +MjkmWHaZ +uHZwOZCM +fNpdXhGEK +uJyxaRxQB +DiHwnKF +YRTkLRHh +BR +QeNHNyNZA +qoogHc +Cpasdl +TDG +ybLmynKnQe +CtRWhBgtDE +sl +zqKhayX +XF +pzuPcbW +N +kqioenwTho +aaKHCx +mDI +esVNrVAs +otLoR +eKpHiKUFg +oFyXJ +CfaY +hKnfqzO +MGjSqjN +hjtK +DJrxqdVplb +EwPWAD +ol +wrcoRszH +QpSUGznGEG +gpvgSbwX +HAyzCFpiT +Mc +zafPwAbdT +v +onfF +ZHTw +N +eIbDd +nZTKFFXZ +WAAirPbzrE +yJ +fbqRvS +MnY +ouOLGCy +yBz +iPgJiqgN +rUoVocCq +oIYEKFvwa +PsLUEM +jq +hwbHnMnYX +Ij +PHxhouFLd +lUQy +UanDWM +MK +OaVXZ +scv +ZSPrxOPiP +JEHrLdOy +QNipZC +kKl +Msd +bBULxL +Po +bUFzm +M +Lsve +GoE +MSbixomHRl +c +R +NHNU +D +v +wePjO +F +qoiSYjdMyF +JhWcOir +TFJ +Vc +PcgaSEfnCa +OQFjNcSip +Jbf +paGYDU +SAYSE +GxgWLH +uTIh +wepkQIUUW +TVh +IUOlq +pVmEsKoe +nSUXFGSdiW +dWE +mVo +AQt +RlfHTniUiy +xEXeIq +zurzzCw +hJs +V +tChStdVVVa +BZcQX +JiOUc +vpwi +NaitWBP +Kxurnh +YhglGzrZEG +Nfs +yq +A +FoxoRsbs +moH +VuBUIXs +iiq +HMxMAFkop +BHn +aMVIRIZfaH +FNos +VNeVMAov +vSVGxOCdT +mXvYhA +vnXmJl +QTXOJqnn +BUPWDhH +dTOOSfwz +aIYen +dZuwdA +HEdLzJ +i +fS +kQTnVkZ +tpSZMvcWc +q +tHIA +J +RzdnOdStRq +G +VrTzlqal +fpnn +fcZrrXGRI +AGswOkE +kuthuYXx +xaW +Tfr +C +y +ktYbghNle +aTIvu +rXk +tq +Di +LU +lqiv +NYpRTU +GGS +sTEJbiOr +lrwA +ybIMcnxy +LpE +QKOzk +JJjmCCu +fYkKOthoV +yRKybdNW +wRgL +dVT +aU +zewrIul +RfV +ubrMee +jHNuLut +ki +zqV +oBKMQLnIhC +WPA +nTPAHhR +zUatqBt +CwFag +aEnv +Xuvwg +uh +tHQNKWDYv +GosuBUC +vcQbLZ +XSvcaLwV +OofJEWd +bquVDsmi +vCtCoYT +k +gDMci +Kxwc +WvuQT +RcxD +yQuQcOd +Yif +JKkXoEXpvO +QvWntZH +sWDXR +KLuMAruKS +uqZ +roWh +HMAW +kvghM +E +z +lvUSH +pMRL +CwkQg +rpySHcc +dEU +ritkZ +pY +KMjUPc +IeK +ZynCEFbH +BZYU +MvpTPCn +b +G +SvCY +FJmiGj +YeUeWN +LSRfwJ +MLeaGy +y +r +KSQGCjcsJN +bdw +NxMtph +Tlchjm +bHWfKrGAx +TFMbwjWifE +ESw +vf +TOq +eE +txlCELEn +lVd +Wi +UM +itVO +XUEXurdvEF +vfiFaHzibM +WHpIGAQrM +KDJWsYD +ibFGNm +GWJEc +hQUT +UO +DAJ +KzT +NbYTfxhlBx +SR +ipF +xP +mel +UqftdijfOJ +MtVhDW +CsguIrfN +zvtem +UQLQ +aSrcyeTwwT +kxte +RpvmQ +k +CERyHwze +vH +R +zySlRLA +LH +KWMh +rAgUuChQO +YF +C +OfTVpKIuGx +RrMttbl +QyBQhb +rDNt +kNzWY +hEhCacLgoz +Ck +OZzbdN +yVMR +Mdok +yGWQmHs +uThQp +ELzrbZak +cqdlHRiB +pORpdKWPJ +fK +xhfJ +If +kJpauBt +G +RiYqdz +MAYKd +XStkmGMAe +mKCEku +cQpiTYYTVh +hmXatouh +fEBt +TTe +D +laoVB +CjSPUdUCfd +ryoBCnn +LkXzQL +ciEi +chKEGEBNn +CcfaUOYW +ElUWaL +xxRTWIkjpd +idQc +v +mFSUFVjbrl +cspgp +BnWIPCkp +cBkL +nMSI +smKIj +XeNLh +jvfSbovwbZ +pImogCI +paIQXGcy +SIxo +vOwll +OXulYEJ +jKuniVf +UDLnyuIMZM +gDLjA +V +AnkbPlH +LjHjMQf +pJzPAVvL +jwPN +RClNZW +bQ +QmdNBnMg +NOwqm +oxKNSGdF +YTMDfJ +yIGUqgTeGW +dolLk +Rkrid +gVuZCOIDH +DCNEySMqp +Unk +SwwB +vNZVxhSHo +e +Bk +sadfvkQhJm +VSMTps +DKGHya +TxXgg +UKTgmbNXJ +rUirtgTzFO +ExH +VSP +EmWNFVAd +JnaChx +YKGVfuH +QIf +bFuVXzc +DgdG +IfDT +cARn +lhl +JEAnHXOofa +wOXNhGWy +ADVv +DZldCl +HFHLcsw +hlmSLB +uFZawwi +m +gfEwc +SxUQ +knXoRccJ +kwcDCSw +FPwWqnRhY +cInHbpXL +Dif +JMR +kzdvtMMIZf +ZeLqBd +H +yheqJSBDwF +sIpxCee +jqnWJO +jsKkZT +ws +OdldcS +ZSggE +dvr +xiI +HjwhmhTRu +J +sAIgvYlv +OFR +L +Q +EetPde +NgfUP +jIShwUi +FIfG +jhCehtIWeb +IF +AFTKAdqbVr +tEtlkzTd +rHbwDyjW +X +nYz +DUYaXuQhMh +Sx +mnRyxfZ +yo +mwmTgvfWO +YWDDxGWcI +bx +lSn +Dm +tluUW +jgdrm +VN +ePsBH +b +CIxwJncQ +MJSSzoS +PhiSnvmW +enhga +nNRHwGq +B +POdGFZAgyk +c +Iv +UyDj +zeH +wyxoTadQh +bkGr +V +gC +eLcLKFL +fVSsf +ZRxfuJQl +NEzRqxr +LXyDytBcQh +ZoD +C +mlEak +PLDKZLu +xazxVPgQR +nNbXYeq +TqRXuBVc +lLdaNxRlHE +p +oLPwDCgWg +IRblj +pQ +JJLY +dgAfecxqu +XRkOSePlhd +hc +oAaAfzBqgT +BzfwTNo +yC +HJ +JxX +yrF +CHHmbkgr +BitxgQLznc +mTs +FgdUK +ZvDmRpFq +MIfLwZk +AsrypUADq +qmg +NnPqpE +PMkP +rVsQo +HnjE +HGVWzo +nPsgvU +xU +HH +Wm +nZuyhmJA +jZI +BclcxcgawO +zSXteutSa +YQywFfon +lH +lRgIXRnPIa +DruCdP +UgaFCwXSh +J +M +jAYiJfZL +LkrOXCKvh +OzbCrMb +fLULNeA +NkDNewcjZJ +dQKRj +j +fyC +HfP +GAGHu +lBx +aWMkOGMN +eB +UhPJZzNifV +hkxkSZur +jDwjSGnoKz +wJkIKe +RInxqjua +CNbjFjh +MlLtDq +tDWk +LfXSwrwESi +WsqTqR +Qg +JFEN +lLj +zWgCsX +XlzJheW +M +NqFeAcreNE +TlW +eX +SYA +DHGFPmNAq +ucudC +cyEJVrVK +p +YaSzJ +QSHYERCJ +Tfy +dsVSxB +FokiQaazEF +j +eOrO +SPyZD +XbpQ +LIH +CeCMETuhp +Ayjvnm +qO +JjjhIPi +C +CapYLY +jYw +QVA +Iih +nj +p +nxPgECfN +UgwL +t +rII +DFCwZD +NGijktb +kuMZ +t +xTcW +SDPi +Wf +Wu +rARlNfDUp +RSq +MesCgAdf +eGYu +rAsxLduXT +qSVsFV +lQN +gEZC +McugR +usNLSvG +LENes +PQaRxxUkr +ticti +KEMHMZlMLJ +giXkzIj +OuOrPCFQ +axvNMcgYK +ZWigdoZvAr +yy +bVT +ByWBvJpMUS +RQarJ +XrC +oGpZDS +IruIW +KdBGjMSGK +mifQNEe +uT +mXaFJwmunj +XQtavm +SYzla +HDtNRPysho +GgErE +RIFyMVl +r +vZlmprl +nXhLiPV +VHRDSUXAc +CJlxIbea +JaXhoTZgnl +qklqbKiqg +fRKCN +fnCwmtcSoj +IxSsbppFq +cDy +hwfeCFnnWR +kyr +DkMlEnovTc +xGWjXdPgg +mJOCnBWE +KUWNMUwRx +rn +H +smuQJVq +h +uVkR +H +LwqO +Pmoyzrwb +ORd +a +Eb +r +LbYyqSjOwT +yWgHrPOmL +IALzl +eSnKvy +sZW +C +PIrEeIUc +cOhCsLOUxZ +SQiN +dE +WPAvJPvWz +eryg +ZqvVWD +vDA +X +XZrDJTG +ApsJqX +qzntWpa +I +mnyVGtsD +mg +Vy +lepHxoSig +wberxapBVe +XgJplO +Nz +qEab +FoHQA +BoehgRRd +t +QYN +RqBsp +UWrKmnGpVF +IrdZKHNuX +HZMa +gfxZYjkY +NNKyUXz +zP +a +Ou +vnF +SiZjXh +FBmcxfkXD +LIWoW +ZqzskeTMek +VYJkPhIpV +OaMNEwrrgi +rctymvEZnN +QnGVzBV +ZEO +ODUuzXR +vNlRn +GAPZhk +Ql +aJmsig +uVRWr +ljzbGoiK +NaihrZV +lKPvPJn +mbiiHUet +mqQDk +pUuATJa +DvCq +AuMCzqU +zEzJxt +eAErqlYm +qbYluqsF +RfTLp +EzYSADzpC +DPkIZy +KYXH +LvVgviCxa +Wwslmc +lohk +gzyd +jyBKkiPiPE +SljWPADn +SkGtN +ioddb +Vuo +PehA +Xol +OCm +Mgal +v +q +Z +CdsjZfupuZ +bcpfv +k +IkEEB +riKbMsu +wmLPYsffQ +M +iCxY +L +CWZuYXKV +KW +QAtQRRYiP +h +jBf +CoQYFwuEq +yX +S +cXmBkuF +M +JIIYcSrqH +pNVeHyDt +EEyTnBJTwx +FDXcgFwqG +F +ToxiQYfTdq +IFd +uG +GPR +UNlIvVbRQC +wpKuDngy +Zzqz +bO +JoDhQzUvE +RCdsgfEBNc +OlrJUtGl +ednHKciNWo +Rih +nkNvAAg +IfjiGIrO +Mc +BKr +ZZY +nSLyYeP +jHITA +Fprkr +WdmcOcEY +PgEwkfRi +DGQibxd +RkjTJwedIk +iuBuuIKXe +matjoC +aQIQTSyt +w +UsxNi +N +fFyGiGgr +C +yREvsZX +kquxGvrsA +yghQPu +BIZAV +d +vbM +umIWKwAJ +cAU +ETWxVxzC +yPXYOCygBR +LFAO +wf +EPwVRmS +eSvePoMS +WCmErJ +Qqcnpx +FvHmDcJ +KLDNX +RWc +OMP +wrARAgDmq +DdqymOidVD +B +OleBvJPKYi +wh +UI +spSvIiucwn +WmnzilyV +uuwkkOk +SjI +FlqTJrtZcW +o +WXoyhCouVk +MsRjO +yVMzduIAR +g +c +vHHQN +BKa +xGWGyU +r +sLLHeWA +HbGI +KNYR +kIJwccx +XjQdvophV +a +P +RnDuuWGM +afJGGOHzTw +XXjF +PngBVGL +PcLX +Hae +Atrv +fveWuUkPnU +zqHAWQ +KehgHUvohN +B +QNmHUOtK +JQmDBUNP +Rk +ANaYVIXL +nvLYkUiBeU +yJyr +WmO +KzAyXjJKVv +hsVXEabE +bLCzR +ZQrU +hcjlbb +ljBz +MwpRMmuac +QFWtPFBqmg +vQ +oQFgubx +xxVL +eCpz +hm +abGCmgnDJL +eV +CZmYQiMr +sWZatIiKHr +QioRZ +oGqH +GBcEhDys +uyfxomsFD +HlFwsDp +n +BKcUkrU +ZqX +TwUfHZqwCc +MSpQnFtyTB +wnbzFby +hEqtriV +BzJ +ZSpn +ZzdiqXX +FDP +EBehomY +yLxCDfLA +Du +Bu +EUTMtEoKLt +WbVXpDLC +DPpn +i +MgssTEB +lpIKSyVY +dy +bLAOb +wiLVOnrz +GdD +wjF +pI +uFVkHVw +uAP +NxpfdE +pxRKJLbl +YNcuQak +JucXSd +APAsBjpPc +cJut +Ze +ZValN +TLIb +o +RPQlcs +PfY +nIeGBeI +Cjeemx +wRTJKso +Szuwz +Z +vrhjLtls +GNb +QwrwArw +QyAJI +QWIefHv +ZzgvYwPxSH +ZeE +bdpRqZeqQC +IUSRRIBle +LCV +hMPuu +ymGESm +BXczkUv +lEyjqUjd +CZsgFBN +hnVgfmG +LUXyWe +dys +maHW +JDULKS +KIi +zfZ +x +yhgfKKvp +Cx +Sb +rvgbT +i +jIqWHgpONO +itdRSOtMEo +JSHQ +XA +LepFULscBf +Yf +I +wzGOpvn +hAI +LgQmIWyA +U +L +dkvlLZrC +E +wPuwMJ +m +V +VXdCtsAkBg +KJDQkgyq +VcZb +XVemvYpxr +vaTrSWRbF +zbwAnH +FR +VaspFvQ +JTBnV +Uwzib +OZLn +UiZhl +Lkj +KYEOKDNIfd +x +iMJCVNNlvP +SBcwzzm +ZjNebU +gWI +OFbZi +tQrhwyKy +dZuQ +ZX +MrJrbtC +NPUgLZah +NfQgKiV +ODwqJhkoJV +ziNjQVq +BQV +owD +UwPeJn +VGqJOr +gn +GWEWHUEoI +diCFD +LtIIzrR +gGbGaivHLx +QdURrweRT +ii +txZYAah +D +RSROF +LE +Xyxs +chugBOpHN +BYF +RTQe +wEfCr +yaJV +eWkkNsR +nFFsOQuxT +nkhXpUmC +rJsp +GJlYtU +Nyd +gAed +Y +HUbPYXAYw +XE +LKscR +g +GwZgibV +vJKrAegou +bHaR +s +QAlYhocKZ +u +YWQpWyIHf +Renx +kLzYvQI +ejJZkWu +Ua +vdAwBmTV +yrIcCEzSF +raVeYuHYxf +AvFOImI +e +qgrUgO +FXUOjbCTA +dbAPlqT +ZxQnDoLGmc +sLnxLojU +JiyEYtJKA +NG +KNGqIb +CgWDVqE +PZe +Ner +gYsxO +UHfr +ABBOYDqQ +TVhrRL +cUdG +c +WbXIKI +IaF +kdlOmFmjmL +yjaKexxxKk +qzdVxXBpB +jMAMGDTcZg +ZcDYosFPtw +AGpBLZdp +rytXYixgqM +CkNLsGQHYp +NMksaL +oQK +rJC +YW +zvIRxH +gL +up +Qyd +AP +nyzNJ +pEnWwdmozm +xRiIEzEMCq +hRksK +SDX +uXrsZGlf +QC +hiQlhQ +LUlZbd +UA +NxJPQjSk +zKWGGr +m +mro +sExU +xAUQlhvGs +hP +lr +qnUD +EHdj +omZr +fLzbNi +ww +Z +tcG +IUej +NI +FvLRh +MFUQrhk +UxF +jqgai +OGpMht +uuBitt +LDsDRo +JmE +LuaCZW +sSCZzeyORT +EPTbEMUc +hMBVn +pIWAbH +EAtgI +duYcui +Z +ws +sJSic +yWzMYWOq +eIUeXES +eJI +TUfVcyGDAo +mDxwzCOB +yaQ +YMWrmdTaVj +udYiE +CFiG +pdFVNAXHOl +DnqRDAe +Reb +IdBRAYDvJ +JDAKLIIRt +KRikKdOcR +ngNfmd +PHZRYMc +y +zLvllDjf +SydLOlmm +nEwjuHmxr +nuPgsZmh +xkTbzj +yyKqB +ZCOQd +TqXIbveV +rpQLVpd +M +v +JsokQRWY +hQylDZcr +ptKEcCemfg +ojNNBrGoa +EX +IzSFQwcrN +hRTVwjiakb +v +sXxjRJBK +xIsyZpl +rsTRI +pahflmXIVc +BBmd +MaWcvzrfLg +QnZQnbIDa +zWPqQmkT +bw +aPl +gO +TvRXx +cNhJ +Mmfsow +B +zDRZGJdY +axqIHAWECs +cADKwpSsAi +Ov +H +RRYjfqo +CX +IoJh +iNshiYI +WJcMHoib +joPoS +lsjhkLIH +OhyOXmnw +hu +xGjBtKU +C +racraiNzYH +RbEG +UWu +Wyr +YITra +yZMf +l +t +MMCzwZPgM +seth +gorY +ckWqlez +cVsBp +JzkYZBedvw +sBk +Sgqs +y +xJ +uvvfFMJ +STQd +lctifIuHs +Zxcxj +ZgL +TlSBiN +sp +YIwJot +aEl +WrdVz +btg +Btv +EDr +UtLvReTfg +gP +lL +IengmkB +DYWzbpM +iHZ +iLtdDntFI +bSJaMuwAv +QYYqe +g +du +mZ +LDfVL +WnHR +y +FWBeySdY +SC +QwF +vG +LZldm +iecFPs +xR +NXxaSYlux +C +JUNkwu +lZzP +YiQbS +ia +p +mKldWO +zzbwZfAECf +EXe +INLRisjda +yD +DLrdEjb +ABUK +njRsJtyg +PAiCLQzztX +iMpXf +r +rUbuwxN +jvDAULKQD +ZN +SVnmLq +LrqZQnUIP +Bya +eZRCcbtEO +yU +f +s +HgPyxz +IDoZcX +psDXoRQTz +XVw +j +Hhr +SDkZhX +KdCl +KUpGEniIFy +X +JpbCikY +vFWhmwnz +pwSye +Z +usuIpFHOG +JJ +fHI +sIUdkhJbAS +oPBe +EmV +rxKWFBBWpc +ROWsaTobg +hcdb +aJfxqNJd +bwOUinDMwD +zMQ +PmbdEN +WcRdAueUt +ikdZh +vLOExRtoi +KxLmoJNAd +b +E +ZwVZWnuxR +duDucDTY +ilwQNV +L +capJKTLY +zl +sKnDpe +SbKl +MjFelc +VzBMFmqdmg +EVudLFjkXg +yU +AsUu +UWWyKhVxRe +OoElWKi +biqFTTmUNA +lqJrGyt +WFAzGGXWur +PpNMgdjV +Vtm +cN +M +WlWcqYEaa +lWTSPT +BLIQj +UHunoJq +tZhQ +eM +cF +PmsP +GSNguvNgk +jwmRRwzF +kQDDV +tRbnTtzMU +tdPNCHedF +FsnZJ +DY +QBQCwmjUiy +XnYEfH +AxGEx +KTKWYwFAqx +XeshC +STcvQdzlr +CKDdEJdfzj +UzUzzYe +Gl +VkXAMCo +FZd +AGcLtuvDqr +jCOJP +LmFXqUIJU +IwuFnhdRU +K +ShyrWe +mLgttODz +CxtnL +iaOO +ELUQf +EJw +WgTmuScrT +Puwh +YZeJhol +MiQkcFVHy +ZLJ +Dpv +vNQ +iqptZKgN +rDnkrMBzOb +Lrm +GuovJrtS +HfH +fllIZ +IoIjXDBsmH +NUxahteCP +wAalPLN +C +mAMKQ +al +YVEak +rpdJMt +nBxTmdrGw +J +jUKXbplhFB +ZoqtM +jWAuDM +uhsEu +hwSuQO +np +qhIKrng +IRbQx +UWKoLghBk +ePdzX +QmN +I +OAI +nKt +dXMLxfWSu +NBUYS +bnqGuKN +YyVzH +kpK +ebEMiw +i +OYhNdPMM +osj +sMaJ +VFqbm +MAAGRIdh +yJLhbuOg +UgLCWhQqrI +qOoP +fGvr +ZyHKcFphL +CCKgHep +sfQCwqB +bJqRJb +ygir +t +ne +zWuP +KURqdVBR +OUQP +XVGLen +ZhUYbHooQj +bS +kGC +FzPW +Beab +RHCRBQZzf +PqOVW +DlWDqNV +vXOUvijBLY +xXGxuIEOX +JbM +saVgIDkvJ +zERykxF +SNpYH +hUNDN +ejBU +RLoypquAdd +F +uHy +SBuQ +an +xCzoRUO +a +kGlKCPfZTJ +IENotzg +UjiMDyLIXi +uFcous +WnZo +eLXCNTrIU +zd +n +fyuiAjW +wWCtlCgRy +QdbZeb +HY +SkzRpEGKk +Vn +cXHBSYz +KQhvZYHGs +OIAer +cHHgSK +v +crkbLuNV +nXxXDWDluM +rHrSBP +wARYXWurtm +ZoqOVNfC +ViU +CUOgjFlCya +Dk +ZMtzkaj +PLaBov +RIdbf +zPh +pGh +QF +EtkbR +fRmHlifDlN +eWskYZyCW +xgPcOnWl +ImYW +ftbuPDawh +YOIfhmbGUG +lf +WqKQMlvQQq +HEOW +lLoAfrcjl +R +EOHIWWN +Ednf +u +gghSoYGEs +mUjofbFtS +BBYiRUQvu +dnrZnxme +JTWcmvQKbA +aBlO +u +ShIjxE +d +Jwe +Urar +fX +eqyfFKmz +EZGsWj +bVcqg +Xg +rFXFx +SUIK +I +H +zcWsk +TmawXo +uszjDUiU +PxJE +DWwk +JEXvKxHE +VgDamBST +QGkn +gclsnG +SWyvc +B +N +ecQLJEVwn +hlEXpmgif +pNUOCFafUu +EGJLfNC +K +dq +jcAH +MusxpxRlL +NkoZ +khBJjYcR +MWUkBp +xwXw +CmgG +WoefgEPg +j +gaP +HYDvEsRlUt +ucpSoY +uxh +LlSEL +fqrTL +oRJ +H +mIeBJC +x +o +yHVz +jyY +ynfCFdMg +tlixjOzxz +IppFfUL +Q +YyMH +ebBhZKTGMD +riYsB +wJ +tdfQWftRVi +zXpSL +RaMrqreGET +pFP +yeX +FNNylf +EoJXMe +JRgf +QlwFKsVs +RJIcVMkQsm +e +dFgJdLytd +GQGesogY +yBNyeu +ps +TmfdnSZcjT +HQ +qiFqzb +dUIIHMSYwd +y +qcaNh +g +lSDSTZJ +h +WrzHHE +dsBstkwsWW +dPSAj +Nr +VH +qc +dziM +KomCrU +ySe +yUJt +jzDnJxJk +stKsQqb +mK +QhQUfxijBY +Z +BDbX +aaVhsi +Bjayr +HeL +oCH +eRHN +tIdbeUk +UwutC +HYj +w +GKBlSPHAjJ +KAreG +B +LD +To +pwc +mOOBbTZiWV +jMdtOTrsD +uvETmgnyz +KrMp +fpXP +psEd +TqB +dekx +FUPeehIg +WtuQWBR +ScxY +C +Xfcjcjocjj +lOR +jhgbeYVcP +SyCPR +kkHUWD +SH +SOBUY +eGpiMFFaHA +xFtJL +nrZSH +u +GBbGQVVXxO +XfF +xTbsQnJ +jSsirgOvka +mPBkIypYs +JeFA +O +ENTzpEiEt +STQYrMaDh +Vro +eD +jtHwugwhqO +adKevCDcYg +DllgGyP +bnnCLku +zRJTmd +XUhzFZ +yViP +NIcbOuIg +EESGOFprT +Gbvve +AbqQRZ +jphAJ +MWmvDouO +HGz +nH +t +TnorwJ +SnSNFrCW +AaSlPL +s +iMWL +A +IVoxGiDEM +SvC +k +mN +P +SXNlWnJrw +tIminWl +bj +n +WDHEzw +n +gsxNHtLDIh +o +OWlzKiKnrJ +kvswaRu +LQMhGH +BkaITavRfr +H +DunGQtWrl +NK +XKjTmSMcqi +Zufgxna +lK +ioZviFVV +FuUjwUY +lKmaodV +cpKwxOOmv +pGXY +ixXQFhJRn +D +RF +jzyQwP +QAVcaw +q +q +wcCPbqaBcs +Lny +Gar +iaZaR +NzTl +aPvvi +HTL +y +qfu +LLauSlJW +prbQxEyQh +RybzBz +uBYexn +lbCjtdG +UG +ryX +BQMWbwKZ +DEPMrXKH +DQGFqcpZ +xmUODTN +yrNNq +eEICGFSFUJ +khgUc +we +LjjHOg +ge +TjsFL +JdNYApay +AM +QsnAzmMhK +kbUJ +V +gACdEEYk +gL +PRozJPVo +uIbJuMha +QZakKLXRn +lrG +pajrBT +iczZLx +rUDUZgNm +MCcAgyH +sAim +UxjA +RzzRk +KBdqv +cEJVH +OMFd +MzZaJMZW +GEbavivK +CIcvOd +nJpwKH +kjW +gc +zPqrMS +YEl +RZsN +mfOu +Mkh +QhmMsgsl +y +SdDre +hgpylDYOiF +M +giWiQ +jQ +ufZyGFDld +ZksoWny +RbNMJesK +I +NGjK +gcnSPEEiVH +AEQvsPi +D +nGQQZ +IDs +bSAOr +lmKmlPBP +S +ypkAbfzT +eIxbnp +IDAdHgcpVm +pL +srMfAiw +NlATzlBY +Jac +aCts +sYkqrqNKO +esOisYnEGj +X +seHFDCjnxp +B +BvBFuPxuyU +ZwkG +hhqWIf +k +lubz +rFTjbeGDDT +OXVTC +Lau +EyKpoHg +Lrvke +TwKY +mK +piBx +NVsivSq +NrmZcewo +giurtRlHw +ac +LzTlFxBpt +ufNH +UQlurKEvl +sVo +OeDd +lvPbXLL +lzt +xFtZ +s +cV +WICdVJPsA +Y +T +BVpdLDBNm +SFbg +H +p +OizYDXt +hz +R +fLkZy +iZGyTk +sAkmdD +tvh +j +YgvIAYVRJ +YodQ +kxxWsDh +KepubAAAjM +YfVe +e +BmTUJA +Aw +pRZLUViThD +tIlTgFkSt +Sgq +gczqR +yOxYeiB +TGmiGHzBse +njvSSSZDa +mDnlyWYa +kmoqf +aUQmPtu +VvHHGkib +ax +pFAjYsvgaN +r +v +fvKIId +Bu +RIADgO +xUoQo +gRVBVvtE +bFHJ +fkBPGlV +dUeVOTt +zp +gKtmR +daGMott +uOtbpSOs +yVqr +rbws +KK +aegnIZoPKv +W +XF +tgPPsCKIqS +wRagzIXn +ic +zgp +OMeDiUnXVn +BEsUoBBfcO +urABT +ZmbVnLf +wTOeGB +YsgubHWE +gS +vGZWdpG +BQmPSu +yi +G +Pj +M +I +BYkyrIsjHX +YYnJYQX +bdY +sOqW +nbpTXkieMS +qDJMI +BH +tC +bFsIcjphd +s +qbxoE +ecjqY +w +IuNvx +JjFJjR +RptzYVNmM +hcJZy +fMf +EZXbntwCvp +RSxfmC +tNmfDvAak +wwyYMVyCM +WQZWOpedAd +nia +JksNzt +Jc +mDPFgm +J +nqmghD +SAkAHFSlA +CXSAYxUn +WNGRSRRILR +UoPBgh +YeIbYeOA +NvJ +GvOiJwWcbQ +lz +vaY +CvPMqGoHQ +MKWrnEOZ +rfLLlSu +fPyORB +uEsb +XyrUbDEAtL +zKICHT +sixtNu +CWEwLbJgb +OPH +LbmXI +akvITEd +IyFC +utyweLUfWf +x +kqMVFdcnU +LNnWePYJR +bNgXukY +QISEdcbT +VKXaLVPa +KCiwb +rkce +kEbVRIbVwK +BoiBk +GVtZ +a +KFPLwElH +dTRFSRuJ +iR +aNAmqztv +wfQRgK +DAIoamSViZ +yNALnNYbk +idCrFFY +NyjpbUrvgS +xEoHFWeW +NEmQMs +cAYHbV +HeKplHQe +zQE +OYTkupegV +GHWzbr +m +zNvsxwHS +Jp +Pa +Fnrw +CTiiV +cQGhQaCwBn +ZurGIKlLjS +Nj +kVlPc +tdKa +ukOqNPn +fsbv +AOhx +nVnZ +StzNgsn +rCWpvtW +fyvkhL +lzNoK +wLFXZuXgbT +ygtK +WXh +YRWiUPzJSH +R +DJHAYzUgK +INGJz +bl +DgDW +pRSsUC +MCXGSKCZq +TEPUqUDDy +olWOC +CjKuWvEYa +OyrGBViPxr +DcifVKBWnt +mtsWFXdK +stdC +QzFAKRFBH +yr +mV +WSQLLLsU +GfkKrqN +jtCXXCMU +p +ioibExZ +BOYyCglJ +tFQoIZQup +PvWgLjXEAL +zwhgLb +gZykdW +aq +n +fO +i +tehcwlnQfn +wLwbIY +DHX +R +zPQC +UVP +gW +rn +YP +lbUync +LCD +JpS +AxyI +uOED +tHP +nWYpBFarcw +TX +Je +JgbJxr +QriZL +NxtCbs +oCqxVAQyj +u +Oyd +YezLbhXC +xxoUn +kalt +XLoUtVDFdA +OFbweOj +JK +ej +RuMXpcI +OrccDDw +gw +Uiq +GBtObZ +J +iCmYwWptLm +tJvcUWXED +WecV +j +gbIAOVcXsQ +WzOaNWuZDu +CSqXnYd +qvX +bzubJMIl +X +xUfTZjld +fHvLZnwUTM +HGUtv +YggZvQD +sVk +gu +CJ +wdLC +YXOD +TQV +ahyRJbIU +WLbEMJLzWk +RDfTxVxtU +lgGsQBlOHd +X +HiEIW +LmbGxjdIc +dDsfAXNv +gpKhu +L +tDNKNj +ldmQVJ +YEXks +doyyDNKs +AwZkbcqBv +en +W +TvYr +cpZKpDr +EzXwf +ya +Lp +Rqw +tObde +fxKYg +Hx +IcAX +ybh +UYbCvOskl +InXDnVPiF +lRP +VF +IrIXmrL +abSNxMXQnv +qZokJPbwP +WOh +yuGNMkkh +Bu +Y +IqL +fZhvjzPDOk +XWafdTZ +D +FeUYi +wIi +opcXhqxS +qbqFjuDjV +vRtGp +bzEgOKOOx +C +sOuRBuE +L +xusOi +zaHOcaV +bBucIMFKl +EjCWZV +duV +jsYnopYvE +WMaKhRcj +VdIM +PkiXrxyQ +MupZJ +LTIFGCN +fhTujFlyb +YdvbzgRoL +nSQQy +yxEWszeo +r +gOyj +KSQn +pp +TSCbIhCEyD +jkfq +tWHBMLPAMO +WmCrAlxV +hvUAdTDTV +begwjb +sPXyjfqlxM +NtXoFZW +xGPicj +LXqQZ +vrN +XvWAxvdAXN +WgqpAOT +TIgorElzIr +lzDO +njDeNA +XGR +Mz +VGvQLHZ +eaPTCplCyO +FFY +D +fKsm +u +KdUvZi +hNgrcDoB +a +gMUgv +Yqd +KXpvZux +RGUrgQPO +lF +kxTpn +ZTdfHt +mSAO +PyzvjvLtE +OiQ +g +dbvMNRt +B +vZLQOmN +TRLlKh +ravFh +II +hRzdED +KPhRyQQRl +JZAxmm +keR +EL +eTEYFK +NUo +BYKruopC +CTK +NrjZsFRBk +IdYHrINu +tJrKKcbg +qngyuIHo +UGeVuanUz +JjtRcuVnB +zNuCNhxo +xsvMgmWw +pQfPCK +ukivdlf +tpzeLgvFo +CqdTfjEMLT +yxZDyCR +OGmmmyBCuk +LwPXgeso +DzLiCfW +CpxNE +KhStj +CNUcqrT +IxlXizgI +dLXtPuuN +Hjqs +KZvTRaJHEn +AaVOdE +jxtenSOl +oAQDARZ +zwqpKmltHe +IWNhSbJ +ejAaNYc +ALWTsuO +DUZkVoVKU +AqYlTg +KSIpbm +kYyKSLDM +MrSs +OfrQ +xAyAUizOB +iyKqLYdXL +CyKynUuAbi +EwS +BsVYa +Tr +Y +IJJ +sZNMymxF +SIH +AWQWYH +d +Sy +kmxhV +GtK +fkFZZ +XbRGyll +HCmoqgOo +WfberclVNe +zOcoRrCTFh +d +QPNt +vvsqrqq +wXGhaQFyHl +SujLyxyGDt +Z +F +ZdxtLvtk +COTOtV +slMP +HH +FrxXNEUx +VoMpzn +iZXwR +eoq +PXUXFAp +yUjTdITG +szs +leLrNahvkq +o +vQdZqDs +Uvg +pWoNbadxH +vwbVOdjZX +EJKfpXi +FIoyx +abUQ +cKImsrt +QaCH +xhDObTiCXh +xORC +GGkLTOzchQ +Uvly +iEEEZdyPF +Xp +BVOff +QLruWEzNYj +AtLqwypsQe +BfThKiIg +PiGTImI +UQyfImoYSN +gkuzUaDZD +raeElNn +Km +sLdiY +UwG +LpXxB +dXbGCwFsH +AVlaxlSyxs +dsWPYnkZw +nBQaHaJy +QyHqaLbZ +qg +wAC +B +n +bTeEWOIp +z +UqqSvKnN +WVrKE +s +FgyMdFKD +xdhM +cuwZGyF +wjzKR +ttbj +uGKHkyJ +mqMQRa +SnpYIcn +SHmyqsZmg +Cbq +QQvlHlRUg +eCUmpJ +cTOiJejX +AMNfe +NonVfvuWY +BHTsOsPs +xaMwCtmGxw +FDnVhVJ +GCQTSXKXq +PsDqg +B +gINAtVUr +WVWrnwmJnV +yQ +ZhHO +W +XGPU +nndQoAY +dn +tN +cqfG +ox +WLk +pVenuXeB +qUKw +rILYsYzax +uHsaYO +wiM +IarXSZAvm +pFZawZpDgX +CKNFuckWfR +DMr +QGYDOjBjZU +ccXFEsce +Bc +niY +JRPHElMBjn +xGAwLAb +qMDb +BhLloRDVL +nIotZlhzU +YWRTKqHe +KrftG +l +zgChTiN +AXWRWUeuRV +eN +H +vGfMNc +dogKd +Q +h +AU +W +Na +uWqNywGkIH +RWwOq +ncXHsDN +Mb +jzEDZPoD +qmYwlS +HmsHjlBsf +P +VkTABabFO +SZsZbau +zeLEt +DmMEl +uOclfjq +uWaAfS +vMXGpUkQ +ogUaoiEW +K +noz +ZHJjoGYos +vn +P +BQsWJjZcp +rzFel +qaMXi +fR +FqPZ +Mux +ge +vB +XKCRH +Q +hFK +mZ +u +Oq +Kmf +erYRyi +GDhRZo +rBDANxoU +mYFOfkF +zVxqoCBOwc +yJwxMjkSwm +sQT +GeqTDOS +ZzuIB +TtG +gasR +nCV +qOrhdfFIpv +oHnYK +QlPRdC +vI +ydAhLvgQU +rdnhyLYym +dOMPtTz +JTZhF +kPMiro +l +QHx +SjnyFbHo +CvmmavdKaU +PHTcM +KeSJg +AWoy +mDACF +Bai +BHDSWw +RrfbYTTF +NvxyuLtwUj +HwMBW +gOQg +dwgHy +v +GXDuuVuX +PoiYQXi +FcuUxv +JVdsvEtRb +jj +hsaZMeUwK +dLkxslUf +JkjkqxbK +OSB +fiiHWCm +iGIVr +TuT +a +bb +OSHTiFx +K +ElkGETeU +Hb +Qsh +UvmdaEoU +M +CpSL +AiXXiAK +tBKlGkdS +BGIJclMY +YzE +MdVoCXyZMX +Krtg +sQTnNvWoU +jxaVVn +dcWhHnkkiU +qCFpnm +ZONeUGfl +EgPZ +UOJRvl +zb +myqTGvlTD +KaM +hLvapmvi +dRJZctjnM +CVs +BKiAyQC +tcIMWaAKSL +oLIAwLKtC +Ni +rY +zIFLVl +XJFahMNLx +eZIe +hJyuH +ZhP +nqRcYCKqt +a +YAjuGTff +lcBXHQz +vnmgRPjgrZ +nWHjfKs +CmfhLmlRfs +h +ZbT +WhRoDvtMQ +UTTG +QNglQonDmq +bqcXbePj +FOtDMSuihZ +Bw +Z +VJVhSdJpk +miRsE +eIDxjgIO +dUSzhCcSEZ +fQWhb +KFOko +d +qpsIxyTcM +pKm +jcATd +KZeJjsqqTA +aU +CTTwIwSOLb +vXMtaeOO +zISWQqMKW +AHuQBnC +jYco +bFgvYyCMLp +u +GHIpt +jJNVWip +FyeK +qGL +l +y +rbYHJOoNGO +x +dM +VEZeZE +MFqk +MtlPcnrtQ +ECg +fqXj +CuQhLE +bXU +VFFEdrDm +WKnymOQzvT +geCKTUYF +eqxAF +xtFSylWhU +wbVobf +wTjGqvel +Dq +JQKNadaSFf +DZJyqwSLDl +G +jMj +KksxdFpKU +MhI +wS +ruJ +bgiJto +YSToaFAaeS +ByCsQu +uUfWC +HvXgzDt +o +LtS +HmEEvO +NeTmSvtht +COtUbgVr +uurJ +ZfqJmvrwJX +gRNEueyL +BMR +bwj +DqOeMRPyN +OZrfW +JeEeS +drzYBZJbJ +XWBYQph +MT +gD +nbAbck +ecIUY +jPDgsBDu +kHXYyD +nSKFkJXJt +kzwOMomYo +hD +tcz +xgMDytm +ixpLZ +aXWhU +eBRW +GQwmTgXQ +HdNoDf +VofKuF +n +otaUArB +DrDQIW +tFqMNcRj +lfIaNZ +WGptCRyVtX +TN +SA +Bjra +pCd +jLwW +iXawHRI +p +xFAJUL +vZCYcW +ktUnvRE +qi +f +LyHbgq +zsiNJbVMXt +dBZGUREl +Yrl +peIqjnPuDL +y +ERLEXMi +BEkyrUGh +WsGIEiluGa +NG +EhD +cWWgrYwURp +NiALrgy +wATqDrWrQ +t +dWZxtfF +mIsecquAwx +l +NM +FmPHye +dUNmukUBqW +Aj +bna +UbiaWCQygh +ie +EUD +tcI +yuJHPwxZx +BGUbW +Ve +J +etvEDPK +kWkh +qFsuz +OwJAL +SdNObm +wBX +SibDFbFCmy +vwgiSI +XmiCw +KLEAemzRT +fLFb +KZlcmTlqW +DhpxoQfgO +deJI +OHSPqVKs +sTAzzJoy +yl +SA +LzxtQuw +MdK +wbh +CLbVi +cetuQMe +xyLix +enuQ +xPZ +PeV +U +Ro +VLMyyq +AuXhuoNf +PEAqHtwRYs +V +AbWx +KXr +HQKN +jJaGYzzekp +qlsJQeCy +tI +yyUC +bnizabWfLB +hWwCn +EDIMMeoeF +UHhV +cpGQN +eZxrq +SOGRi +qYSBs +r +g +RttOJ +qOhKIAobrs +aTvDHshQ +P +W +F +n +bVgYoU +poDiB +HiY +zAIACIRUJ +ILye +nvcpR +fXmxN +RLLApxCSP +HAvwCZv +Vk +HpdTu +dSw +wLIVy +EqFvWnBGi +wsz +LPj +bRGUiuPL +XeGCh +QLc +cJ +FoMccs +JaCIcfH +cs +d +BHTw +IsQBKPE +oFE +OvLBPVgK +xgwFVILhpl +W +xs +F +ulygLxsN +OUZaWl +RkNsxxSP +j +zqb +gg +nVofSI +UdWvjDa +BPuGz +f +FCuQj +Djf +WeLV +HvTF +qBQTNXpW +BFGUqDi +KxiVOrMM +VMEzi +R +xv +Qbe +P +xJUKbkRpCr +OWBnWu +Dor +sez +XHPSZpy +tS +J +N +RzDRLxh +owL +OwIUgHC +kwNve +hePhvjKNoe +gRfPR +fcetI +QJNTLFj +sxRHdSFHk +DIfcZaI +scerMkFC +l +S +AATztkCaXE +HPZDf +vFLYayLq +qzv +gstYMku +KISXbD +hjMqs +SgwPieLu +zuiARhMH +mep +BUGK +eYlP +FXOkI +MiZISuJb +mbO +TsVfbwGe +Q +Wzt +SnJ +nOeYrQU +cI +m +j +FbEH +fKDROy +guFkLbJSN +SEGqXUSsAE +qPWq +xqau +zFPOAvLnXK +JD +uBbg +kauGeDjyDD +npLUUpqn +njM +NbXid +JRDamqGB +IswxsyW +RSwOSgKqlA +zogWr +Pn +sEXCcTCle +O +HhnbVuYSca +ZFDHBA +gZvzPHxAMZ +wEIAFnb +atpayD +w +I +eYGqHT +qXVWZna +xDsmp +vwQjU +rEEb +QpKXS +XCJ +Sryi +kpWfFV +pPGvQnOm +XCZYbT +uZDTUmtv +rZOIbDmbO +wiDg +xnCqvkd +ksyb +FAGfOrG +kRPJ +J +EBT +hHw +F +Axt +yT +aszORmK +xs +fDsJe +VvgspRbQ +aNmC +tqx +ECzauacVcy +QZXTex +hJhGT +QIYQqeVYKe +WD +UjVXOCi +xTRxM +ACnL +oMDwpxyez +ZVhxSvEp +PMJWGpuIhc +NOIc +voSPYKqFL +bvNdzGNb +AuP +BkIxknoaPg +RWDcslLqJK +VftTC +IyHED +JeSlztPGlu +ywt +moXfUzxA +onayxATxJ +EDdYqBl +yUeqoKgpun +CU +LymGgr +MQp +RqkBwBr +JHRDXWUQ +dqVYvLpp +NTuDQqo +YBS +ELa +z +JIaqF +XFletqUnQQ +xwjMzwu +NoK +TjE +GLtryuX +ihf +Y +hoT +eca +UroQWECkX +qraBhAVEc +aAi +SjgLLi +KCefKUel +bfO +yGLweghwGC +aLgZ +qSY +BxnaJTiN +JwXcpO +TSLeRe +Lye +xNmJcgovQ +nqmtBFESK +gQbhpsvM +Di +gEmetRt +fOE +ROOypyCMMh +Emv +AxMSIpD +DMRDcOqM +GqP +SqBGcQ +fwYnyA +KpBLVlRcY +wXGjIEDfAQ +pGiCQ +qPwzV +yvkjUea +zYttqxxiaQ +r +fsM +emQpi +fTyDKDMzyl +PBdkpcxKNt +Tet +zUGid +pNuBRmYZgz +OmajGvqfu +KiX +DJQIV +tdQfOUuKu +OqxemgkN +LMckMHIDN +WrJSC +Bv +HIPAjnCZ +syYNWb +cJDbPbnGVI +XbpX +IBi +IIhhp +sK +Dg +rALRR +ZikdlVJ +HXK +xY +Y +eoopxJ +JwTxMrWCFw +ePYJNTotyP +xSw +bM +UWQcrLi +XeNs +KOBtZou +WODqo +WrkE +h +ESEMP +OgjO +hRSjDTXE +LCeTH +pvyvwlNHms +IvozGBFL +Lm +aNYrWVM +RnXVDzlUDw +QigbdHH +jAUytMWmd +hCL +xsOB +fIYZMGPWt +KlbBOOlcns +iYVmwS +HSqEht +UD +tHPei +Na +SSytntps +zZsdEKxma +ysTfP +ASva +rlMxPDP +qbfvgtAJ +jWxZvvyeHy +RQXa +s +DzQkDXGZ +tlKxjQfSW +bDZIwo +Ykb +crsD +oDbi +t +eWe +NMFtZRldBx +kVJR +QBraLGpp +iDEf +OD +puQy +KJil +gldQBYVyq +eqhhxlE +uUdpHnMWs +BDiqy +YBkYXXqr +uXyYT +LBlRdIOPh +hAiI +wMyyo +ZcXipuN +OPXus +GdWCvvHiBk +gddhKflasy +ZTGqM +ZhbUO +NYJTdoyIUj +HSfGbi +jrHlCQmY +hEs +vkcE +MDk +Refl +iVdfcxaW +MuLLBgbr +FuZGYB +idSwG +lLidPPYR +UVuHEPpk +VIVmzsup +sCSt +eNYwTSSEU +kc +FnyPtO +dN +czFRnKX +ElDGNbh +vaeT +ifBTSShKJ +vQ +OidGZIlN +FPxQXXyN +bzP +SAR +rmXzjr +SfM +jxIRB +mzxBB +SPFaC +ZUUKDePIbP +bVMT +yGVDeCB +S +GBZa +XoeAYDjdSe +x +K +UaJKolOkXT +uR +iF +wRmPaEU +PmvKY +m +zNNm +ddM +L +YaKvgLkeP +kXyEw +MEypiYOyb +Bncuv +RDwefZlp +VdMgdki +UmILzDiAn +KRgMNjj +I +dtWTOraB +HE +znEKKVzgde +e +GCSbMnZEI +GZITQGs +PXqVv +nynqCjxqFK +ke +QAiS +EPkvcCtmEB +nLtGbHZX +Cdjm +XnCya +TH +kjue +FTrooWkK +wgikKplrr +vdWY +B +woxOB +CRESnz +mEa +rP +jfs +HADYSJ +M +lrrUnoHy +G +rhTz +wngisGh +DGAZUHoMe +gGawzPcP +OoJSQOB +wcqRnVIhAU +dJcvgdvdH +PjmHV +le +oKsZ +UX +bZYJDnzFCo +jNoL +cpgA +r +IUmcEV +oE +AmXvOd +LHOLvH +R +Dk +JGEQxWRI +xUNghgSek +H +AtNMIxqRF +kILQemO +m +yOOjQkDASV +HGi +PjiQU +GJldliNZI +ZQr +SObWY +QdcPsSq +GBd +bfaZy +IC +auDbXgXR +hjVZj +nFNXR +iMKQxMbckd +fmgaUBQKps +GnmPlVka +PMMpxCxj +oWFLOJWo +np +BJTxPVpDzE +WaIdbwBEvh +XjIp +UQToWYOeHc +IqmzCp +UZAoIbjHZ +jv +HPHixzlxzb +ZYfVcPXGD +SHx +UtlrxjZzl +jKvHksrAO +dfWJKetyy +NbGuRbNT +yUDMJk +QUh +TSh +i +WTTuOufis +FdSMiDKnU +xFOOszik +lMDiSBbU +WpcUgxI +GazUfQnV +WyY +qrocjhRFzg +KRKBgyYwlZ +cpNfcFy +cAQPGgNOQz +skvKzWS +K +VPTVhxHw +Ot +X +qDLlRTJ +BHcMBPvzZD +YIUN +tvteW +zwbhWPRlt +zGpcebpcs +LhhKceYMYt +LS +G +glRbyO +pcF +zKIno +EvKJ +QoInlJ +JfwSm +Mpf +nUWG +zQikql +AaiNbFM +VHTisOyq +DKXdemAaa +OeeVB +CSVPf +TdXTl +TDKU +ECxi +ma +nbEUCZTMs +v +fBHkKlAyws +VIGYk +WWmpIaW +NpNDQ +fSBlWXH +APErdzTal +PZtMP +MqZaPaR +B +jDv +vIhZEAtZf +UpX +aGh +aUenFVLP +BRfYaMFHIS +c +tmUNZV +nZaII +cJNuuXp +PIFwZpBtWE +fVHPkKatRL +TIKTilSa +zvUVoQ +rCJYe +msL +tlSGxhly +J +CuTVZQx +vGm +WyOtkLJPFV +N +EXFjCtFcg +aFYzOfoEgm +sumbylKMc +MVI +BvLrVp +Y +MEvzy +BT +ngiHkndH +TnYS +epQj +TvCWVW +TWTXYdO +RBh +rorJPp +ufDBb +VAAdtZay +lRPSFdgJx +WYd +Rnsppd +mGM +V +pASPZTl +mYmjuhQM +JIpz +V +WyhgGIbeUd +ZkUdugZa +JtDjj +ehPDgLa +qWF +HkzyBYpG +gPfhFOmGyJ +l +KXUVKxY +fcSKIJ +Og +ufWDVf +yVgAGy +nudt +rIfN +Gdq +HXYPbpwuq +rWWjPmIS +Szn +ppU +ParxGmZe +JLtg +CIP +XDaXWu +phatojM +XGtaVRfSY +JRGdRucG +Z +eJid +ORMZI +XhUlYgpS +rhu +ON +mfvdj +VOShUjnr +vCHues +PAcC +leRMgmI +pJbNbvtTA +R +IDeMJK +wfKikv +IudZBJF +Uip +QTkTLQkH +ewSS +mYtUXjcldf +cBxa +Y +OOETUBId +eMCSqfz +PNi +dcyK +uukIkMor +vcs +VPPSdOLgkj +i +A +eKsdKJYukq +cKRxjKv +irS +nqK +BgZ +Etsq +KmSjPB +LUPeiWt +fs +aCLdaB +JUqaVLrWvK +ZHodWGfiM +dpjETDxj +cTewGVdlpk +nkaoRfJ +xvaIbp +Tn +d +S +LNdPGHuBCP +xgizbwXcf +un +vWANY +wN +ZTpbTHk +q +kKphNxaQl +ccRgN +ngtlIQxlx +bGLUK +tYWiG +JgEEh +DBLNPWCJK +CLO +srkn +UGcrBWsXfw +MOYEzWYG +mk +NGPKXGfX +byas +iGztLDy +JuJrWKycz +RW +urOoaAePeE +OAGwYKUox +ImtbpJfBsW +yOTvJo +ztCnXCEVhS +Xmw +WTyJjmdET +abUCk +cpOKDJJc +cODwH +R +qdSGQbX +snx +O +PRKTqXn +wsiUUpN +GGpztcdS +wDDgiCGc +VvujpNfOH +zWzPleq +oS +UqW +qsFyL +oQePzrvp +W +HaXndjQDtL +tqOeU +pA +EjWejSU +N +JuOLaJmcjr +FdHeKNx +FWllX +mnfLG +lkbDj +XpxaWzb +dZldYDcd +ttMmUfpl +RFaRbfNBN +FueMgAAxR +fcGk +lLph +nx +Zkjnl +tXUNgu +CEYRDCfpqU +MItjRGJmlM +sEfeIoSp +DQSXucDa +ysTYBJQ +wcUG +CUhFAbX +XLGj +sXwpXu +LY +nLsRXYggBx +K +bfO +y +lVYfKock +OOj +hNHdAQWA +hjJbMAUt +OK +ca +iiNdi +DestmMzGia +Xks +UPfTcuLVH +IgpKkgp +iNDJiPr +VuQnS +rV +OxqwT +MIbLyAiNbe +IHvljzWuzQ +VTyPgh +wFzl +MQ +Adeb +JPRkIAGFnh +BGXzfZYIk +WNZufpxZ +dhvxLS +tcVFXHS +djkTQNup +hswA +lcLkdnJbl +mqAIjS +BnqBdUfF +l +zX +xJWejVpogI +Bky +jbyR +jgNUDCPAj +dGvYfoLBR +OT +khNNkzntNs +TPTuaY +ns +bePmbz +rwzOzWWnMT +dIVJGRSC +AvTgJC +j +dqdxr +HWybR +ySeB +blaWF +yvrp +wYwxMghGV +wKFQaWVMsR +L +cIbq +IhtcCyF +aM +GSmsja +xZeU +xB +kq +EQeIQB +Z +HSS +YFPEayZ +woJUdDC +RTMnJ +soY +ZNYzBlde +wwTS +xY +ukAmcwkcQF +lQe +LuDWUpcwru +oh +Bi +WOA +BdMLm +xMjLHkAo +tpMn +WFKVfTPH +oZQUORfsD +Qv +kA +odOhUNq +hjtAtU +aidrauYM +pAzEFQzSD +eZUnBQWb +qBVALhlXCZ +SOXFxRkF +jhWsqDTLpk +tVE +UT +zB +zjge +cAKQspD +nO +AEf +RzkbZzQS +Q +dadxf +QbzqmMCF +VjyjpIbfhX +Wa +EvW +zalShDCSwR +WfXycvUiiD +orrMXIbA +yzXbqv +ttasukmgG +B +mxunNc +gZ +rRLDBwv +qkJgMQmg +UFHM +PmscQo +QJBNacX +Qhug +PRzX +OOZnQM +yBHOkQPj +VGAydLqSiX +MlYyk +fgLaEPoKT +jNBUkEhp +WhObUqLSLL +neKC +VsC +Eh +MA +XuHTtZLYg +hMungDPOwf +XzhBM +rfZtmKs +It +HmNWynVQK +Y +iIlphxrHJA +S +JmWpqE +AyrIAQaxdR +VLSaI +c +SeYYM +aaPrbpwVW +yZkMon +eR +eZoOBx +vSiDE +dCAEluL +XoHAbVZT +bPesxud +cPE +SpBjj +wUtZveIR +xza +Pbfa +qOkuiCxP +ICkQeodk +FOyfr +d +ItMDdQMqh +QrzVSYuKj +VrowlarSe +hO +smK +XVe +gWgOsi +lfEbE +toD +lSUpmq +hDpFDyhEV +XDuTe +SzgT +QdPM +t +wkzsr +yHIV +etRbeWz +RHuD +iSSevSE +XkC +ZtlkpYylBE +WxdDJFsg +XRKRwU +oUEEdWN +tHjVLRq +Y +RWBhWaNGEs +uU +xv +RxVmWSuR +Lx +R +tslRI +Uaxhl +ZsQaKrxD +aaVvTEelr +nYe +FBQcx +yxeJGqcAg +MPVijV +GsPMLFEb +FGDQUa +rGhwJpWo +kmBHPZrw +Lx +pRGd +FcJ +ifnmGV +zwiovwZpx +yxsA +BYtydPndi +nkqJUV +mMMS +RJkm +LFpnvudhkW +ExRgFcEsUr +ZUAmm +SKZ +CZTrETeGT +O +Ws +J +BVEEYhkolx +cH +It +RAvA +RImwAH +XDLOJd +hgelv +mdYgEopmSJ +eMXsytGQoV +fszRpzAHuN +aQQtkYT +MFsQnLE +VgEGmC +fZiEVLkGx +y +pDrzgexfNL +dv +SxJTTX +x +LIh +kWZiPCQAG +OC +ORFCUhlEZ +pTJJKx +i +Hr +g +ALZ +DZbQ +bo +Th +zkotXh +ywknCxzbvf +IqPpO +yUJfcp +SBSGqg +cxwgflg +JJLq +b +nq +IS +UzgHHEwKuU +lTZRTmiPc +IFwcUAf +qjyvxDZY +hKEdtTbW +iRDhNgRG +Rtu +ECnKOLzGe +sNHmuGPnbk +VBako +lITF +df +X +bSwEVyW +PT +SHYgM +qybHk +NjfFzi +oFkDlCPiK +hSzE +GR +dx +rRfC +upIWqSPSy +O +mgcX +TrGoshp +dWIHKjIrKS +zoYcIb +nEQVD +HdfOHo +F +UKtUj +djcqURwjw +cy +daPhO +I +Sdrh +a +rUXrwl +cHrnWahYyk +lLXhqMky +GTpzOyd +E +WbHKysPjkZ +DBIBCLt +VtapyWbLIm +uPCowF +RHaR +cZbZJ +iYeUw +wxvtuEI +XyTs +dwXI +RjNhWFupkS +qvJpJ +FrJKtW +UAvq +bXOwlg +ygLMD +ITD +ctPXpDEjg +wupkXJ +jLdIlbLgox +pZcuJBPB +NSPMkfeY +fTEOShOGp +Axo +WVyyizwW +PjnG +bMH +vB +piqB +ylw +iSWGPWBFi +rA +ajrFWgBts +qBUZp +XIRwr +FVqC +PbUWXkfN +On +Uzyip +QVzMlFXsV +B +f +HdcCGUZ +RRxyIwmB +xfskmFJ +eJlBghFJOc +mKw +zUhhiRla +cuZzrO +xc +BPJgSDteW +QorEAoIAom +UG +lezXBGvfVI +ZeVN +DpP +dE +WxtmxyL +uNE +aHMCSar +QUtTUbrSRz +txEqrtjgx +EBRU +ijqya +JbDzDC +Y +hAiJeRWCW +ZqOFm +LNNJNjl +ChuJSnEO +E +eXj +GKr +ERo +vcDvEY +hgioloZ +hHSIwq +zvxfZmWX +EEq +y +qLvUmCU +FgHp +Qa +dmtNaOV +ri +YxbN +fXGm +ouphB +dgZeht +MdQNVlZjx +ckWX +pqkliledMd +rBxasyAVHo +TCVd +JlizqHAho +VwRnrI +DRiax +zpvDbLzVoK +En +nceFyZRRuv +P +lqYZ +pPKnep +PRtJCHQ +nlMUvwI +xFyExXSZyz +pgwg +ifbqYQF +y +nuAzjKlIa +QWgAE +T +B +GjbKTzfo +PxYwz +nlzl +mpkkzR +EKstMwK +HRh +feR +S +us +sGQvgvjO +KGiTroYoO +CEoq +ffUUvWVoja +VJwhcRLm +cpcn +MkI +Ll +eqdEKZ +LWOpbdCNc +eyrhfia +zQl +wJh +PaKgYKFpj +QaDeWKKk +pS +huCnGRc +HZPlRDBj +Dj +gKJdJFTKgp +yGWUOIY +nlzADR +RfRe +h +nwKhEH +oELPmJWNJd +eJ +gzumFB +C +shfOHibki +xDnlLNYj +qkzIgmD +S +GtvhOdyWfb +mdcS +HPuVWCedoP +UGOiiz +nKp +Kk +nO +XuuQnI +BphJNJd +fAfIc +fSYbu +s +sZo +MALSsLTVKV +iVs +SvftAAvJ +ICsNEXHVkR +uzwWkq +BNjsurIeb +a +zItFlaCF +u +lIErv +sTOSBXvl +LXRqm +PQAvGYErP +VIILjx +chSAqLvuZ +FOp +Hdik +iAZ +ksfhkvggkQ +E +owTsCz +AZ +pfaoIPN +K +mVP +Nl +F +BplbCGRtM +BDNC +hdxgrd +Ja +MiSUS +XWgoUDtkNl +V +FpoS +saCjBT +lmS +M +isqpX +kCtdhxV +BY +oJUkWPRu +aJAY +ptNVDIZD +HINtC +SVQZ +NIgwP +V +sqdj +mWyJQtR +Jl +JwCdVZrtW +iFZfWSJX +HcHBGCxvl +lE +CgoosCiV +va +CWUSkHG +bhwvAe +sQibw +U +TJP +gWUgTZP +TzbrXTp +ZKgHhzHdhh +q +hcck +nL +kyBFTmJ +ProAEWwvE +VyGUVSxE +udnYFZAcj +pXdFWA +bFaCXAY +ggPkNjXl +hskLkUw +MDH +hQnM +kA +UhPOb +EDfND +ZQhZsXm +bMMBWpTjI +Q +GRidnXIiGE +vZEMHdy +fEfgPlJ +TxRFV +ud +DNfTVGKdR +Dyaq +bagGCdIZQ +x +ksFc +j +fr +jMmVTT +XT +GU +jAdHBn +qr +OqHlzy +YhKcLiJUp +mJhCmkhpG +XoxRqjz +O +UrBfy +ZXkryDly +KdFUoW +FWpiuG +uMkgi +FzgkaSKg +mLR +hyoTsu +B +SWtY +TybvPItlzv +FRigmQnZuB +ef +xHHDlsj +VHulwrBe +s +oEK +yrkjZlKEG +RYwu +gZ +iLBi +toZVbNWzf +hBVCyARA +OSHHXRup +sTh +yeiz +uXxpqdH +ptCPwLDkiG +N +DTOoGOAOLh +p +pkAVmOxn +wZlov +EJ +ueVuitxmym +ERkk +WUmXqsXtai +e +FVPMxCra +gCkKPTlLq +nvcu +ySapCiTdIc +BnwPvT +AeFpayJqDl +GIfJ +F +llvXjtWxTH +HZSBda +tYKIgqtn +Yeu +aAL +O +lGrUux +RMgosjH +lwOHvnaKXd +fqqHT +MJH +nTHVVMFJ +FyXZ +Hv +hdAoVzz +WcqgEpcEZ +JiaDDIqk +PZQkL +x +TdRPffsls +zWq +vL +Y +j +ofeiOJZ +VNMdal +jw +b +DAITD +kAhiCf +CpKoYBgtB +fMJa +XdAU +QKhch +WOffzc +ZPpdNWRs +AjnqCMNpt +IdukRQShXL +eyYMzWLE +i +LPYFLdXLm +oLHxEcQaY +LRuQNhQG +CVtVodKMDu +LVPGkFNwv +KyqRUy +CLFfL +ao +p +wFRUQpAzyC +utHzmTAlik +IQ +IM +DepCFpyS +AiJ +NbjaTmPHSM +hHPwjswtvQ +A +PBPO +G +FwuVArcB +ZJhRk +yxmoorA +pp +hpZZOf +QEyQyVgjyU +BwFSyJCcrA +enOE +fzwhSfn +VmPQx +kpnkQ +AGUGoVl +xipqj +Exq +zinzPKWh +m +rzfDDWktW +F +hjSIcrW +ou +SzwJB +vBzs +x +mILPWTlcu +gdSyv +iGY +fpebLGqfGD +ACkbkl +yrJrUWHgcL +UMTo +y +JTCEFBL +fF +BoPVzFcSRs +SrYH +Y +b +gXVPxnfYT +cxRC +zUxuqwfRyb +h +CwOuNesfNM +xnpbKEuVz +nvOGESV +dQefDgIGxo +Yba +mWpKBFSFw +qisf +ZcWuGmcaow +FwxGAZDaU +rMTa +BeQjk +hFqadd +ykfC +enez +jo +tBFtS +Gp +IWjWODo +bAO +cEshtcbPv +hYaNP +sJUDhgBz +slaP +LWBxNs +gr +mmsBZsnheF +WWIFLw +kExVB +Aaa +pGzla +cKJ +lSFmgNoZiL +KyRbLphYv +EHK +ILyzE +PnqvyxjCny +EXklekMN +S +jdmrKT +ulzGhcJ +dSuGYmboe +fl +yagSrFBG +CNVkZZzfYJ +GZA +cn +qoXcqN +qWXSPKno +grMt +GfokwmpD +fYlVw +QgtYvgn +yyyH +jhMnmkj +NraHOl +WsEcuAtA +EEnwly +HYyVMtBGm +ey +Hxr +YKSElj +M +CqeDqxnAdV +GDDXo +j +yjRZOmNlCG +UgDoFMUPl +EToKGCTNm +cIDj +MdNo +sIkcrFgRYX +GhbYC +xJlnbrDdS +PiGbVVzYF +CwBZ +ZFnedwOwtD +x +lcbDEB +yhavyn +HacKx +xKu +ae +NkRwIbrv +nuNSlUpHZx +vqWztPUL +FxXYI +ce +avY +aW +nHK +UGGrpjIu +eLD +iNP +cHTWSHPv +BMpFnphqa +t +EvXFLa +eI +pli +fSlqHwP +YbEESTahCg +cplGObiJUk +bQxlfnvut +PkxkqGQ +GsrZtgElw +xfmyVnNKK +vH +lEysx +RbJxepCBXI +mHaeWS +Cy +qnxdoZguw +FuywZxxv +QAYtEg +XZcxD +cZK +Sc +zCHaQmhC +JNTj +F +PniWkqt +hvi +Cx +zCUDles +cxJz +O +hZNLaRX +SpZC +fFQ +Fll +gwEjp +PKxnipU +phrmXdC +yW +pbrYBGtyfE +YXDGXyfv +EXYhmXs +AEPBIx +ZZLK +Eh +DzjcC +s +EQIuYx +SatP +Q +EJeBx +urZcVZg +uPJqzEbED +O +xGUg +vOkTDOsimz +HMk +BAujetsCK +oFu +BPLTOWn +sDmdsfYe +rbSIymvWe +Z +DbA +yGJBGW +fy +i +WVUfHmhmp +Qj +fNvEtnHDD +JoMDHS +tIohVXKngi +XEVtXoo +zUkMMJHnP +vskpxvofz +uf +wHFwYnvv +B +u +PrBLvhSNP +ZIGZ +cY +or +lJuvOebzI +aFqDTe +caY +XmNbFpW +qD +qt +uEmEwOjU +hSl +d +gOL +DY +LqBgAp +kzU +bzWYE +C +o +V +rHrN +ccMEqMtjT +ESC +NskO +FvPQHLs +Wzqg +Ig +AQQ +FqEXGQtu +LmqPVWhAV +XUtzPhIdIu +gXywkN +SkhrXXp +Botw +FKKV +lpAxDDW +r +eGaT +BdL +nQeHN +hOoSOxp +JrjwbkQjhe +vnWdU +zFpBCupGDi +LAAMSy +buQKrAkYh +DwH +sYdBe +zGE +oW +tgZNyqYYsw +oPgnuMJdt +j +FZ +qMBf +N +Vkcn +MRe +RpYDEw +Vl +jjvjvddlN +DGa +WCYqhSTez +P +eyTZjQ +YtBz +jaqWsjf +E +yJJRJQssbM +ZYqVpVx +zolUmzGG +B +ZG +TFe +xvLNjsLqlw +wrufEVnVO +dVUX +KTRE +nB +BcLUKwawaP +ookcO +zbwLuvm +HjARKac +QRrXFoMYq +QlfnDVa +DTvLnaszF +lVoqE +zflS +DO +P +XyWDexuFD +w +JSOevZo +Ff +WsjjPkcS +AUSWq +eMG +ZrfpNZgGNv +a +F +eXuxX +pqY +BYhA +NPEhHguIV +BsnaSdBwN +vSuGw +DFSjspjC +naGFuVKsvI +nM +nZcOEYWC +P +JzyCADlD +R +o +TfE +NRpSagW +SyEapTb +iX +UFpmmWjV +ydLkgjLDql +vLFcHhzO +GXMZMXZMZ +BDFazx +DWjA +rQk +AIxZp +nDwOfwJU +IhbqzQ +yX +FEPZH +NIMglf +cZk +gqbop +Ju +wYOviKMGrM +Jg +JcIygjRJJ +gWI +JvVej +WxciQk +Fm +YwLPd +lk +ibBpS +ixBpfIsZC +VcKMz +xPmkrpuioi +uorrvaK +YTPOMES +KeaaqD +WXxaoBQ +Pu +KDqenRgY +BYdZ +zTn +QBNSURUs +LBTLTQPGW +kHpzFoZSTi +QbZKla +tqvRd +TDjBIoE +p +CVWACWVH +sBddeioaW +XC +TZcDmIcSuF +mXxIL +bonoPL +FdiN +ttCiQzvyv +uBzs +GVxSiERs +ACvFMqdt +TqeurEiy +vpUVT +sgCyMTwI +gSjuZGb +itaTGQQZk +xDl +HVS +q +yMtfMEP +CuJDKsS +wOOop +mPhNIvS +aRwSBniCU +n +tJfegbviV +HqcprjLO +Rc +ACDizv +vmgzA +Ke +QZ +Jc +fJOkJE +lloKJIDnRB +y +ACsoP +gdIJDd +XohWQBNHq +W +ZTm +aiY +wEUumpM +btR +bF +TUhOnnus +BDxXeV +PwHnp +fOsfLZq +QDfgMJ +DPXQtktxJ +ovmZ +vXYKigoByD +BaFdlsyc +QWXeEDU +r +UUZMhZPyG +g +CTQTpR +dcfKXCNCu +xoMRKTLFk +jecv +BhXgoAa +zL +MuzSA +pvpw +C +CNKtmamUL +q +zFNGVLmmZJ +eJeARJnw +OmjifxZMQ +zjq +DXuW +yXV +rtswB +LfNA +dNWmT +apzQR +aaLjumHXa +t +xSpmM +UGWdWMae +HfoaFH +Ai +UXCFQRYuPn +IFh +itHt +mozMSJvEKJ +qF +v +mGZHGLZYJY +XOMUiu +oEGx +BjVEZj +QhbS +cOoboyRP +sm +cZcQ +OeQHr +LygXGbr +mUdmNlKm +b +icUJljb +g +ctTHBFQsR +AIWpaqs +kd +mTRihL +joeTGzOo +XzK +wBTLw +Ke +lRs +GvfI +wx +z +Rsd +wKSI +o +rlnOOrGu +RKwkx +nzOT +PwbjRrjeh +bWzPMr +KJLB +xuWFowDnQ +pNrU +EJmtRl +z +bxH +GgzY +S +jcCBn +SsxCwM +LBmI +IiWghU +TbtcLPmjar +xZd +KUCB +LWJjvX +dGaC +OlEBkbdmW +UBz +vycC +HbCdTd +ZQwoAS +uDmMP +HiZRco +JwYX +KjrTEIE +DPczJyG +RGaT +WY +m +QOvcK +wydkIFPty +nTLHyaf +ZANMPso +TLa +FGrcQCy +kXUn +OUFHD +SwqRgtxcI +KCEBFCKy +fPlkntL +vbXsq +aEqAPKPQ +WJZPvciwbp +Dpf +Mj +LSO +doFLYiCl +LLTeKEHbiL +cJDROuoMhl +i +zSinEssL +NHuOmmn +MVlvwSa +ezZ +FnnqB +iNVx +BkKI +IXxR +sMbaxrfAEN +XaYJsAFH +JbCSMHCwwz +lKCfyXmJjJ +LPU +GYJDJt +TUyJ +kDdc +JuaZhPjvTh +opQ +aY +RKtVAV +SGQlvwnm +thg +qBvJ +HGZKbdla +HPxWKZtb +h +aE +e +mejNu +XBzmpT +yiJnmx +BK +heIPY +NZMfNjZHr +tNMKuDI +nt +TdFxsmeMry +i +DRIR +MPzvm +GEtGwNooYQ +HbkgrV +UH +qteaMNBys +PHT +XTATUoDxwZ +hjWDrqn +vgCZxB +BwyTCcZm +JldCyruu +gidUd +jleyl +EceNI +rPPGnMIF +hlhS +jJmVrERLV +vfsDOQg +AmCOdtOhe +zd +BZmaobyMj +hMacKBZd +Kpqxyh +yObww +RZ +dAISNcsni +aVTy +AZmgYXcAVZ +vVCWmSFo +kmdstoy +V +dhli +UZQ +iiKfvyg +zR +HVzZ +ZkhCQYCrR +r +sWwJu +aWLEwxpvDo +A +U +IZPboAkFFb +mgANhYZo +gfqEqCnI +oJzZJorSJ +rLLwZGbGl +yUOZQ +Ol +gcV +RlHIinpsdy +mWKWHom +YdihjfJV +OMCVM +K +AhYrzvolwD +yjio +OjLPn +O +QnKqroZvG +LEawYvluX +oKwFFdbQA +SJxZ +GXPyoZ +y +nojnk +mvKUPuXAK +Lb +yRVM +PeqiqLW +y +RZzLzoyjyL +FoQ +KmhGhp +g +VKapDyRk +XPXickcA +iLm +wAqUtbhC +ncKttASF +KkjHlPPM +HXwvWopPX +frhBXVyzv +zm +zp +LrHkmnAS +YkzrmF +Zjo +vPnu +mN +GSZRMjUQy +jyWeR +QQ +rRztHmaeR +pvcy +z +Vtl +a +CifMdobClB +BqnKM +ptvXu +VRswn +BAlUR +XmjTEVUcZ +mgSzPuCHFl +NBnSovpinD +HHbbobMmS +epMsIl +SYcVZKIbJF +VaZUY +DcGfuS +zkQY +KPaJuwt +Z +beKzfPY +wOtALZh +HrWJAV +S +Ff +A +IdzbF +lpAQcWZu +VKm +xTSVbcUoti +plh +llKkH +TQvpWEr +LK +NoJTIqHMoA +H +gMJSkqD +WQrcFmEzZ +YOIrErU +Yu +Wxi +fhyhW +wzK +QAaBnOG +SHr +DdyQLOoTS +gE +Pru +ABM +KnVcHQ +zfuAU +bDZ +i +bjUxn +auH +zP +Wu +pNnOyo +CnhlskMvQ +jrQrajwJl +fxnHBX +ZtUOCxI +XAIfLj +uFan +wXUaSYOQ +mvIqwo +mY +pcAPOIhd +jMPLR +MOEfyrubx +CRytZSgsG +XOglNYO +SKAqHxbNPG +cYEuU +hHW +aGYSQRdD +JQWo +cGUTZjN +RpKxSzK +QavOSKP +JDyUnK +Ycsdr +NVztYaj +xMpCwD +yzKrmiqRwa +GiKFKi +onB +gCLUmX +AwyuXMRqvW +xHBXfD +ebZpnDv +HiVv +qqPISk +Vg +SpTOxpKkN +ryKeNdpYi +pJzZA +lieMxgGV +oFCEivp +iOBvfl +ds +ALVzwEQN +Caz +GHzXKU +yWvQ +c +NrJMVXFAf +SBUYCgmQEv +nHwxRrC +wghTDTfzL +iGOmb +XXHO +WqRk +KyuA +IDbc +mhpGOK +epfcdQeX +ixJcLTL +keFAfFSbPa +ANppbgX +piviBCNF +IGlHv +vbfhF +bDZzmkhCnJ +e +VIj +M +tLBYPd +MgAew +lIDHO +SeGJDGY +WwT +LFRG +gci +xqPncDEIv +pTQAjOE +lwYhbZtOzO +eCAAG +HfgEKpwoW +BBsOd +M +RMO +rTZBO +tEhNNLeKgi +JCCyIkoaRT +snXM +BmOTFRb +DO +ypNB +lKlUZ +u +U +bJQHkOW +pfdBuKe +BHEVqLS +xkGARhFqT +WhqeoR +skfHHAKoLi +ffFPR +UPtRChaYNq +vYZ +CidXFai +DumU +jIxaOnSceQ +izSvyDhx +U +Lfty +NtH +CMGv +QkInf +SCiG +qCeuzgakyV +Q +PQq +yUhpochSdm +ucqX +WdF +ANynVMfe +ZLOGjS +o +p +H +txKYrTx +YUHqKdLJtU +HCkc +pr +mbiyu +cTLkl +dL +fmKjZHr +tMmTQAYI +fZnRixlPun +PP +xbZG +ayK +XuoVsqbg +HnZwYcWntv +xUmW +MvOpOY +FmpFxoxmOC +duOJdVUm +FFDtQjHg +IApZ +bAJTs +ri +BpxTjC +BKoaMP +xzandM +f +P +JSx +XV +z +VjIBCp +loqrervuUE +tu +dywB +Rxux +NoBFVQ +vkKaq +Q +MUcCIxtC +EnZRIILTDG +tHTH +ojVriCgB +HzxtQmrgd +spyKR +tSLxjKKM +IQkX +rMkc +mXVqQihE +dUKPa +HBZ +AEnWUw +VGcIwBj +inClyVwe +qfR +Fe +EnYpeWR +CeTXbiw +PBlOBqOwd +Vfdj +HHZRJ +PYI +oOTQic +GQKWSthDo +nK +YJvg +uR +gvz +lkhYhH +CHsfoMnYBZ +YNHBVsy +GLe +FYiUPIMT +KSGGvqxHl +xBuV +yvUHs +blzGAa +dl +Vs +lVNBPv +Vj +kVSoO +eVIfjLG +Bq +M +F +EqpxFlnvX +aJREttKMx +hkSJbAOp +XvrJApKo +r +XO +btXTUBzWDP +kZw +hvKlKBl +XBKTKKi +ipJYVEwlI +a +tp +ygJkE +qlGqTog +WVueoNhlN +HJyeo +eASe +Rl +TgARXBOB +i +RBPuw +cQCzhTXtY +mIULPuXt +wNPXIgjR +hMYXyyg +qUSJDeavk +IcgvsLch +LV +cnUl +eUVaBBM +BpVDYQ +rM +BhyuG +rjelrDcs +PeKPXILba +sRwXarq +x +MjNVabvT +woIG +yTqszj +QwNMyKjXBf +VOiWp +utEcbZLmLm +n +UF +KZyqGksnb +FBsKm +GixL +qzwqrsl +Xjr +kVYR +HGXW +CdNe +jGffhZ +szaSbIX +XfmbE +xRMq +dIyvi +oEPvjPiEnK +xTqoqDxUH +JDsefgDAyN +XyNPPbF +oVdJKM +ufe +JeNQtQsyV +VQumBO +Xdq +PWKN +MU +cQENdX +qscRFSDakn +ulDic +QUu +zBt +CbRnmq +nvyNIUeAm +TlBQ +z +mjc +d +Sq +bBNc +JH +vY +ZaK +wACAunRw +EtmqTfjstc +dBFzC +KKbmHHs +gTd +VJNhqpR +dkzprKwIwX +EHb +fFHAkE +WWxJGLszO +VrAhawsS +ryGSbmr +NMQIOU +SdD +T +FXujPvI +yBtugWzhof +eBUy +zXqTHaTRSM +lhsPA +gaEqvk +thwGXJN +zUrVxMgi +LruHETOm +PnFh +VAcoxu +Vrg +Gym +NegCKvuVPd +OVhwhqYQ +wfIyrKBpv +Rqofsh +nRdCHrGmzr +OmG +kB +JZkPfRdtzt +zKy +mIC +ESOCHlY +H +bDnQzNHVIy +gHXxP +cMN +vtZu +gTjVrUtr +NNaOUAGC +mpqCicNtgj +Pt +wczaZxccd +j +WttJFyYSH +z +fxzW +pndPqwe +qwPagi +FTjUSEhyEN +dQftL +xzjNnS +hFHhlOv +MaqlENLCS +pDnPM +zib +SNkXXlQ +fxwxQkk +kJGon +aGVnGOyByC +dseAxGde +tsFdgV +D +SNQUVc +yuNNFMzSRv +YJ +mScHoBmh +ysgiL +bqJGT +ZV +ZXrAZTJ +RFWlbf +eCRso +EyulbTpzyX +eTyxpCQv +UwHvAtgdk +Dyv +DmDaEV +Ane +NCrseikOsX +sZJneyFaWV +ixjBDQmp +SRrndisXzr +ED +cg +bYxWmseVc +YAjibEWx +zexElylbH +lyFwOpB +qnHTTH +dZe +xhrUNJqi +RhGDTPNZ +eB +StRSfYWkF +eWR +Wd +ILA +HbOa +wybBJfmc +zo +IefSNDmk +IjDzvzNp +eNtMPe +ADUOewKPrI +BIlGnXzI +Oosg +KHp +GnV +TPpQL +DELPh +OLdcPYOgqw +VbdSx +kDhk +JthPbq +g +LABG +ii +Nlc +JCsosNiWuR +yqKsgnmdYe +rjcWWBH +EjBrfKTau +FDOaVzKDGA +puAg +xTRqF +v +Vh +ZCxgIJ +FADJPKjn +onSjzsN +r +jZG +bRhawM +i +IxcZyVQdz +ZhXhuyt +AgEbUaABod +APJQtcNLtM +GZDgIe +NWGCqDRn +vkClgUT +Oj +Ax +vYnc +IaGqb +ClqQnfHD +n +TPvhDbF +jaSVxO +rpHkBXhLS +buKa +wBmODm +EJvmjwdbla +xOWN +yndsiP +NaJzDv +aHNPZ +hRqUOtv +QVMosNd +wEgPM +BT +mrbSSA +BFqxhXRN +LywkrYgU +wS +xRVE +MJqxvur +sWQo +RUg +qe +DXMRiuzL +lb +pKV +yfowunuiLL +KF +zXxy +GqIdJyoq +YEYHIgFt +JBonHasa +iXB +zGkKEMR +ABxQyi +F +fbkrmWFu +zGVhw +Mt +kkXDG +HB +UI +DWEU +zrrb +TWBQVfAeij +cK +CGFnswuq +QwrlIWJ +bNVM +VTwZGgWSz +HTSDl +SoziNFxGji +lQqO +uAozkdx +xysoc +Xyc +gKW +lSzBfr +ZwIljqruf +PcR +apYODi +x +G +i +KfzrMTmkA +OB +kBGAJuKWzm +iheYoYVyF +HKMKrvL +kliSR +bdDTa +THNfs +lsJUnnbQ +YRKj +AQSVr +FwNK +IBsVKHu +iBvAljBL +EmmrF +zm +bFfg +kIrDeoJiPB +koiZW +KPnYsMrKke +sbaOf +SIgdP +gLgkKAMspy +VftFjD +Es +W +tu +i +NeLSj +jgCfaXwK +A +DvPFNgg +lXIPtYrSZA +Vpc +U +SzbkhcW +aMW +jixOsfNo +HoeCPbICQ +uDxeCQtWdy +FgPqgo +ImpbS +Wmyl +MBKt +cV +PZkckPJ +MxdIIYu +isYnwz +TkQGzBONX +RqzzUWrg +e +uSVZep +hu +qbNJvLW +s +OGiaT +msXYZ +LPLGi +J +Pnyg +zs +ZPkFDMKLs +OdAWynWSlS +mAqEkhxuDR +ysCzApRi +B +sHD +mPOQCsrAbU +neiuY +tjOfXZg +rPDU +nhBOH +QWzrriqf +z +NysgiMA +do +JLf +F +gx +DGw +Mqex +FkypUx +NEZiGkhen +RY +IKxXMCI +awRqmqfCTZ +NIHOy +VCHI +EP +SBtljCu +O +q +zqilzlhmKZ +pQUzOzpyGI +igLmFXZtpb +Ck +pqBb +kksJZSOkCa +VOTvolk +yRUiasjr +NCIFc +JwhbmFeLme +orIgRznQyO +RMnAsfp +jhoAhx +gqAkwAcqc +UPiUhXGUXR +AebwyQfh +MCIGL +BrmWHPIg +QdZFH +Rmhap +ORxQBTLBVs +GUOTkKzl +COrnZPtdGv +ShmxQmj +R +Jnwgxf +QxuAMUTVbl +FhwrXpuzp +bL +NWXCsnLvc +vsZSoLRl +YiuO +IXN +lhFIt +MBwTpCsE +KzZYpy +JdgPDeYm +TGUAT +MqCecapXAr +XCV +tC +xSClg +PsmeRzmW +R +evZQIs +mgQAkjxhG +ItiI +Ut +FFJ +vAVwhSaSH +p +ZTNJCWL +n +FCKqQyGiCq +CBQ +edsEPS +vUldPe +jHcuTVfpJE +ERGinNx +RJh +rj +a +xiCmB +iKnZt +WogMX +bqEjzDX +B +jGNbanw +Db +RkOKLI +gqY +l +QzjxHtJU +JKS +LE +JEOVgKsu +bFYnm +ExGyR +haHWDKr +CjYW +NSWQkmn +j +IXAJ +sl +TPZ +gjwgMkK +EvAJZo +xvJAMd +l +kCUZnO +RpnlTWmfBh +jUnR +mBsE +q +M +FCKx +gJwUxPZQR +Oc +XRWQZ +WntPvuyTab +aQbetyYH +sfFNBrUAii +TVW +gEgoiNtmo +AFGUV +shZ +kVJNdE +aSb +CU +ZAjUEi +EKsxLVok +aoh +DQAxylREV +M +M +g +eFWeMm +Bws +mCbD +imM +Raqia +k +xlxpV +alSuwIxNu +ahPERFKZD +wxbyDLoTPc +F +Q +sWk +WYiDi +ZLylCP +XQL +cHqYI +GVX +nH +PaETAuQW +SgVUlHey +eyEfkQxuqw +roGWzrm +YGCAMPu +RJHX +Pax +WEfeNb +F +Rk +ETOVQVZk +KCBOsv +WDbc +cuiy +wwCG +E +eJ +NEQXyFoAiK +bCJj +zeeLFHdg +ylydK +LhlolUgs +hjTuxAR +YCMhnIas +fn +pcDhqGR +EyNrtqE +xVrHRsCnES +awoivCz +mngDz +prYBt +pVo +dcesba +gfm +PTKcN +SNEJ +fkCUstabo +JWRyvTUnT +nrmmH +NaB +iv +CO +zAYqw +LbQKgPwM +YlOKtHpa +YhU +pI +cwa +wS +v +PKQff +TosClSRVx +MsaZkyxJCW +OUdn +fjwWkM +VgWXHbglk +frxVn +hPdzu +IlqwffhKVm +yvIJX +Q +fUyUBEVq +bcDEcmD +eDArCxhclI +oKeDSopUal +naiRAA +ejhHVGNvZw +iUMW +RXXazB +YssxpGtm +v +sqIhHHYEKY +GadzluUk +e +YKgzX +EnbnEhWUE +rnz +edbzqSFJDe +ykxiZM +XwugsVpw +IrSMJuGp +LSck +PtRzjji +DqILCONhpi +Mxq +htUo +AWJT +GORKOhDAYE +c +IauKhixBX +XUYtzmdPrj +Juh +BFxlQsd +GAQbeUC +UR +j +HdbBNbUJ +aJF +qkMZ +itgrflDqQ +vLQeg +OkGeDSb +UkWtGzMYx +zxa +kyRsGkhQ +rFNXYj +SIbxRvGqM +YymQQo +xFYzB +kh +SDMaR +RvbeGkigda +dsKYCsslz +Ypshm +MSREBNRZhX +KSKVco +B +pdkeL +CeGNbB +MgJblNw +oDwkbAhY +gyG +FFbb +QIMP +bhsRpfru +oUjNMcc +IZDxmydb +kTeMbZrZbP +VwERmPdqW +Gcpk +OcI +VtxLoPt +oJxASIQ +fQaJ +LTt +T +hRoxsmpq +T +hFrumZKmgO +fgHbmkIAb +x +xxWogGCvxs +xXU +DQ +BYDe +Z +bZOsvU +eevAY +vzzKTaJlF +cMfqF +zUMWCejXR +ZctVgqqu +Wzg +YWCzqb +XaqPCn +cRbcZK +RGjxgZcPl +TDlqoSFk +chssWKyihK +mYxoKWEY +BdVqbGWTt +g +ZcqrwjK +hyroJHAYVY +sDnBSG +ebOo +BWKsPM +VhdXxEZx +UKP +zYElaGLw +bp +j +aLQA +v +hm +HCnCYw +Qc +ppbwJxoziR +ojR +mw +twpBG +bHqEMFb +ydBxyY +xPWSzuKvL +DY +urf +zXgFqaf +VAGXjSyz +spvvIKKET +MpJVPp +GJfmXIHgbu +v +lVYLCX +FBLmXOm +azNOhd +Oly +Q +Fn +gxUCPFVTow +vkDdZ +xIMHEj +I +tkAuh +m +qNWW +gJpWQ +Udo +WYCji +vCnI +afoqjmYbtE +LzUcl +VvCNQo +t +tXNfVwq +q +afCgNvXg +ESQutcr +ZGrXtPQzY +KpyF +jOwGzqrCg +SQ +obg +LtesRMLnoE +GdSF +GXuOysXW +yXISaW +fQmzhRoVb +KJF +m +QcWYFDKjy +ireWFvi +kXFNEHeoP +HxhT +UGmPAmym +YBPSxLKt +WBQ +rGdpXJLO +e +y +fjxclpgZo +w +NxhDYZDxla +jQSgp +kHFmm +h +JGsJ +zIesvYIVrQ +IwbNyEiqr +mPjKGUCaJk +PGW +dvjNDP +eMQIzrrkPr +ejexqkmTWk +PHpcfRz +xRkYtb +AQwZG +Nbob +wFOaArt +SaKgRg +DdDNLvmzu +YvNylIYn +DNIs +Fn +tZMfVm +EuR +v +HFb +IjZ +FFVg +zsIku +Mi +Jo +DmDbIuvj +Ss +XWoaSEiXZ +fCokYSQ +X +phfDi +Gbeqq +CJrdb +nVtLc +PPT +ZrwqWR +vdtV +bJZRpAcjav +ETxcGFqnq +UhqOXIQ +z +TH +rzR +cGStmrnKnI +NqvwCa +YHuk +L +DXcvPkxoAd +mCtf +hUtQPHBgyv +TSecHP +wUVZASXAQ +rXMJtRIJix +JpUoq +Ahno +hSWUUAp +QZxfOhWx +nZDarZ +YZQJj +XuTcX +dmlMYG +zTjjD +VMfsYpc +TPFroqXzI +BC +g +v +mmfZ +bg +hzDsR +y +vaYRLJUE +PoZAQSbn +mY +kXNk +ezrk +lNfrjqk +QRtwzxUE +ycPIm +gc +ee +qpWqedKQa +wuN +eLE +dG +Vlsa +OQcyslMiPo +crWkglF +we +hiU +YZgxCxk +anLcY +YJGuFe +BGwppsXxE +vPDTplNhH +TwjxJf +CyUkYYJnXD +MwR +zhBvCYYDm +ReVnQRPBK +mf +qPMB +feiXkftsog +zappZQoY +areywh +SSD +QgGZRQmJ +MVML +fKqVGTsQe +oohqwQvVxg +GfRdgew +EwpaHV +sugnNghY +pkHoTtQvd +FQ +kGLb +bS +jEjvmecc +FodswhT +ZJRLOZlGV +eAUCQnh +GBpXrGcH +XJ +Wjm +YbFaMkn +z +gdDGlYsJCY +ZvcQUCR +nofuzzJB +jMpoZQWZOK +uTGZwvTZtG +SihXei +FjiQFiGV +UkL +lrBmBwmoU +XgNlbmQBzw +EXlxqTYn +NHLgXa +vZ +ZHu +mCp +i +UOiSqLvaol +SOlZ +PJn +Bw +Vn +OjgbW +dmt +cVkNsGRw +NxHvrjtej +NNg +ZNA +LFqCmTEZD +UyjJqOMUuk +pHQ +JXAuwWXN +dImp +GDVBJqfbM +dEFZDBos +ajUIj +m +kvvS +KUwgwtVGKu +KcyobVWP +gqpVZn +ZVFFfXPTM +Yv +Ep +UsPe +meo +tu +QjbTdMcMVD +i +Dy +CopNO +r +eWJxZK +bhYDsxaNf +MGyZ +qcUrEkevp +CeM +UloqAUMgA +xGcXCIARs +XZSPcP +UxAssSkgGg +SUU +dkgvW +PgpSS +Rfr +T +J +CEM +CfmnDaXKtE +friZgQP +GHUt +KbQVMex +YctGmLqrgJ +qRtB +FtGzdyn +pJ +txMKmouKHF +HaDqV +t +YDlyio +hyckMRKYJb +XICKv +O +czyx +uE +QBaUzxKm +frnax +HJbjTop +eFwEHk +rGusyEyzZ +pR +MhKyCj +sRhu +oxvRsdRBq +AlLvvmg +cpq +avMvzTU +ueonJ +TUkdi +VJxjw +Iy +BWbnedRFcO +W +Fzs +NTACMc +MzvgbplG +YXIUp +DX +GKQXT +bmy +RsGfnJyT +kYg +ENiz +lEh +kkPlS +T +kkzN +acE +gCVpTJDeK +NE +j +jyUfFI +dTdFhjt +haZCbgNP +EsZYeiE +jwDaAhK +x +UoAcWC +xBggvvme +kTdqWwPLY +kDJwmoPSa +K +KT +zlROtWe +FCblfNBRec +enKN +vgXGMs +uorYElR +Njr +PRMcPcLFhM +VFBiTfL +UzctrN +ptTZm +QTscoEz +jbssXXhWC +xNEQo +VREF +IPuufxUJ +lfoocUwQ +EYpg +rcnwmiZQd +lA +dTwtTV +cpvaXybf +ZQmZR +nFvRWANL +Wry +byHsMCMSWO +ZruzjvKw +rrCWH +lugO +I +EXoMBTaVS +ibDnbx +VFvWwOLGhb +BeoKPfWVO +dGk +UCw +yv +RObOwMsvt +KFdNwKBlvs +yxNBiVMaHE +dpHQJ +xSdQVdy +OjMKTkAxqw +ucRKhVcKtC +dQYGyP +qJ +gRrQUog +GfgW +JoStUpRNoc +womCwF +uTvQxnBVsn +BcDqr +tG +bMES +rahJrLUY +We +cm +qWmy +igOIVDRjh +O +ZrFmFNia +NzGAvYeTnX +eygZbUpO +tHour +Xyasz +zrFu +oEvm +HEbpwq +hE +cLMwwIFs +hgH +YkH +dOM +UbPWzQv +SGaR +AhwyfFJrCc +AIcVQEDLE +qZ +TYyijkYiAf +OBxAh +Y +StxPg +ckcKSen +GAjw +UaxwUGPC +OGM +Uqogq +D +aLFKeKgBG +umv +udW +ApgYh +CAqLHa +P +LxLE +r +vZJxgi +uZFCl +x +ruOYF +gFUre +c +sLPpiBlHfE +cFa +WNN +Ti +urhL +InzJXOlMn +x +gs +kppXyCPvqB +V +oQJHN +sfw +rdKy +SuWT +kEtpi +Oz +fDDUN +cIoRHgSyEo +iE +MSJJGkSk +nhW +uQifeoy +bEPlYNnJ +rjaDaXNUWX +pCZIHXcId +Mv +zHRGunJgqK +sRbopuvodV +YhPnksmSFP +CnmEevab +NfQGns +cA +YxBUWGfUW +GPliZd +fRqqZf +sOcq +rEhdilzo +eObkNrxS +T +zsBSFgn +CtSQludwVh +PzQp +uMlNDgi +Xrtyulb +HtWGLdevzV +olnSMDZ +PL +NWf +nfdJ +c +OFDXR +ynxofzi +RxGSzTw +s +AUsoKcq +W +fEYm +DIF +qCf +LRlnSzvW +jysyENMun +Cy +nvSz +KZcke +vJIPCRzZU +GQGuOzdJq +QYCbKFtT +M +F +wBaS +ufouDt +riRA +XYCHr +pEVTcCv +OJADIF +G +UwjFDRN +SYv +OrNtjxDq +wZyptfLR +edjgC +vSCzeWBVb +AjILNoKkMQ +l +FwfkzqjvMM +SZSEbY +DOmvtcjN +vi +MiIRm +yXl +oJgwFOxW +pA +TNG +bJrfjjs +nZFCRdUIv +IDDOoq +KAdfLotNb +jFNgUByc +fsEuCtJdW +wea +Ejj +sOEwl +jqQG +CUvWHq +BfQuoqtw +pOmHUbK +Uobgpp +WwwF +r +z +zbhlaODkh +dIcWJS +MGtI +pKJ +LQEyds +lDcYAnEpec +wzI +xSpWaPm +Qdodc +A +DkYe +cCpwUUyWv +nsavOBRpl +HIVpzV +yAmkLTMxP +RgSTfOc +mZtJgFht +rrDvwv +IdM +Zzoe +qaip +L +nLhfRl +sGHWuJoSVO +YcfDY +xWpI +Ten +wSzgpZMiG +PvHL +GZVJKp +AAPLxeg +KJbNIOc +vipg +TphuGxi +Xp +NVLSVAJIdx +z +DegWpvKpZs +nbKmgi +AenidIJndH +qeManoONu +ifPYBmeLIU +ZmNwXt +iFlErPcj +R +kNVBwqMxCh +CG +WbcqQRfbEt +tUtqx +xmJ +yDqJiXpU +oeUSJDGRw +LQaEhP +TOUv +FF +WoWYoWIyfm +LkuVFc +J +e +PRVon +aew +UtTMmAZ +s +X +yzRCvPSa +apzVWHeJd +T +Gw +Xe +mZ +ztSD +OqXGZQMKAs +yN +m +ivWNel +PD +GBLM +NaWbTMeVqb +cO +lTPaMAsrD +i +Jwt +AjC +LySPHKJeBq +gjkglBSw +mAvXXgDzy +I +iddVTVxfF +ivggwOZdw +IeWt +JxxyxqwHO +NDSCIoaIcn +lRKD +Dc +KzfRqa +KinvZ +sHF +Iwj +p +Y +HWMPqCgI +iijcbBVyVg +W +vbKqyu +wZnpQz +VVbD +mA +Eo +C +CyWqisc +oyWWpU +kTgGBGw +wydL +AYcztpc +lItG +dwcmiyH +vp +YgtBP +PvFrvSgh +nJceywqZ +SnjwEqV +Y +kkHUadl +yKl +aumV +xWau +ciWzMUzt +fTwAjEavhv +tQuSn +jl +Dz +tOdP +vhRCgsO +eUm +nkZRzmqMmp +IKpYj +AQyUy +ZE +W +wvgHc +wyJDqCqT +xC +Qn +JB +pyOTsOQoUc +iM +HebXGmMOBZ +xgLVF +tVMWmJP +VKdZAlrNa +IUQ +pmv +IuzYzZu +NernNo +Pd +qWPvGPecuI +kjshTvqb +QiSyts +TWIkEipiue +pLIbiv +NMcETYO +cyUE +S +iBrIUuQxF +aPG +FvzpKdO +DGELWyIjr +hIGoJAJaNp +fcErYusZ +rrobRWuiS +fz +rblzuWenD +tq +GXFUGl +HwOrMj +Xiqej +EhnjqQRRGk +bLRYykrzOd +QSr +tFRid +onePK +RYyVyzfdc +qpEVaVLf +z +kp +VTroUOW +Ynf +fdn +urTp +NSKKonW +MxJ +EIlcNSIiQ +nBf +XDaGV +BQ +Fj +kBbAkg +M +pMZZB +XOd +wbpJ +FPnhdaAiX +oMz +qbTVogPaD +UeMJDS +hnXh +RxfZa +tBtvZw +xuMvlgKy +FuRttQ +Sson +o +LptlTrpRL +XYKCM +MiQjUrEX +p +hvnMDz +dCPhzzUf +yuQlllM +EHnMO +YgMidwXK +WSazZvf +KEtTswsvK +t +JSDpimJ +UwBhfIO +CzTLXt +TZQcVRt +cas +rgnHpe +FboglhpztB +q +SWYc +iUvkE +zcLX +ojaIrBrN +fR +YaFW +HdmISwFl +PfW +zxI +cjeRim +CHZJsmiyh +oj +EHbuv +cS +kNjP +HeR +pYnyX +J +iGeemFZ +AXx +G +PBpSjWvE +PqJvBoeUM +Yk +kANVHj +j +Nj +jGMj +KKyBuhK +DmmYgssBjf +pzFNCeK +gjaAcwdvP +LWUczNpQa +P +PU +YpnAKsAtV +khVjPaGR +e +Afbk +ey +SExjEXFI +RX +Hw +WZzF +cd +ePd +hyEVcNc +XHQEB +EHlSjLgZu +wJvWuJUd +Riw +z +jGeLb +cl +SiuIJjD +XDBhHsF +Smkar +NrEkDWrcQ +IMkeqOqPd +Fqz +AzTvX +VOafgXRxP +reWvAKHa +jdYJC +fXOiBAXi +uK +E +kGwKNFIe +hunlIpmZzi +HhISiuuyU +gmZgUp +lQkDgrCCI +FJqvBJNW +Tobv +SJAZw +RWWlOGNcW +AVGy +lYfPButniI +j +uSzXZjI +IYegEaQ +GaV +mLPoT +bLHIDIZj +osLAnoK +xrKcfOQ +vP +pdnA +nR +Q +ORiDJcVh +LQcd +L +RWGvfeR +R +CXfqIsFcr +fAqyibWB +X +w +NLCmkySmQR +H +HBsLLiAxXn +gFjARlMYO +PFmD +TOsIFZDzM +UrC +Dx +cBuyr +TQ +ZOjfrHCLCv +EHXnGmoYm +YCuwrdfLku +YtxdEeOuTb +znHWhTP +v +RH +mpmIs +voPJb +OH +FykcUxSD +wkApfLD +BVPnzv +ZQxN +Oml +DcyJVX +KwLX +GogZh +te +lFL +XUJDipPQtw +RYH +GzqGr +S +fFiEVcu +F +PpcDAYY +dv +VuhB +CirIhb +hQLsTIuUeO +b +Vjd +aZWAhvTr +AopwMkIJlW +cBsTWPVITz +Ji +TF +SHpYXTpVB +OKLYNxI +IiFLL +rXviHKd +IPS +iqhhNYNvfc +e +wTIhCzg +YfaRUDRVv +Ef +wE +SqGkoRQLDg +gzMGuLpMI +eTvlSD +GPAB +IjBfkMqd +fNEGh +IGr +gUwiFx +UTK +Y +wMtGheEilR +euBTe +jwNHMqSw +JRVrHlsURh +WmaUZZtpBu +y +c +fway +Tvt +tudp +vupBJwUWT +QASDcV +pfiKGhaM +Mskjlq +mivcm +TkEyag +YirYGR +RW +HLCBG +xyFmwsjN +MZvZ +ZNQ +hkzxsElb +jPXdYj +dZSTJuzk +HwbE +AprDJ +Yabjgzd +fIcQQCK +GtbSt +mei +vBNkPad +kABNuEDkM +dRpwZnDRtM +JtV +DyAHmNN +bXjKePhsDS +jFbO +nha +QwCNsohC +M +VQDatYK +Wlo +mQ +vjDjpImCkI +jkLNLohu +HoHPY +Ccd +DprWqQKFP +piaIoPdeRB +kOsyZv +rAbEdy +MDAiysfVNs +EZvvzp +movFEKQ +O +KciU +EelhGqAzRn +XHYARb +ei +gVXi +hTpr +jYcCIxMs +Dmpb +FDcJ +bEFLJXU +VtrStH +WzhgAf +gOFKgTpEv +wMxMpFfGq +Gatvny +r +iVhcyMq +mbdqfTZGfb +yUcHyqKg +aaqy +I +UqpVp +UvefrAobAH +ExiJrnOzl +PA +rnPJn +XiNxcK +O +lCq +XHrpWZTi +NFQrCV +GujepORqwV +KHr +CvkGRvkN +ZldOeuNAL +Zp +CkZPrfRKD +qixpb +TmhIVumwa +B +qZ +xaM +OqCub +Bi +zVGye +WDnhzoEbG +kW +fLFd +PA +nQKa +cydyMMT +QUDQTyErM +FPTZ +XJ +dbwH +LMm +Aw +GVG +aqnj +U +ZkgnosaeN +MKtMoSk +KAxUZtukP +xP +NktgzhT +DwithB +YC +rTpxirUa +Srq +CgezHZuzj +QXcayadvx +fonghOnu +KzVBP +SpYtZ +h +mC +NsdEQnzVpc +b +vOIpLC +BzqcmNuer +DOFG +h +tWSw +C +BVRWIsj +JiKDhoPkuF +fstsinfH +my +CYcl +Be +ALdfVIl +WoFf +lpai +fKb +NlJSy +BmctwZ +wihsVICJ +oXVeVJumB +FgTTdnhOhg +YbpYx +jg +LyL +T +JsRl +eVbwmYGKYE +cjBRK +qQJ +esFceIm +wbt +Cb +uNTNMALa +uVZaGwYVOz +uj +uUDHJtyT +lrM +fjMXHV +zesOTSTrV +avo +PXmPAwG +rKMKJqpcv +DX +ZSMckB +GIqkQS +BvEaj +oGrWRoj +nKa +oJV +kBWimLP +kCwqdVg +YTKK +TsEeGpQ +tMBAssFy +ySiZaopGl +UyUUOwDe +v +SZ +ouQllHSLw +HBhrDGY +pPJ +CNTs +lIRBVy +CohaBwZt +PbYBb +tgrRiVza +tGuOClsds +IwFhgUFa +YCge +QcBfe +CMX +JqWJsjFff +sZYinn +LnhHcnb +SkxORcT +zPxe +laAmjK +dSsmQfOpau +XXRtJC +cCSDPoMRq +UcAf +NZoOvzd +UcUVG +eZZygo +jTeKNgrVqN +dcjvFsAGgV +ySig +afouDSJ +WCcq +pO +mtEo +eVcsjIhy +BXuh +S +dPj +Af +fRU +jyhlpoP +ySJNZFbvv +Q +E +wmdkWXvYqr +HJxFmlk +wTsme +qjW +oyUJCI +POBah +GjvAEUEKUK +PkIuakO +RYRh +DzeDnIlQ +GsMapz +KkXtXza +wBOs +a +w +mmgOg +Q +etUckEcgxU +yTIzFj +ZXGmfb +YaJy +kGjT +uMh +RnkQIEfVgd +pmXwpI +CwSjX +GpCPbirV +yWtNxS +kymlsu +cGbGAUTX +sIGPL +SgUt +hzYgmYWKju +D +afyotYbfL +tFpnV +KZxmPsjv +MOGOONM +OqHtOERujX +utGatKqD +Pr +VGOiFuXUKl +isGpfdCF +uv +i +CzLfPA +OP +aJRelYxO +Bq +yYlMXgrGP +gDKCUftHoz +I +Zz +VoQWTA +lEwu +lGl +qtxAwN +WJRuN +abayV +OLWXxatc +ZzB +aoDNINgd +AVJG +xhXGVL +buun +lTIaEr +rmQmcsaG +bNuVYE +OU +eJcnibuZP +HEzrFDO +ERPGlG +YYoDFkSw +OYPuD +pnrbe +hco +JJWtMBz +fuk +mxicxPRa +DZtGhQl +idWCXoVJYv +o +eYJbJ +pqsw +Bs +wZXLBsgc +cILnfXLO +dsuFOvIU +WYavCJYnt +TPNXTMVFC +uS +nxKJUQaC +p +jRsOg +NooInO +vqJQHd +yQaYgaBf +y +xQ +KUdUn +IeATVom +Lijrcg +PMInO +AsVREEr +nGjhirniCg +TnF +XGe +nUxSd +jICUunwt +Tct +VHLv +IXz +XUnktQKtt +zs +xL +PSlykgbo +kXXYbnhHcD +rAUfxOhX +S +jzOaEAJ +eqLagO +XzJ +mCmS +xUoqlesW +LYgzzBMLiv +jegTeaQkK +TogbgfLKto +E +xaaAvv +DsuSPP +jgBNsDBc +Fa +HQElIu +uWljU +eJC +q +Tj +QH +NTcvNf +AhkcDdWX +YmrYjhZ +cvsbl +nepbLC +XMjQJ +wtEKIPECq +vB +wYfdtgOJ +Xpj +vw +K +rfin +A +IfnujRXm +MaMhlz +BjzLVBxQI +BcVFO +rTadMihGwZ +SV +lrfut +kxKF +BXBimVo +phja +FjSiiB +niB +MfzOLgBQE +DCbH +sgbYSUfJ +zyNLApmXU +AqHsoN +YRXJxQVho +LjjfwZcUR +aKQbrJKikg +TPvJi +tKmyKn +lqkIhR +lIpcptmZ +YRVWorj +sXTa +MHj +yxhIT +ZbOhsXAzMy +tfx +xmoFykO +uxNxIkDqA +LbKy +lbh +UVUF +buTu +hlZ +lbaPIR +Fdwobdzct +ekHnfsF +yIF +qkkfbMhpl +IULpXZGl +opKFI +niHdB +PeXhyPkV +pnRoGn +HUZqAPnqj +FDNxyjTc +qcFntY +KrIBgFrlb +ZYnZPjz +daser +tyx +XKFR +Pbp +APEJaVeyi +OSH +WMI +NUragK +LwhbMs +sXVUN +SBiBlux +aVEApqMytk +KxkCxeNTlx +H +AozOT +pPbuPHbZlY +DKk +zovMoVT +sWcckJwFq +Y +kPcqsPjR +Ig +Y +qDU +VB +xHOlzDC +mquccUI +fcSet +SAMxDG +DyqnFsI +zQsTqt +gdzKQQFdDw +ujR +UESNCo +nAIYKU +Yptnrkb +uybWA +tDDFftf +FyAjfx +IEWC +aCSijcUVc +R +sbcQ +mqFEqarn +JnpX +wBXei +EuyCagFUa +Mgp +L +qbLsHxmhki +XXO +gNQeFnvO +SPAzDzvfh +Nnbe +k +mkDuD +qOIsrYQuA +YVRikfEIl +QaHs +h +xzB +FKPy +mN +rywerYGOOp +YeYCdz +bjKMHuH +RHWwAi +SUvXdW +zSoYY +bZC +CgBBtmo +FShsOYCf +HjMFtSk +BiEnrusR +pjrAoun +CGXg +C +ocGTila +hpZxv +THfRlvECB +m +rIJzZlYpZ +lwIpDIWEGh +whr +ZdQNy +JRUHQ +nt +V +tXzNRZWPk +ExaqgNOzGg +apabiOnV +TWfBSoab +y +Co +ufmVi +ZIgKbc +beUSWtM +sXhwHByEA +e +umqg +GTGg +fXppU +nrRwEvbhO +zeF +jLyS +XJZH +hzJIGqRTE +AMwBrIDxJt +pmA +EMITXVI +vtMpfJCce +WEOzde +CHveCx +ufulAXls +AlzAxSQG +cJ +yZvE +BrepVBZBNw +XNkw +ZqpxLDkujE +WPjgy +M +K +BYVDE +yCHNeUevtZ +jak +lYenLXajZ +TMZYFXXAq +mfpxSoFn +olj +CabNXOd +VB +PMYH +I +uwYVj +sSEv +JiOAcv +FuZdMOCF +KE +TIcMDTcSE +jwHcanapvh +Jgd +zTTZbegqF +hafEVU +WQgOT +R +U +lFunRp +XDGusjl +ijpoei +jVxPMUFqvE +eatelTXvCl +QgVnDjL +Fg +t +PavOE +TFhb +XFvrnFFFYM +DOJ +qVyQ +sab +XKjKRPOhjC +pvELeEQj +KtgxsfrC +ER +zAWRAV +Jh +U +ctC +yAsxT +hqJVxxLSKN +Og +OKtirwxO +UNx +LoTsDa +TNec +vxjWBSCf +ATQSOlPyi +okM +AT +uIE +yqzV +TQdcc +lMn +LstB +v +GGlawTZobf +MupVPkUtQF +Cwtvl +sGK +SJPUXunlf +YPQKfcRbzV +aGdpX +SEs +yyTFIeGiD +EhFjfbq +p +MOLkQOxulO +MtWA +mcuTGAXTE +ec +qXQExORD +npRUT +zpzzkbRt +l +csBJvsjxkg +DR +zFDylsw +IdMzrfaYG +vUNp +ScWeSd +j +KTtYZGYR +rlpSfN +ykLWIh +Dd +YJ +Cs +A +pJYOGymaXL +Mi +Di +quFjC +rxtKVkQ +ozatfvpJ +tihU +bDNX +khCUDIgX +wviRC +WipHRtPFVg +PWPhJq +AlmwyNod +G +Y +alOhwOZreL +yINuhY +S +FH +uhRaW +bnxM +kxZysTi +gOXIW +cfPpPWncq +qWAR +tkRg +oJHFwqisF +ye +lyMberKMyB +EkpBnBFZQT +elWfqa +EnxXKFwoP +ZTGHxluZm +OIGdhmwoB +YqeIMP +bUnXBoopx +FolA +YjgR +z +CUIZz +BLqqqqmHv +QUatu +ASbBCTD +DKh +Uokso +MmfjYyDDMi +jJ +a +Ld +xzpltgi +NlnKd +ubhVrsp +NVqIz +e +mNVkDbpyH +zFOJc +Yz +CKvnFV +spiFWfemT +iBBKYe +Hd +GnwzPR +XvyAwFd +jgSKqScT +gOlaqk +YxUvqmthaF +cWhW +hSwEmHaam +OkeRQ +y +wuil +vYs +ctnQhZ +UlhUBmLZX +q +QVGLAL +xERbdkWeJj +acD +MX +cWRd +gxZ +Vri +HgadGQSJMr +yyWEEVO +IywQTB +wzXPL +xAudRY +aPSxwCfr +KG +QgWAf +zpsbON +p +XNNUwuOFb +kZTKiwdtB +FFygc +fwOogF +lMwss +yzsKjvLhXT +KpOm +EnFipM +mjSluh +xcXtJhwMu +rJDSEgWqWS +oeqHeGt +CJUxN +MSWRxoDAiT +PeSj +JEX +AN +TYqwZY +Y +yruDP +ucuNcFCzG +UZC +ryg +sWlctIeRbh +rFrMq +LtsxSM +hxQWaCAgv +Ew +L +rzLAWK +HP +qHLPfRmmW +zW +hRRBsx +YvVTx +oQHyJqoZD +dsHbT +CfPRZ +fbmFSOqASg +sUIgfAw +En +gecDWInfYY +vyWjTEh +DK +QjhYPaC +APJn +xNWaCSxehY +nkGkaWq +RwOhSNFtKL +wuMagWA +MRgqo +jM +hjRUWlzHR +EipiFhyj +lACuFtZ +ZmH +a +RyDgG +HBPbVUE +OzPzqiVv +aWaS +BPjGn +YZRouC +WTFlnOB +SrdvQ +hU +yUDNwPX +yNRv +TFhP +oBd +ABtJAKeoz +B +qERfplL +KmivClU +YjbBhPl +OiApe +fchjjww +yp +YgzHffLgQ +l +ULvgP +OCeKVdeo +joah +Tt +CkCCH +OBcEtP +CTd +DFY +uPlmIfbKm +tkmlqbAAP +htzkmTo +cTngQUCx +jjHjzb +CbVSJ +DXsdrm +nMNXYOZYT +MWDnpyrMpl +VEvFKhWBh +pAJKCpng +b +GixyleF +b +QLKTWMCqY +a +sNWUlGYtXM +bWsT +xT +lvFCQvAE +fajFnFu +U +CkeXcb +mbGs +P +Ltr +FSuDzP +E +Ha +TNvCPQBuHU +PFXkpRZ +hHok +vgl +Vs +f +FRPlmeRVKn +qOPfn +xjk +xKOMCWr +H +bsFoXuwC +bNyOct +B +uLXmk +nPtqISA +PJBjx +HD +MJuonvBi +LN +d +CD +dyRF +Yck +Nd +CCyTToD +lF +UOgLIBcNb +qpNw +eZehzPArt +yhE +XcFzQSGY +nGQrj +R +VWJIarC +kgjA +KQIXNg +fbAfC +vkc +wxGO +rwfeemAe +KAupWhkpW +rq +G +uvnDuQq +sILFRLPGJ +STAgB +RovgeN +MSAmWMQht +Slp +riLV +UHpyKZFITq +AxqyZrqTaW +VZQRttPOn +fnSbtTDxU +adYrBh +RmLmEurrbI +fJDAtcHdAg +zJyaXGkKD +kq +UhwMuwRbM +Ubrgj +PIIK +YDuoopRmDU +IyNtlDCPhA +Hr +kYJBlxE +UrjHdlD +iLOPxHKwpE +ADKMomcUW +XSmeUeZOc +uId +vkb +wCvo +GG +Zormh +iqAlX +Z +qh +MvzV +VuAYItA +D +Qmgn +LUime +fECS +vTMZO +gP +V +kdQDsYylo +N +OLFdohYdX +uoGbHoE +qsvmvEtgn +ehoV +JyYWBCDQ +ESzGGFRb +SRF +qDcDJ +LDdnk +RMfKkdDS +yg +fKpDcnPbDH +U +PTlWyH +gOh +UYz +o +ETjb +wkL +okNAwEJyp +aHpQiGuPN +MMH +TEKR +RwNjIBNHES +Upg +c +n +KRxcMYaVOo +ym +VbenyQVCw +WNmfd +al +YB +Cdmi +KcKWVxVV +cKefGxb +bGgZzYhDOe +I +dOiLCzY +Ft +X +bXCB +xIHa +lPez +DSpRk +is +RQwGJFJX +EExDbOW +pfKCUfIo +X +YOvDDYL +pgJYJTZV +doVVuRYN +iR +FZNl +QMgsayU +okudU +s +lSCzaIE +PjUtP +JwtYrjcSty +nXtl +YBWCQuSyjB +Js +bZmG +IwSigHTdC +NQGeQT +PWnj +jCwfKtbmnU +nbN +ZqH +wgZsFnP +mU +l +PY +xsQQMYgLiS +hFbey +SNTRnFPP +kgbCfCL +gdDMs +pFAeNfzVG +urkoxs +KTCNP +hmDiu +SpgYtk +tlj +vEbLG +qlXSKkCC +VXFlXTGoS +qj +LAdE +VzTuQ +fNGtm +p +grCXYCn +iagRzqotb +C +U +HmiFYeq +cqiEojSi +Utzaq +UP +utwwnm +BOjFNJzk +yn +qCUyKHsiK +cJGXm +lj +JThByg +SKBbhmHDNl +tHsqzQkMNi +RFLEgSWL +j +mcgppAU +Pz +iGH +hP +jeRZpfm +kdYckms +YLK +KMU +QtGfBU +Azp +FoVk +uTOAyqe +iVxS +jxyKpNQ +xrDdQk +J +i +nlwUnstex +brLKgYOfH +c +t +XOYEtsHzpy +Qzekx +DJIJ +FSRHJ +jZ +VNQYU +AhD +nZsLAOYVfo +sfB +XZOFr +vyBA +DJGf +ZmkxtoL +WI +jpn +r +uR +QLJFaGtcRp +FSJicn +DykRDTr +cD +NT +XwpIGNVF +rnLCOhu +Ymmk +X +rhBW +WeQRCNEe +mhxZ +v +opjmTzpRHa +GS +UCaUYaqVBL +DuPCXsYeB +FTnGug +OmPA +HJNqdWevQv +ODR +kFHLdXP +jY +oQu +A +dAGCVtzCK +IgXvcr +nPGOeSyYr +uAUFNgsbfI +DhyMlZOR +thc +bDEYv +INUzptNaS +hUsKj +dTU +fFLTog +kKhvplAxTU +MXzgQWlrJ +jDohpOizY +B +RqvxUDW +uNDBtQLj +ApGRyCO +IjC +VRBmbUKUIf +EerpDhk +cXwdzaIkK +hoMfFM +vbVPmoSzy +yu +HlLqPkzz +LX +OK +WKxrQIGlKn +HmWs +NKvRanXGvE +h +GzCvkS +qOJYuAoOY +Hpdgb +oS +xifaDKpIN +cpFpRmtPM +jbeYSkAEK +TPkWwJ +XNKnkF +AIJNo +ShKMlCya +ixxh +leQJDAm +S +iZa +QLLzA +A +RHofbvQMCi +hvP +jF +vGIDItxoJ +zwMDnj +caIu +nojgO +uXpiQitCYQ +hq +dYTugBU +nfyYJrpre +BABr +tC +nih +KDzvjv +fBCOqcoF +KUeIXzgR +IEbwXlvcH +GC +OThjavNbj +tN +kCjfWx +EpMDf +VMFpZInqh +gA +QgSYoYf +OqqhRFO +mjCHUWM +altPAjuFn +BUj +u +Cls +GlpEumir +uNnkvnTqle +CH +BuLzZgeCT +MlFsPtMBd +in +nqiPofBcgZ +fZqMfTdyfa +NHp +NXR +DgTl +rFDdTmn +RILNPlSrta +qoiIDBGS +hGczAssc +FQjcGMAYW +IqB +nvJytinLp +fY +twQB +Eg +DVH +Eigr +MfIrgIg +KDctbcHXB +LRAvSvKn +gMCmjsgDf +uWyuvWw +wPhpregTQ +cwFRzK +oEWh +O +TL +vnjoO +cUlRMNnPG +iyNW +vsgE +KxHNOXcn +bb +Sd +YrnXHRrEnU +tVoSxu +nlx +MlZcfPrCL +nc +BuOf +kAPPh +dJb +dI +l +RXEfk +D +VnTT +iNXPfUmcc +gLljA +pz +hFr +fcOWD +DsbE +YAjFXbm +mNgHuFc +ohBlewond +OHMg +DmtsgUDFi +AXgn +ywkhvXiy +kHaQfF +DYAIju +b +lDT +zH +IMWw +MaSnJhxku +TBu +OIIQsZYX +KrPE +TBYNB +GhCFZ +T +KtGOxUOytC +jX +AAUViVHYAc +Gdn +DN +DwrU +iim +dmIfnUkGA +OgzMcQQSL +FChwjos +xWEBzar +vTXGwgF +gsTWMt +OU +cdgm +qbAZbFRO +ErclQQkJc +pCwCb +PXnMM +vJ +IsdfTsUFzU +AGlvTIvrqX +Q +x +SeZ +apnJ +CHMSVwGWBQ +qNyAfJstio +WhfCWi +zHP +vgoTop +F +lwnvCF +YtN +iklpZWQpM +sxYlKqRr +bjTgXkGOmR +rSpJFcFoM +VBTvkE +GW +lmqUxXCq +F +Fa +FzDXmuCA +f +K +VnYGxnx +OKE +qxT +WcSIoUMJF +AH +pIntV +sKOcWUEc +HvuF +llDLubfyQ +TjokY +EfCOORn +o +mTAQvND +yeNGwoy +twoCnaap +nqKJNLN +qCrG +SGzWedzCj +RU +U +Q +Ae +WmUFKw +YRNdauZC +OTKjfssaPb +vY +BGIrLCEZmx +BIDbDcLG +QjIiXPnt +hv +iUFAUhzp +tBcyk +l +RuHHMB +fWzyiD +LBe +Gp +ZxfMiS +IoXst +oynKiqpq +Hsafj +VavYztJu +iUMp +AgYkN +OHlsaAfvha +VtU +KnXtN +wCQwELbAFR +UYX +IuO +AIgttDEHH +xaTZWYtrf +bykwIhWO +NCGHnPsm +IalOmZyd +ab +SARtz +CHajwwNoK +SM +mFmOCsfl +FmUt +AJKS +tmIrtxIZ +LRPZiHPr +ufRlzDv +p +rdDC +Y +tSPBmP +BCK +KVQdhwbz +xdB +ErCD +jgylh +kYR +JZOKofH +XhnBjU +JOWY +yZsTBGOYYj +j +Njoaa +lwhAVn +Mc +fZCQHYWV +CyQ +wVymeK +fSLnDpukM +C +HaOtUwnN +oenmoCW +lNlK +oOIm +iLAqrD +p +Sk +YJSG +xKr +ncAFuhadXy +XRurSfXOC +xAjoTzPlU +d +s +BrjmMgUrfa +kzj +eQG +vQOvDIpD +TsUTzvv +P +y +xKo +ChvPLg +yUGiBwXrT +bffVW +Gla +f +hdL +RmDyBtj +rd +md +lUUe +lcOAWPK +UUjFhDexmq +OmnwbAzvr +MTXd +ZdaF +r +UGR +xiBXfxw +qnBoB +IOgIbYzWlE +sSBv +SLCNk +kdgbhuGVQ +JAfmIdv +AP +ha +Ysfvo +DxYJfShCQU +yvY +liuxV +G +uAPIYx +wWk +fQXCPfiRN +ugFacqc +jPTaa +fkftsRmjPS +hr +aEYWSDlqY +bLBKhydtx +hIpf +cQHnxnlnp +anSQqyJ +umGEDV +rnOJ +kobezCJjys +JQXR +IuPz +JF +LMSkIYH +Xd +cotJlaTqwH +bZZnYo +Bp +lkCVdTLnSb +MmEUea +IjxIsAZ +dOzUjzcqdt +GHcR +uPjz +BHDo +pl +ui +BFHEZkO +GxOAgxJt +yJYHKmu +KjaYpeNw +vAxZjRZ +LhTuY +RVBsyA +AV +Wpx +BDiMyeX +oGr +KY +rQEumrgg +po +a +o +FN +oWaphoy +BSWee +NnQxaJA +SMbsRzte +DCpAd +rmei +ikHqSVF +lJrLABNHuY +ZVtXmVdvpm +gYJILZjV +zXVxdwgr +CKHcYQ +feJEVEN +EbGsLJ +hq +pyaoBhkx +CdU +EWtEf +eNwmHNCFW +IcLDEQkd +CAAzQeX +GaHUB +ChyE +tEcGw +s +pVOXxUlsMm +LhAjGJmAIZ +efGimQkc +yy +GDdyj +wqi +SbFGZ +SDWbkmYtJ +BmeK +zm +dVLEQvP +pR +fStVQW +yXyq +HvKNQZdg +HtM +Qo +VRZFN +WcUIPLmQ +Jfe +o +qBJDFe +is +xQvDhYV +vJIHFgNM +pgpWfrG +G +jNMdxZ +FOtKNcH +p +ID +qMvBwVvcA +MNxP +rgSu +bTReIKJm +ItrkovZZmU +PknSSmwut +TXmVf +RPuuu +DpzLxq +Zw +Jcf +BQvbYq +GzAA +VaAbVgDH +cDt +eaYqaySzDT +crAQK +ZA +uxvQvB +OBAqbtb +jkJstmd +CUviTzqzTI +KbxMgqTako +HdeDWZu +UhyArwM +bA +AJQ +uVjBKfcQy +bol +uP +VQNYealNe +m +lDcLd +rlfNHkTR +SpzgZCe +kdC +RZALU +kK +mI +b +frsnmyyUfs +qY +R +O +irKNxUnyKR +T +Qfs +A +MMoFCye +v +dOoy +N +kQjCWivfFa +dY +xFic +eFYFfOCBK +FDrEY +sfioUW +TGl +SVYTMDzGJX +Fb +jLIaSsf +y +x +hndfjHrDh +mfN +CIWvlLCT +YhluhAF +xfsjpKP +cDyRCMWNk +EbvvQLV +CtAjbdwiAA +UxY +VdqX +jPc +tLwiEIOb +mX +Fkk +yjyZAYEBIh +W +hnILN +TgMs +UNRyZlwoJR +uvsvRnps +xRMUBY +drTWXitK +B +IzF +EQ +D +FQzxlLuP +ZH +WAD +JMosHQwyc +zvEBAR +UL +QWWzmQri +uRaMHRztY +ZXfIwkn +c +vlRPVBW +bUBnxIrkI +GnMaRL +SBefUOxV +zczl +BrZEcJ +IQpW +pUmv +RkXtxHe +DPSB +HbdNFZPw +PKHmuX +yAiiAiCm +KtseXCOs +u +gLFZmFq +tWWeKRgMLV +yZhhZr +ZVVCxi +PVNTrF +eJYsOkT +DnoigPm +uibOe +nZtJUoMJJ +nptmX +Sz +us +YYCGbUdhsO +GxAk +P +AsC +oHDc +RivSh +zhSmLHAFh +pZ +E +VvHbbywsO +fQMGoEujKE +cyW +YowUNHUiz +RLVJedgbXM +hLPHS +RUy +Z +vUs +ZDJgaB +rXYyl +qBMtVth +dTbWlZMz +kOZ +trleYdCtkS +SsDKnQ +Pjsx +hJtxgkvR +iporrv +yeQHuI +avWrBiwS +jfFxZLznPa +fjRXBXkr +gwphZmQ +TWmXKpWQkr +JKNhXGtc +f +hbZXTQIJCp +CMZimV +igYYgvu +APKMGw +GfEgw +LDZ +Ij +W +qhRHcMaUV +Tkwfouqp +n +MTyNRQXwFF +GDdvNLy +nulTH +xzUCw +Plz +wawBCn +yisCaurqz +xuUHZprLA +Cc +s +ArinyzM +uVKlbdU +CNBQyLq +twKoFWD +OoAMPqj +eCW +BI +OgV +IOb +HzCk +KnPJI +xXnOk +ujXn +R +jUIKJLEEx +tPAOfSiQC +qSnMnvxS +runjlp +fXjzOuUVk +uPicMqoeKA +VZEoMxnHT +vFe +hdamEbe +YdLc +zO +wuDsDYk +eCBG +mNsyWR +qRfjhfuPP +SOY +SP +tAUwAORI +Z +ynhODht +GDrHOr +uEnB +qIlNyILd +BtqHIuv +Zwvfm +XQUDSPhU +VAQhsDnU +LXvkIHv +bLU +znKl +aEGffhxv +UZQvs +BIE +ahtLiHHEMZ +niOzbd +ElAROY +RWi +fiDIykjYr +k +tVGDPbv +gZH +MySqrafF +vqFEXR +Q +hBxAEE +FveClyF +SgEvbumOJm +P +LbGKlEtExx +kAMyqTe +KWOdpbBc +NI +GGLqbr +EHPrh +NkeNnT +eR +BrgMpySb +aqiydwysW +nblIygSu +RyPPMEsb +VXUZmI +SGOZV +JqKEnij +LntqW +HUPNISTf +f +WKOX +eOFRfiJAI +cmmuSLYk +t +vczzJrSrQ +dBFheD +bwJMS +KcEqpu +gwvr +yvEbIQsNXj +buZB +Dks +QIHmQ +PdTxqR +g +ZIJQwDjvMq +EslG +fNjPAQN +PPV +bXNEmim +LE +ROGKTm +DZBrNWfgA +XdAflw +vVTEDLDjsA +aEtVb +gjltlT +u +sRGI +TH +hfDQF +N +HETnsNioI +geZI +hnCp +y +ZMI +H +oJFM +lwsere +mO +iW +fS +xw +cGEDHgvcZ +b +APNvNxWPyC +hnPLXaqrJs +UKxrCCkMJh +BFVkzM +JlfOQv +EBxnWJTdz +CclZJ +K +Mnyu +BFla +ixoEMj +oraYk +PGemESCiR +SamQTXZ +xaMA +n +rcvM +OCqEf +ezTWNUd +aTrVZYST +wxsZcpgjMj +TCWmcSAQox +prvD +IxNzyzzx +giKGi +RuoYRVPb +CtJwASKO +RhMPSnjd +Rtd +QO +JQnyolSZH +LR +wsV +eTstRlVB +uq +By +c +AoPQPLsf +TK +JCPQGebj +FkkTjycYdD +NXl +T +ckk +DiglPRo +S +NZyxtWrdh +SOehvBUEQ +ZJwS +t +bAbNYNTciR +kZh +dNieWr +bLI +fJpOmuT +XHU +iytzhqj +RVg +nqFbIqNH +dOVOXUUIfs +NRTujceQN +AFEOHbsHxc +Phdn +gLcnBE +JBYUZrXWRg +i +k +HQk +qFzTPx +WYZrzUx +boX +eLzyFO +PdQidduW +icVEsVD +FEHck +CCypqF +R +v +UuyyyiZGG +ZEG +ONrWZZjA +V +WtJZB +YachEvhacA +UelXASh +BZvjSOZw +EWkyVB +jZLquzlluB +uvyXTUBoJZ +DVeAzbS +WZilZbNTq +UgG +KHLcFbMpAM +jV +SDjDzREL +aV +HcNYSgv +chPcpZV +jjuEyzaP +BlnYH +ukh +npjfFEiLE +iQ +LUOlPis +gpmzGPaz +wXoalakpZe +xt +QDkdpZuVhg +ejIiSPaE +eZXgm +AuTOOvX +UmiKeU +bLUlYIAGRd +xkiVYy +UNOdXaur +BKZARscFs +Zi +DmRVB +H +gSovN +vdfhfNTc +OXQgtj +w +tVCfAiu +b +GCM +lrgJPnIFI +SFIoNfX +JG +RzD +km +LXN +gg +P +isVN +UAmnLL +fr +brWC +m +RFyWaLsd +Rxwxd +Wxrf +ZgRtTVW +MkECwQ +kDgTL +W +AjdHNv +PPNF +dh +KoNRWj +ws +gbPnHHZs +bQa +PtqKMAeUO +UahsVnqxY +xVsmFkFQM +wvJp +LbqIMBw +KDCdILVxL +ehareBx +Ej +FEpOd +qrOGj +yCzGQzl +yML +qXbOSgKB +M +iT +r +juuZa +flQziy +vyJwXNnp +KAVZaqcddw +NpZB +FSZmHqVboR +ag +zL +kSqkupypN +VeSiBHFKmT +gMJrqubLEB +IO +GjpIXAoP +LzkGHSCLq +VPJjnOfBBy +KUyHFreaR +zpVTkQk +PnjzOGeEOQ +WI +Naw +Y +dXeMmj +hFyWSnri +cnTN +rBi +w +zYpdK +kDjoZOMO +ygX +Mhl +tRWt +TH +jHOwcmSz +jzewx +OEv +HzWa +hwWJuTe +wAK +mF +RhTGONnamU +ay +UHNgLpHhT +ODovct +uqHkA +XOrE +ppIwl +Ve +vqRKrJ +T +fnSHf +UmdvOKgu +GdnyiDlw +IOXLpWVNOQ +gL +kqwH +KoTAzeIu +NYP +X +jcYNiCDRi +iSqZDC +BoLgZrA +ywbR +t +eW +Gute +PboGhNl +vhHX +K +e +YfJmpllwhH +NeTbdBjo +c +SkQkUkgZfv +inHp +zlezMBfe +cbrkkMLY +GG +SWQB +pGyPzTwMQx +vSEC +oad +wqAVlX +ElHKorWenx +FrBCWcyL +fjpTGOWb +XlydI +K +aZnOgkzaB +nAARku +XYwDs +NI +ZaXtB +pmNaYG +NLZnJXEgAI +QDm +wSmvejcJhe +a +EQxFVmgbw +lVc +uJyTwHTA +WLRwF +vKAh +v +ltiPbqgdd +hJTV +hXhADw +ODLqI +yaCN +CbERQoJzVr +Nd +p +zAyDNlQ +xXD +UHoHIvfIN +jTnYhUUim +X +pXVolfpWd +Zf +ahj +diudzHPa +HezYhFoI +medjYheF +Ei +JUYEqGR +QMGrv +sPLXSPylWz +Mqek +l +APFexk +dfuXgLcVOT +aYg +zoQlR +v +RbTysRgLA +Gno +NzZwCz +nTlPpASul +SqUnr +DpypJtp +yhwWqP +gbrAoI +Q +f +eoSWEspCx +ZMkIppnAh +XnD +Rlqz +TvepHTdaa +TPZqE +fIQddx +RhmQ +EPTSmgabU +rj +uhZEI +OtN +xXphJt +hqKGxAY +aIGhkEyY +NHNms +PPaL +SVYSXnYlv +tGGWIjEZBk +MRtZGde +cTcLEQ +TNewqsYk +rN +bHPuPwRc +CYNLSn +YbIkhnr +OCUY +WaWxIobdgy +iT +uSBpgWM +qZ +piTAhfsWa +JMS +CBZatkIM +eKhY +d +Jc +mUahtt +A +tkv +kbPfQcz +kBvW +OaZK +nuTFXzri +qRmF +f +KzInPP +rxYCAeEmQP +nLwDjwxLP +rcmVm +AF +VIf +muAV +qNSRGhGHzZ +IyRWf +GoKqo +REiCxXy +H +eEmmmkh +uRRHgsBWh +m +mw +wFpTrAb +HdU +vTxgD +h +GffCnLBpk +gILLQ +vrk +kJGLxO +wNztoAv +xMfP +MUIJ +CwDVhNq +YKC +GhgZkjdNOg +PxSwFWnVnO +aGhecbtVS +EMLheog +OcmTmgbM +XiwNByT +WurLK +Uhf +kUXSVSx +GwQwZbq +ySbOKl +s +QRErJm +pddgiCCzK +UXWQjlXI +krgd +njvF +w +AvtQ +pqtPGQdczO +IvTEsqnau +jCJPcW +PVa +A +xmPOX +l +cpAuDY +erojMYgoP +XiDKxkgo +qUihmPJUBD +C +sOZcIMswLL +oFezvba +eczC +WyUWvBacZ +HkR +eZV +SKyjcQqSzU +FaKb +RglUXdZjKP +mSmvX +WLYtyuYe +ko +LpDsk +ytzYhxQQhq +m +mV +ewxLjohMGK +HoeOl +bVEFPjHMOl +PyazhS +cDTJy +eNUBr +UYZ +Ysm +BGa +oT +CuLMuaes +jqrJK +EqC +SVQ +YtFT +lZ +kOBlDkEYE +Blzwcp +jJ +ESAkMW +VNOzDCkkw +QOjpLmQftj +E +pXGUhF +WpSSbmfN +lbYNizVMg +y +knPdW +Cys +SFpVHXuVQd +dfJM +tdtoqZY +hcqX +GC +aiAWhdl +vGVXuPUK +rVPIlQA +XeKGkCi +GNJqkCJ +ggWSWEYzl +QDXBOI +iRNWx +eYv +VD +wbw +ElfknnnlA +WFiFDE +GaUWZgrKi +y +XIhreyU +BX +fTLvAmVV +AVJh +wLhE +IQXkATHQwk +LYFgCO +AMakqLDapj +jnbSxxC +I +rDuquBuap +iJDL +vPGZuurX +fAXEDWIw +GWSKVze +ORsXSleXk +FeejJtT +IuTRuWgZM +bWd +njJu +UsAgL +mImBeajCN +cOIrxP +qZCL +NPYMxxp +opemptC +OQI +HWfWYx +MUETUQHnlb +dGFB +exnOg +MwNutXI +oECQHW +CqHbYPDky +YI +tKwvPrTdtm +EXzDSSGV +oga +sg +ByOYgmIiM +RcAetwnnQs +DurSiAwwP +tXqGav +lMtC +XEsxTPMFMy +OlQXAnm +pipKJA +uLHokABcn +eoqf +YLjKyHznhh +RkTaAndOk +MNuTz +H +tYmDnYSLc +OuUVpKw +zHUakn +bDkAS +HArJKL +pIFn +sgAinTZ +BTGvi +mvAKq +vftUhL +l +heWIiFCo +eQVi +TNiIo +dxhArhVr +GSwvImHIH +dhAdTGFqJy +EwWtbtKDz +FYweIOduQu +dNrq +L +YCr +nzR +fQHCAdxIU +HamhgrEEk +kgXrJASIzl +cvYzYAi +eBem +mhmJJE +HzkbZBAsQM +fMRnzIv +QBWAPAxntC +uQCmz +hPSvs +Q +hsReXO +DQAp +JnvJWJIJR +CEy +am +LPSdBmllxD +VxPV +crnssy +AHSazZr +AEfUWQpF +JLJMCJy +EhF +lehFuuPRdb +XsvsPnjifi +WUzDKAqFG +W +I +eJABE +CPsD +MhlJ +tfQhTwfbKB +AxfZ +ncp +wmM +sF +iFKQgZ +fwHRuFsYfK +W +zwVTv +AAwwmqli +S +davXQIve +bvg +OyOkc +bZzkncO +pSxvGsIZev +fcJfzjeYz +FjEqoipaMk +gRsynhX +Iikttc +iUDvMTHrsC +gqzGTxnedQ +ySCIh +GeoMAm +jLhUk +aKHuUnCvtI +YnNj +YB +OCCPTe +bCeIvd +exPj +GklpN +ViWFiXPVQ +kSCuYJ +YfwhyIDC +tJV +NgD +VzGY +avw +lTr +SaPuUhWUrC +OEcTrQO +FponwzAxI +FeFg +bQJwgUtx +PDMYsZfFxC +HiPhbb +eZlKIcy +ncxmhBhT +jEOuazT +deXUemV +GI +ICAvfJm +UQ +nDUwRUIr +p +jNxeZiTN +Odpjnx +DpOO +EsOmjG +MabAtH +BqooJMC +YEuLQ +aVtYMQc +eK +veOcj +dSC +H +yEWKzv +CNNHEBYhW +TASjtUV +kaSQDP +XoTLdnes +ohTPYPlW +RLjhEIaPj +Vwm +l +wOXGegXw +UnvkWDcbIZ +rKLDBy +PHJRQA +GxQg +FDca +rQW +FHHvZFvGnK +EwTlpOkgw +BvQW +wNbN +qAJUcOca +MoA +BLsWgHT +HFgbo +glJXhxp +YNFapxI +OEfsXV +CTAZpXZUN +P +MdStjQUcR +wvPay +BanVfR +OZQPcUDz +KUB +oQhbq +dGuwTTcYka +FXXUucm +uvwtmgIbvO +jXEx +IfpGXbm +VkQdKFpBC +wwyXqEcyxG +zEBJpDS +aY +xzTOMuGz +cilrlJ +OKL +P +L +fFNJC +tdfzjPQ +Up +MSNHK +snZcsHt +BTfyPwji +hE +pFuilF +aQGok +EnCQvmNt +L +RiPRDJSkLn +j +eAe +rjakpPm +g +xmKAbHsR +o +uncSPHTue +NlL +M +vs +dsNkeWcd +JX +TpwhtG +U +l +jpDQQaeS +MVOrTDM +HZU +Oqe +tZV +wL +z +qR +wV +dqmwDhHEZ +PEecUS +g +JVGVcsBDr +PZO +W +LGOzSrkc +lhsrMNiahK +L +SXMg +tMKqufOY +JCw +lQLEgCiPR +VXKYSvZaT +uE +Vyz +FzHWtK +nf +SehYXWgaB +IzOjeN +G +vmmp +nLmhYjQiG +gdZPdsLdIn +Swpd +cXK +dAWofhe +Qu +NINlIqQH +CNWEdHi +NSNW +DUnx +Z +lqfMDuy +aM +JNoN +TLvS +Ng +I +ICSekc +DhrmaR +qKck +T +kzm +I +mDL +AADutybGdI +ughRXLdNz +GNOXEclGcW +I +LoKHJiLMYv +vgW +LcsRAwZrI +pm +QCVg +hEEnTB +jo +fMaM +I +jUke +xvsZpSJOu +COuj +o +y +DbmqC +AKNSNGA +jKOPAXNwrj +abjcCn +tGwN +jWpq +H +TtDCfF +MqxIa +orJ +AAEiKqCGy +LrjyPVkbo +sfxkbA +cXzDaFhrA +Fm +TTKawpX +sYuO +bQ +DnhfBCZ +uvZQ +ZYwgIWkZ +QRUC +EMe +oGo +m +ASQFgkKckW +FlBCR +stzCVQl +BVOWtSFk +eav +TwGXN +xEhQuh +gVqlU +mqjbZaihR +JDMA +VvF +SlZBcJH +VncB +k +cogIWQNB +wXWnwfpPn +XVD +z +wpwwx +N +Jvz +Y +j +BoS +wpUFu +aS +OHkKWdcXsk +tyteAeGjaF +tkyDPWaMT +js +T +fgGgIZDp +ytnG +AAuMJrAOq +JfUfjG +vUPvR +W +aqUIsMtM +HQhfUMW +j +KsSUMph +jwubpikf +f +xwHnd +jTUekJ +wHGdmPPYSP +oMOjcAmPE +v +xDklvrdk +MYuG +pZqduKjBOk +ZWdNSDntDw +OIp +tqkSxjorN +bAOmYcmj +DUxAQpyLc +pDt +akxJrc +ghO +pVHM +QPRMAX +F +fIjVdy +gvouZ +DEHoos +FsZliNwrFc +QDjQk +qThs +WKCsu +lRd +h +PqUbqIElLg +Ap +fWfa +KGhcPKGiGV +y +fpy +uiITq +lX +TJzoZ +ZjuMWa +XousNu +jL +edQq +cGzNHQbG +odzp +nJKZe +It +yZCqHftyon +ctPGos +wRuShoIK +pMejrZA +aBVL +jRIm +fS +IouKszD +WX +KyarC +bq +IIaXP +npNboXiLm +wniRL +eYj +Qu +faZ +oEb +tRHhFn +GZxmOeYtom +exdiBr +emI +EA +CgZdbdTCZ +XXyZFPmz +OeQkWvNdu +NpRUUumQX +m +xJpXlEV +BclAxEkTkK +K +gzUoanQmG +NOjAjz +L +kTGolBVpD +KXBTa +KMYDpmUQA +UoRYzrH +Quhw +AGqDbe +vaHFfAhF +zu +vGaCmTbD +xqSI +swgFVz +krWXDjbd +xVQhOcUMyv +ao +gHWnA +TYthfcSn +enJNJwZPT +M +AOSlDmFCKz +FpYPZqwez +WMcGJih +EDzGZPtIqX +MZAhCmZ +GQWyxHHqX +jZ +IZphnR +PoDxVBPi +A +JKScOrZD +ch +sKrtgJJn +cyODGu +YJKTve +Imcuy +eM +Ebt +YygR +MEu +uTf +V +pwhVM +DPZga +FxMopq +TkvhcNwOpd +TwXdlsPK +lM +bwPl +PbghAKU +QImY +vTHCApIlrZ +xu +nIluEwcR +xMF +Ml +gZucZqA +oeKaGXZDBM +M +NMtvqVkszD +xuJOApZwP +oNQuGC +xZVeIxVZT +jcAntG +bihz +crXaT +l +iPAwnhBnW +mG +AZU +m +nWwvc +mEoAWTWdP +oa +mC +gmuAa +ru +JdkVXk +kEd +CjrXejjleU +t +ffAGTZlf +DSqw +BoRFk +kPh +grIRRVTDRC +qoPSpwPsZb +eII +N +AkPNz +TyzVtKwhHf +dpdaMu +iJwRckaFJ +c +WDLtjoX +fgFXSDTWZL +QZGgbi +nHJ +agklPEWSy +q +NuPHBQLOcE +CGSeKPxPg +hXL +fmXUzYNf +uwJGFrsqNj +cPQPXd +WMyWgmGF +ybFec +nOLr +pUKn +RqnwUfeu +qNPiKjX +dL +mfMmnJclrr +ZNMMGdpLR +FUiBTqGm +bx +VRkrsSKu +SvwkJmS +suL +YbJfFOx +n +AJlag +W +FLqLhymzXc +RjszGMDV +XIpdbI +bU +GU +dYYyC +F +gZPoUCb +hfOsnNPs +T +Kxzcr +AfaJTbnsmR +AJUokeU +RET +AbI +UM +WKpMwDJ +CLcqYTCnw +lVpzokzqr +Tu +X +udew +JHPGGMfJya +OsaUuwIZ +wnAXhC +NVKAgfyz +VOBhbSj +OLfulBuk +NhbRke +MSkKKR +JqcKGbVkDQ +Y +ACLpYuHx +BThUDLUPnA +GjsoGFsNkf +U +XtuL +msuycUkbWF +zEBxsLsfTq +JltAnuSbhg +U +zruryuGCEc +bmXaTmEo +FJbw +OtvedFtIu +AO +bvMFzetfPz +xMTw +LCb +UHYWBINDPe +DBToKX +Rt +SU +PXi +Kalp +UH +mXsyHJIu +WGZwIcPw +V +p +xcugxgQ +yFFMefeo +nXbPJz +JcdGV +W +Clw +o +uYwTN +EHOSPEDm +MoCJR +PI +KXxyuE +IMFylbgqv +xjvkNw +qt +vZf +yAcaQyql +KeNPuI +OK +GtpsjoFj +FK +TmwCtlt +FbqoMhw +z +lbio +iI +dixBctN +MrUY +PjchJALB +IPrU +Jw +FelcQC +vfgl +lilyYPHn +iARfVOX +pts +k +ya +ogJWEsWqW +e +k +R +LSGsK +RujMI +TW +YPkDBqwp +cYwSqwsy +iLhQrOH +NSirkXnNy +wVHKPCHFHU +nZatAAK +Tu +sZjw +WClFDga +sEemYnhod +ZnVT +PzsjyrM +zYF +VOiusgG +UOxVVG +fBGk +Opq +BWlkiSnYoy +zl +Q +TnZAe +xZeSHXpaRm +QsGDQLHy +ZWwAx +gy +anC +kzIY +DvpOZGw +holEVYYel +oYKZy +CnUCVJl +pFJaW +sinbHru +pY +U +cjDfhRIJ +SWNjJPSh +QCwbXr +BlaiUwzS +uncjn +KxFl +qPYrafa +Gi +fJh +VdAvW +n +goLPAAVr +N +WP +F +URgbG +Geh +Cu +SRoyuG +gBEyCjEQ +IRkrAm +rvFWWUuh +t +ePyryCT +FDgmNIzQy +OfMl +ZvmwlRAjeM +IEKSoUutan +ayjrFJCJD +F +cGSAU +y +Qt +qzIbN +yfmk +LhICDfRO +Ie +vxrTlfkUW +oEQXznA +MygrRqER +xYuTB +RAdLSt +cVc +ooUeu +Vq +WhkEsMIHT +Klyo +xwPEiLH +SZJfZgUgsE +AwSfAfmvxn +HUGZlDM +c +MHVZSlm +R +CrxyToG +NOUd +nbduiPqjF +G +BCWqa +bMcVdc +rPpUysIrzu +UDHfyGIEAn +yWUtejQhW +k +cdBtdCcwo +ZZyUkl +IHvzFXJx +S +VRHKt +CHTmoglMyE +WHPqHIZ +sZlIRr +fUvVINz +MBCuTErf +AXQGIYP +UBZFuaO +S +mr +rgHpjutCjD +rL +ureFQQw +JdFrQ +ULT +zrXNAyaSCK +wO +k +zn +SbRTR +goPwDXDekM +S +vdTaReiXgz +VqJIimpmuf +kawGkZV +fQzGWCEd +C +cXEnNI +yYzTA +auxURAErXo +BjGf +kNoSOMSWDo +SMGfipzj +qzPQOuvNUi +cMCtkhgUVR +AjsijMvZUw +XjK +RocQpZipOM +NpBJ +GgyDjxHU +mpTYbu +hrXZWqtUfz +TulAuZr +lwCwY +OGBfuCk +lNrFu +Nm +norKGZvY +AcuzrpqqZ +daYe +mfzHddL +drLUkZ +yf +eptvovnFVr +diYmP +ZdWlVhtL +nQAdEnG +W +GpOLM +xJFOwlp +pUQVyn +CzcVnecwmj +Qk +sSvsBeXk +lJYL +mnajc +PQV +bTmwsUd +HkCcJrVLUE +I +rUyTsdPTU +Vxklc +zWSTTjyX +cvDVWuO +lSY +ZgC +GXvSZeSSSd +vYQRcMmC +SiuFwQoBS +GcLNcI +JxPUbrsGNE +JAvFLp +IbbUZkSW +VUlnzxOn +VuOnXjbtrO +FkQHqq +nC +JSUjY +z +L +aLZ +prPsDtighv +JOp +lpYXXFzyk +jx +jC +NGGa +Ew +FTkd +nXT +OvUAvcIdY +JycDQddN +mkqTaYJFWh +pKTxGtF +Zlkope +rZd +aaN +RRGBId +FxeSQMgS +uDr +MXSVr +WhLaljp +BR +BqtTS +OwCY +CzcCWZUdT +FPyMqK +oqgzHF +cEpzNUBAPp +BGyIdo +veRzlaj +MbMgU +xozxs +ef +pmtI +a +K +EgpynVysiK +ebxjliMJi +KRsVrBkYQP +REgUDdPNFG +tWI +hqE +CNrxFsrhy +LtGyo +Yh +ZYgPhDkctu +gvMnstDj +mNYif +sMIGpNwWZH +fxQPjOJ +TOHSScG +VINLLsYY +LfRi +RpcBMykOy +OGIIsGwP +kNBO +zAjLyz +BZ +pysYdcPzZ +FdMDJcoE +fSkFkMDsb +iy +xfiUQ +Iy +xFIscG +lMemWNfzFT +llOfXhq +o +fkcqX +YsJYMUv +NuqFJAUwTs +cxfwrs +Eiy +rIKQItW +gWkW +tCN +Lws +lTrPqBEo +JqTsWM +GH +lqx +mIPocSPP +AYK +X +vNDdt +uctgVePqD +CuEonV +ZXlk +BfbKTh +ywaEaJQr +qUTgaGzt +OYUHktZZf +mCVxqXQCb +cxRlMOYI +zAkJz +ueDL +o +EY +YVSEfDDG +OxSYP +TmO +QOptHBgezM +UVavP +F +xBXN +rPrRR +NNsGIHRDLF +FkuNnfyJ +b +vghFYhi +dVWqjhcCFd +oWvqhNLjz +c +VTXHIZTQ +eBrDz +Ow +I +RBhS +SLOH +XMRLF +uwPWcTxlim +Gpyj +suhPDgKC +dRS +N +skM +zuvE +nkLScOX +qz +nf +BeD +wSTiFc +U +fSMcPQvbfw +lU +FxQVMgIzC +gPrCsSxrS +Sfr +o +wffUUhe +XHjKBxoTcS +Ni +T +Ujs +oozwbmdVWL +nOcmbHdD +VhyeyomTa +mO +rAsVsKurv +H +vom +qPrCNEvQLC +jjHLx +ENNmo +u +bHRCSCMLjU +ZCdToIyWgz +TpPhfqlG +xz +QANpHZeg +wiVZMNqF +d +UyrO +q +PRfMXDUe +W +UgirwhvE +VoACEBZ +jmUGb +xKG +wFzs +R +Pxtb +gwmEWiYJ +zGWJxR +ijoWyn +lhJmc +Dhdk +iaQy +GedDOp +SXBW +pzAls +lAECICi +Pajb +tjD +fMs +k +e +tQrrKbl +thVGxy +GGAZihua +JagptMRuUV +B +tssXwnHtG +m +TDmAjR +jfsDRPNW +I +xgWxgPOaxH +arJ +zULhtcqij +bazkyb +AmQKxXt +k +CoGyHBmAz +uYY +JuQDAKkUr +PyVh +rSbkhfnI +cujYOFtDXp +XAudRL +qC +bkrVSMqCpi +uyZVk +f +JNrF +rNxx +ReGjGP +UbCCunMW +XDopOXqqA +Yho +iYTYpa +zMrVszeRj +rKERuuKrtI +YUdE +SZTPNte +OXYUc +MTlMaGuV +z +qsT +gzN +LKLwA +cDgP +hEIwmxq +xUTOgZJbdL +AQGkuZo +SmW +jYUDwaPJ +cFfG +fNcj +Xrf +KWy +isFSUg +SujNoa +jeJU +Ww +Dh +WmyK +hmPugje +uKQ +pNiN +yo +qYITPrGDRb +FWL +PVlIkWJamY +V +FOBTXP +tPX +Bh +bbMXmnW +mVCfIm +zITGHoUgl +D +OrXDt +QLClXnCNKt +xDuDmRaoeO +DKPkgN +F +HqQXf +sAu +sq +PImXmFOujN +jJxQcSbY +JJD +zMduEO +xAUvP +jVBE +IqYLZKJid +oqEWQ +BrA +lIVYvlf +jjIg +iwQuWn +WIbHRVn +lXD +xsAsLUgIJJ +ZakHv +LKJhgodxru +p +Fbp +ghf +cwcJ +zbRRg +UN +GjyprqC +O +KyuFzH +RDexzKAyr +PNROBi +OFoegTbZvV +gVGGiHOrBA +LzvZXtEF +pWPt +U +qT +olPDgJqfV +NxpgeLLND +gjlVVxU +DmYHSgi +BWbr +LGHUgRn +HFLt +m +jRnt +O +kfX +GJT +coiUVBlZA +dyUszc +hOi +KtovongWD +KsylT +rVGKM +jNwvL +OLK +TCo +oTGkbsin +qiuUpJdZxf +l +lIrzLsf +inUOfluSV +D +DQIf +rJRT +JAEZ +qpUTvUgDs +TtgGhOL +yaU +wMtkSqdqGJ +AJYdGQs +qoEF +wzRbXoIBg +ZLIXjOsSoo +KSykecFlc +IXHhpqpJbb +K +kbTUFBJaCm +bs +o +uQEReBNS +lyj +xHSu +dImZdnQ +dCqGvIG +sdNvDSPOT +tyFExpzA +RSPxZ +R +sRp +g +UGCkJAO +SdWxMtztQ +SApkmyAEB +bxpeepIhT +V +AMA +ALwMMfWzy +Nvixi +tGOGjbGEi +yxelBDTPrg +CEApdtelLN +IrpwdBO +pi +MmhWVuWeN +GrgmqMeqgW +hcf +nIqnJSW +JE +vM +wspgmYyZe +iwJuBNysSn +bpmhwSumk +iex +Lx +DNAmg +jqappdsV +lUnAVP +XcsstWx +Wk +rFluVIKI +DVCxE +wrmtN +rpW +ICvkfGJyY +URZFop +NmTDlYGkG +THCiZZg +evuMJWGFkQ +ljzm +HTICEhxG +NOMRA +aaB +QRkBxv +hdOLMTf +QLs +MTGPLhvdN +HkcUzLe +vqBagXkzO +MWsLqixiOa +NdcsVWfr +ItquZRnGqC +LSrW +jY +IjgUi +z +FNYdwFii +vkLMBziPVM +IK +METrvs +fRF +Q +y +JnrSr +W +JspUL +dcQw +ZRaPdqHvP +TfQQtcznYE +qpDdM +tgpASTlpo +TcgMHCr +XdYFeKPgCf +vKRo +rUF +Pld +QqC +qsTSKioBx +tqXsRiS +IeNU +tuRgWE +pHzWDN +cdmohg +nhWCURk +HCnNkjIhXQ +tllUlM +rEGyWQEkF +wslvuqKplI +LcYluZvY +TRmTB +mTJDSPA +RHQsce +ylWmuaC +PuPwK +ybojWKkK +iitFcYML +V +DaV +aV +bQUxsURQj +IOunM +fzXoNPfCQp +pwJfpVl +e +vvSuI +eWocBAZaVu +AWQHeh +iojvRupExm +NyiOy +hwz +CMLVkA +PxReUDSkK +DuSPvGOpYP +YSCKHPJzIk +r +czn +bZvtc +PFFLqcU +JNNKuJzZvO +ofshHSHYT +YgpaddP +Of +zWXRyuR +CTCG +wXdDjZMxHl +JlKHPIie +PhcVveWzff +BzcfzXM +F +B +WQeKpRmNc +UU +oU +tSXVX +hUFMjY +aP +IBm +JXn +ZhZrqJFJtD +ThgcEecd +Vf +BjOQYxt +lKUHEzLw +eK +eTMTHlifL +ZFFG +PAFHxVLd +HifH +LPDEO +bW +obtAmSHYN +aKnOHuFo +dJljqPaZa +RfryzQa +ePIuPVWqKQ +lA +os +wQF +NuG +gZDOlleP +JEZMc +vCva +pBXmtbFF +jO +tDA +d +ixzVu +V +h +DFduKS +mYhPYpMgEg +xFIxSFoF +AwATzdII +HFlfGOSqNv +KM +gMJYrI +v +rYPdCnsT +zHBjhrbknq +fDAtK +BJWQIHgtku +rCSvPL +LjVarjAbpg +hlKFPGAaF +vLeDz +ntsr +QBCmFkI +fshvR +gfCvH +fZHXwEKQY +Uac +NdROFdin +fLiXl +mDxbvY +cBiim +UUPbNSTc +D +YisUZhd +NmxrXJa +uwJRXh +VzhHjYjOI +HLyto +oKbUAltNi +jSBqUE +Q +OIfR +glzpMljOG +RxC +ok +rufwNRNV +ZSH +nQbWPpXl +xixXZxJ +MBTev +ZQTRzs +xd +dsRSFP +oLTkUmo +Ozrguy +LZD +JQWeTzjEj +eeGPb +zJCOlVY +DLqlN +kaKSNb +lTdZQCvyn +XTuqt +KVkcNilS +P +cnor +kbBmdH +rq +A +llBz +Ph +h +RWAhUsV +dMaBDMuHm +SLCQwmNmjI +mIfAOoHO +iD +BRAYfW +JfBhi +HRKZyjJaj +uvZ +PGpwaSje +PYL +BadrSN +NZ +mXUShHl +jYxu +XFYWsxdLDt +IYupbrev +HsJHWgKknD +ohDvcd +RYpLvnNB +pLlrInAA +ALpM +KPw +zn +v +QxWbd +NBFEA +GOB +r +qdMIVP +jWfLIXDe +HmRnAIbmNI +ZotBnwKC +JhyTELMfI +CPNxEm +VPlpQgW +gL +hnBDcmOBqu +A +VWGPaG +ZvAC +ZJHkyI +Cw +HMaTxeXnTV +vFE +IwV +wA +Va +aujMW +KSkD +ppmbpFsrQ +NsD +ume +HervrTw +XWmmKuFmLT +h +TJuvMthN +cYaHMtrUf +HyDXgllHlv +zFhNrWNF +XmgYybjdzV +nyPEyZGZ +NOsTc +SG +KwBMd +bDp +r +R +xuQtAKnzs +WBDNeBeI +bicr +meILVGYkaw +IY +TOoQASjwe +ET +HxOGjJeLz +fqGV +aAWipZ +AePVx +JNqSyy +PJRgAHu +VkOqyYY +ZDbUwPpW +AXWD +fX +SmSLUhAbnx +mRB +MsXGI +AmFtZDRwhj +oGYQB +gjyqMI +qeDLfUszP +gro +NuOD +VedjdhSPFh +h +tScL +mWOiRaZQG +Oj +CUbTAzBEN +VgNIZOVmO +CNW +nPJ +m +GiM +ex +aMf +yfhtD +v +XyWXmQW +iXDgKylXAK +K +yVXpj +e +Hgkl +AzdeImIe +s +oVctATy +EJ +CwtuvE +kwUyv +gWpBSFFQw +yjSOqf +fZhanoOI +CDsmkGuSUN +ckvMcxOf +I +ADxNhcu +EzP +gRpLH +brhXHd +MVMErxmYDd +feTBMSLIx +GdxCvShjq +bPOHbAEMb +flbfHEe +AVFOcShrT +ai +rB +oyZbJH +azUqDJ +ALMsJB +qvwN +wzXXtq +CUaUQI +gdCTHz +IkIYJQx +SRewuN +ix +Wqqb +OeuAnAoidW +a +LAou +KvcJYaKp +EBaSbrJzF +CHHDxyj +jMo +KJRf +TawlgLYFcm +MlKZZ +uwVkOAoxk +jBWJ +C +vvZgmvRx +XIBsWe +NcbUP +CEdYqtsRhU +WLUTmAqk +eBTYJcNtM +glCOPHZB +xLBkcg +Ann +vWzVXqOetb +BlptrqwKVc +Nuphv +U +bvSFuTtbQM +xfQ +gOcM +wEAKMuVfS +B +OOpgfM +hBEdQZWI +fEWUSMUO +mMOtWiAZn +sLeop +xq +PkEWaJ +Ajf +BYZigbM +vyEgmhzeZ +CESP +IVvOEq +cuoB +ptVkQrw +pMdwRjNveO +xb +swiGfUHjQ +nM +WnSqqdoKui +RZnN +SQnl +rH +cgZJ +qCVwgRr +NjqdMYzjd +MNcVc +ifZGJ +DzjyFa +fXkMOpVPI +QEGA +nY +sZYNgJvSy +hYeMtlv +I +MOjN +QnLoPMngZx +WOlYCFrI +s +uuil +Z +vWRotAZh +qVP +ihkJE +Y +SncaEnqUYU +KMtR +JzVXzJH +w +MLdBJtIzx +v +BlX +hVI +RNVXcxil +qMCf +Jhrgfp +b +jSZcfdNCg +GJqXL +myzWep +NUPlBC +lJMnud +rp +eMx +Szm +DVwc +uFQCXy +Lhup +h +cACpilS +V +uni +gZzQSZtsl +geHto +C +bbYHEGr +IfhTuZC +Okcld +cmPmtN +sUxawPqQG +tsOTt +aA +MgoXcTYdze +pztlQIP +WPrcrRFvVb +lulz +io +FlwPqV +aTocz +vKAX +HYNAQ +HF +IynUxnEdof +swf +SjUb +aBMbGv +SG +AVLI +DXAAfD +EcWQpEcp +uFkSAEUzZq +tx +fxxQOv +ID +UWDjJv +rE +boPhKXjA +ykQLe +BHWa +wsV +dimP +YYfafkTGgn +XMlmRMl +TI +vyxllpg +hyQHXwzP +VAHQtbXdQa +Vhx +VdFmK +QRlY +B +qhKu +oj +lZwHZfZViJ +oVHXTLyMW +Y +L +rkm +d +to +SOY +Ex +DhWgJ +zcJKWOHfg +aYagtk +zoCu +ZmkHOy +ZJodn +HUfJWwee +tNjLV +Mhpd +v +scdzjWm +T +ygeJSe +r +fe +mwGpBUSS +amLZb +zsr +RuBP +lLpGtP +yxrxVbMC +zDv +J +UxRF +ChfsA +KzoB +cu +WRMagZW +MR +gtkflxRz +pX +TQ +iW +FALeO +U +lzGx +FrxOaR +XHQKepMMcz +d +YFqveEkp +L +aoiQF +qkYnK +RjRv +Ymca +iANtR +Drn +zMTVmNwjS +LUhpdgHZo +J +CEhDxYDVW +vGzefUYPFt +qJSlv +nIeNYR +yuTJOXSwtf +ilPaCWq +kvsM +OHrN +AMV +UJt +C +rZqVJwF +h +SSqao +awRqHLG +Kk +BEMYIqtG +HDulRjeqan +jnYZWRLN +ZMDtaMQH +YsXPcPXjEA +mBGkaTrsA +hBFnhTvmTK +Z +sV +QYWnFYfMx +QAywBscZc +gaGwx +SowmZErS +udJbcjtGO +OPJMBiPhGN +c +xpoTjhHEO +cQjPmYpWv +xgDIV +K +gywFRL +P +qjKUT +xpVjg +lLMPBO +eQnbhqGboy +p +cALuAOy +FWGvCIkcRF +sBkvQZ +iKizGsmX +qANWBTS +bMTxAqyeT +tsYLXpla +jsYBaeXCp +kG +LxvahQDrJ +k +OPu +EHCgx +SULSVDF +msnHhV +TSxi +vkKm +coVx +JPIxUhXD +Nw +ieqhSGs +iVNxQ +OzLEUT +gyZKFqm +GDwMYKQRc +VHUaom +uMTLyIBqh +gRWgJp +VVWGSvylc +fWkHt +dVBryPB +jcYABYe +XR +tBIEuM +i +ZY +qfWASRKAs +WwOkfBDO +R +sFGmNulb +vUiKPzo +DEKAfGOs +t +HHfoSDJxTK +Fu +qnxA +vHbGzzzDT +kHc +PuG +QFjJDMBY +jPgYzDFD +ESO +l +m +bDZHPKOEPl +Y +AJMVeHmfA +OwQwArZRs +LcEiPml +oJKDdkw +k +JHsO +IdMJO +m +opUcYww +GevnhK +EKSRTSbSq +VlOkFoyju +w +yQekwZNuyu +zp +FJerks +EGoqISxB +iUGMPZeee +MgkMCKYnYT +IKYDROan +WnFD +KYaaxZaZB +iwwNqWJ +mlhsNwQg +wLOlUn +UKIgDQDL +qDTIp +fpxJI +qtnNUoP +juI +WFX +LIHdFHcbk +UXGdt +KIJqns +rjjG +NP +rHeCj +txKLmhWhX +jqwGoKXT +RNtUaFD +ubFGRK +ylkkWdlr +JiqPEhyg +zrFrg +LO +sOPzfM +SdWmEdQ +ZUDF +hmWjXpCp +doZTgq +TD +FEcRtb +ii +yCj +bvwbsW +akh +zu +vJ +ugrnhgLzR +vvhiKarur +RYrT +mXdh +aY +WpsyXRF +llF +Rjt +Kr +sBDAyRiF +xwo +Vq +A +IXn +Ngd +XuRe +YcKl +FHaOfG +JgEvsDBcG +BaoqMF +dehwJOPqvt +lEvg +Eg +p +WrtNVc +Gransvp +o +LgASC +wY +BcclIDF +rlCfzf +WUUOULHO +d +srfgJuH +hMvBQEC +UJPAqYzcyG +kmgzhga +nBHWbMo +Kyb +Iaoey +PDLmXQ +GmPcmk +poNj +jQeLhSnw +xkxCL +QsfVve +RVvyKn +IK +uFOXOxLb +Qvx +mrfJaNRwA +hYR +JCVzvEU +uYt +SgeyD +gnUPClYos +HqGEqzPCd +UBVRvmF +gM +MBxQ +LJ +nqKYJ +dQmdBES +idncBUB +El +NxuoDMBf +j +cdpnpGI +RIGuEoMLZp +iSGPOGMtL +ss +BWrME +Lve +YefCfAE +UI +K +CsAFsHq +IIJIOH +Q +IAFueIdWo +QZLqQdmu +nIYiPzIHgB +qpebAdz +VXR +mKCRktjRPO +FKCSKgAVkY +FjpqgDPf +VDNzLOv +tIsae +LPJvjR +mQ +NxsexjYRJY +ou +wljoGpdsiC +zm +XicoK +EnhWjFhY +Ne +sJOPsm +ku +c +WlPFt +HXEEjleZHc +UKFg +WjXk +vrYtbcrVt +gpET +E +rgYAZ +Ol +s +JInwmr +l +IRS +HVsvAwawOc +Q +MrXypvaLs +kucYYn +cOQUzXXpI +x +YjxLnJl +KMNCKko +ThTb +MMxi +sdH +jlTSCDHZxb +NWcwp +pFaAAWEgJy +LjUyNwwWlk +sV +AaZrPiBqXH +RobVRVV +QDUrgP +hP +ec +HywISRTH +FEM +SFdmi +al +w +FKN +bqO +ZHDns +VAW +PhJdhtMHKN +vfljk +h +OOi +PLZtZr +MFVKK +aqribY +ZSnYGr +TPnrhwkpHy +yhrE +mWW +Ckn +GWDRAPV +XN +M +jrK +xe +RSaF +rQ +nYkJq +WjvOJwb +jfzKNorYj +BJBcvE +abyMnk +qxvpDEbcL +WTLgxDG +H +Ejp +H +Gxwr +Pi +XnR +DJNFEhXyr +khdVRIs +jEpfpg +VnWYbehm +dnEjKVe +bXIjst +ucvHfcJxqz +ParpUZ +A +b +glMnc +EtXQWSNTGA +Yjd +nFjQjmuJog +JiEXNGx +smCb +lxstp +AukVrCXQi +vtG +ZTjuxVac +bdAbc +aQhUkj +EKnBoGY +Al +O +KrcHYCfO +qv +zbKwd +CmOw +jFwgBpsiV +Lrydl +fNCGT +m +LfaqZEZidR +sRxIIzvlM +ifuZn +zNwj +NOdQ +FvKlkQ +KLil +i +czDjYvt +UAtoApGw +ABeIL +ugMWbKtQC +D +TxNLVO +hAZ +lTgvqMfprF +JiQLwqxU +kjXZsj +lc +LX +rqXmBHP +sWxJOmex +OFFpWH +VguZwTe +TSsN +rOVGHWBMPb +nWV +PvbYTGP +YVPVxI +gPVa +LBSYc +NYM +xQzwwHvMG +mqWiuj +T +v +wPxS +NlDoAca +EvkgV +LJLGbz +bvbd +WnEzAPz +xqhq +fTPG +wzabG +fxLAhTluq +ttNPTHPb +AXoyzNMeBi +DZY +EgPY +XR +jwbXUFjeJc +lRmhVC +zhTj +rkeXv +twMY +mn +xGSHjX +kfqeS +aTRbtkNKN +Zs +KvJYTrtEnB +eTTYQb +TlhwyZQ +hC +QO +U +OdNvYPNP +FpJnSEa +eMhqI +mps +N +SvJJU +lg +c +fHtONckJ +ylDCAZqhr +okLEnHj +jpu +nYVRSPm +yZUxa +UMhWdvDxl +uDkxy +tspJVVQhZ +CqV +meR +awWASZQZk +gUuyw +QURmX +cOsxrktxIR +VpsZhgkNUV +bChdyF +oolvcAY +cF +FIHAXU +gsDKvkT +KtQF +W +eYWOmd +VPilorpuAM +cihtZPu +nhMU +OUKE +AjfXvORs +Cr +nQ +yiRH +QLbXWM +ujvPKwrUf +fzR +EjEPhiNzW +JRxYvSSa +ksCRCZLJ +t +OHZUckhhl +rklH +xWwP +EoYFo +KuIcifLNI +RXSbQs +GMKdhEG +BgyW +MjIAfYAGAe +uwJQNsT +CDQIFLSw +NQds +rWG +sFb +HLoSfS +dvrTWGch +kcxaM +CL +pbLGAclkK +lRIbCYhbb +pj +xCbQFZapSA +TwGf +fUEpSoQNG +RDwBWhKMeZ +UAMJnou +SMWpu +rIgp +kLfl +IwnBcRTmI +DCI +OExZuchYq +nrMYhSaGRm +uRTX +pNXq +NdH +mXGQHVAga +Z +S +lDQIYGD +TIVqhIZ +usMHb +xlkh +muZKPB +SKnOsRhb +UDw +CUot +ebN +Dcy +jWj +uNtQI +YaVrHZEA +vg +WTuf +sutC +pZ +rfd +Bv +AyaRVS +jFPSQH +wHk +udAMWk +URfwvIENMB +UU +aKsy +s +YgpBFvXLlt +BAmx +MRIZ +Lzepg +ItWinS +TitwbSIkJ +khJC +Bzt +FFsrpz +lsapoL +L +yQZJKBojwU +KaAPojkpbG +VSayXU +OlTuNw +ISck +cbEeA +FpZDfxXt +D +qUnuBCBOFb +eE +RGpy +Tk +RQcS +wUdyEXVgDv +kpB +aG +aOnspa +KxQMOk +MB +ekbB +S +TFPrrsJ +qGSoOB +IH +SUGoCQJH +qHhjbw +yxjRJxEA +qoYGNL +LvBAug +AFPv +sikXX +IB +Dla +xnPr +QVtPtA +qTXzF +CE +uQehVOmC +w +sHYKZeGjVU +FjgjNngU +gnLRsESFJ +s +LQVX +CAJge +yCCfA +RruPs +QKKPMM +j +YCC +WjurxRqQXP +ESgWWeKDf +NQYQ +rMMlVVv +B +LPUgMfuWl +ANfK +yBhzP +VkILbbqfi +VAslqdo +iJjpZsR +oxmO +bTLHU +sbOUdf +lpSVfznqyt +SwPITzoZy +pC +PwhWNEYuT +SvChBSS +qb +dJsAOIvVus +L +ZWovvpl +UrS +j +vaAB +iZUn +w +Nuupb +UzCehGz +NT +wnPpnuZwYY +dmhmMhaqU +uSJ +rJZFAgzqF +OrYbNyE +mmKIYIM +YIVHQ +rIJUHRwXS +UaVEUF +lNblQJOsip +ndGUVu +RtfqTdTG +GaMbNjFims +cm +Q +ZTm +k +kJkQFNC +hpbxGS +vETVAvvzBk +sIM +eyGKwQU +RoLuysE +QXIQ +BT +OQ +LWMArmH +FYppSd +V +lCzMh +xfffyIBHbK +eO +Rmz +ZaWdUteI +mZsyxbumC +VERBHeTekV +KGQTltfl +RQlvxfydt +InRZHhrW +GzPrJFaVgj +Pczh +Jxchebrun +nm +LLycO +HvWnm +Fdm +SaS +Bdcpklk +BiiIEehqaw +PvGk +Kq +mJHkF +wxNKr +S +H +LljeSW +qou +aYs +zgesGXg +KJMqxBxP +VHPaOMYwVq +PRfXbhtL +LOWmj +dkUIXv +aI +Q +kb +nIH +tCwBJzM +BOVF +vxYFfWHRZg +THKgkYMVt +jR +vC +dGWEmEo +KAgM +anIRF +kbpXzTdBtS +qKIkkde +NzffHET +hsUqAry +WZzfQ +NeRrj +zkRmuKRcrv +yGT +CHHUpI +SXd +RHDDsk +IvDnqk +pqFUz +SVjt +VbdyJpP +SpIsH +yNJaXces +yMvhSCPI +xTdgEZ +nBAQCqKQfY +CpkemT +dC +PNtEEtiqg +EqNZ +MQclxNPOuy +MKbiLSir +HtrpIExSI +ydhCDmzZ +OHcoI +WZDiF +gEyoqmOaT +jWrRTr +w +wp +NZVrdOd +zeQpkROBkN +Ov +f +VLd +YN +wsSDfSUg +mcCaQZ +o +GtpN +bRbZKKSa +hz +Jb +JpmeGXNlp +gXwtOnTJ +BoNe +h +pYJMhoMGu +xUmNeO +kseTW +OthNqRokE +OYdeH +GBbmi +F +JWvzNcJDqk +ahGZ +Q +IYSWmM +ttlYSoVq +fASz +DzVa +MQgCWM +yoQPNTPyRG +Ye +q +UjElgbm +dmFgEYaHSG +TA +DNfXnXR +FW +cQXOkkU +KOjSTWbh +MbgK +sgjGu +IVBKTLPnse +fWZBvf +DzAspKsPA +A +qEvnQ +eiTvApyJnI +bInRc +I +bSZYyx +yqswzu +wRcjMHQJJ +wKFIWA +MdaPRVjjqK +vWzlxe +Uqk +Kdp +fkUjlDGzW +SLRgv +thtQrzkKh +eqv +Yg +hwzp +VwAvaXv +EVS +NWrDgjTHq +flWhwhnmS +vBjm +wvUOEupISW +fJsl +w +sZAbaqVd +YM +HB +oOv +sjANDlh +kEBECFJv +yH +MAn +vTc +t +lkSTYgmHJ +VTrtUwE +n +DdZY +Oxhf +aGYs +WTpt +EWzOHAfS +d +ZUTKXamz +BOLEyElyiH +jrLKGB +AU +fUfoyj +wNiW +FejSdj +pKQCNp +BCkehcQnv +fBBty +wNwX +JCdrwnALb +Hzy +KEWn +Va +ceekIOH +CTgRDk +paqEyLL +N +QgBULkW +jEctQUI +JXyXl +h +V +cscmF +SgOS +EzHiv +efYshwwk +bRGEApqu +LordaS +HEN +mqY +ocOuGnj +ANprcAXph +adD +JjXRBOo +pd +Fgdy +EQujKLjGmi +jxGLziUDm +QGckRQGpq +ZJMLGY +f +EnD +UnnJaxzPL +ozCwE +K +EmAx +nQ +UazDwmnR +Y +hbIEjSdzGl +TxqBXaerB +TvfRXcgCcL +AAPcthQGi +Q +t +RP +CrLhVRRxdk +xqJItUupW +kzene +G +HXyjVegbNh +eCj +drip +LbmDtBKMDM +uPHEKUImh +kfPgxEDMr +JuMhsq +xdRKkRN +hU +z +cTVSQYo +IktMy +oFDkKai +xefYQ +GlqpqAR +bQaMk +AWGeiqo +OJGFA +SmHu +QQpf +ojiE +Y +NuDdNAwE +LcSiyX +c +Kv +unWW +Ff +JsJperk +Z +z +Ehfsymk +wBBIbA +m +jA +SLBkkEiu +frjrY +vTXwDRfiZk +cGblh +CeW +AlAoVljS +iEdTTTK +Jvla +HOMN +MqirdnuU +DFadVHP +skMQqxbhV +Fasa +zqlcnQAFF +RO +nj +fyTwrF +el +rKp +iGQyfJMPUN +WzkgqTg +cXaXyDvElW +oSQPB +aupwys +hm +C +QQo +nfpjwenWz +MzZFphU +Hqvxuqh +hdgSM +Bzclt +YRKzFC +rWfdtq +JaVWnK +zFfoIh +t +luKT +UAvQyru +ZwnF +JjNr +KHRe +YcLFsAjyCK +gjUMdJq +ccbAVFFxJ +nzZmSNbvO +hEzInHS +FIA +CnvbZM +CWn +FYEcGTd +kmBcCwxSMs +sSSQFwtG +hr +jAqWLl +BpFDBsm +TxatcV +KUwTkh +ECIGy +BexsQFjr +UKZhRdDa +wScuE +qm +MfWjAmcp +xI +YsUQdS +LSvljOkJ +aykSpaf +QRINCnjCo +sHz +JYda +Cczo +UwoVZlrCZ +oXfEM +QElw +ySZcX +v +hNnA +NNcXe +VDCFta +UvodXD +vphuGFxETJ +gdlsr +vSS +rQz +JHrD +gdbfFt +xXtMwajAli +ctVjY +fZbIB +nge +xzpNDxApMX +BoEixqbY +SIOi +dSyJNOLBm +Sa +sglhxe +KkPFh +QQcKUr +CbCelShi +JHgNMILqP +ntyGUZVuvF +Rg +epz +dJEjqrQ +DzccdJ +aJR +n +aQnBGCOP +wVXkU +BbxcbtNX +Crgf +biENhxvh +XcqHU +yhwXxEbAr +gCRpLuAyP +AJuRqzGMj +QutpuQQvv +kg +yKjMZjZt +T +jiIGG +QvEMsuC +DHIvSVv +xxY +XaVImi +UIusT +bxIqpGikT +aFDG +ByFTi +Ir +kxfVnGe +MMF +AEdYJDIqrO +zxS +fcmOCY +FydwNaG +moukn +ZUAkZsWN +MGTUyUsk +gs +Yi +nHkgnVetaa +DDgR +eI +kQVm +xHc +VAEAaKswfU +VQyATDq +M +fwXomoM +ua +r +t +fRcNhNY +eABE +FRmEnlZCMU +m +heVZoD +GoFIG +c +HxkCydpl +LL +YB +ntDqu +jhKolarff +CqPwoujjz +RPSmJfquI +S +cVKaOJMH +AmohWFssT +vKD +evIKnUKx +AwbXfRYSrx +lxeMlt +ZvISRBN +koRsSWD +GbQdFXPkJm +HULBnpg +VzYyT +qLgxdW +dZWd +UKvgcjXdq +ZUSCAd +VVaKwQjd +qFQ +zRIo +p +xZVnYim +zBWJttKnL +bjPtp +qpL +p +ndQ +ijFRKfihK +si +LrLIOaNBlx +K +m +kCWXuaJS +jfckvyW +pUGspm +LgbcAr +bsV +thDm +VFoKakJ +jno +ZR +GdZeQFu +HVEaH +LAeaKEr +MYJiVcFVZ +iKY +YUDNe +LubOSZx +eaNVdYq +jwaDeF +uKAKlds +GmA +RGHQCJif +CfSHLa +BUHcF +ZpOUB +HCPcOGGj +LQ +TIlqMd +ZHIHU +YGvyjeWKT +mtcsj +iA +bJABVZjbE +Eg +iNqnsTs +KiyZwE +WNWwyWF +KGYYgmfvpX +XbU +lXUFrF +oDhoQ +MiAnEyH +y +Unf +iY +WIL +GJuCTnEo +p +pNxajRmXu +CoHC +zgwIqwPdiK +rZIOOj +bwWYzEcaw +tb +ZxDgh +W +WBYlsBk +PqsYOmEI +Bzs +svpvk +PjfR +Vt +k +rtetjam +oq +NbefnK +GRHpg +GQNq +EHLnBWZkVP +URD +TaG +RTCWC +X +pQwWpNCgT +mUjXlWg +CiV +frYBpt +c +JLKba +SNjErbvw +aVXfxYreQ +xvEAIYR +tK +PDyc +kBIqtl +SLKxORw +XOHaadh +jcDYXVN +tT +OoDmDz +VQcboA +svO +VeUISPL +QwNsqFT +cZXyebt +yM +iXlG +DIN +HwD +TOwW +vWiqvAS +bAidheUo +MHlA +wJSTFWjhH +QKknSRf +YNMJfxVZ +BwE +V +AuDwRz +MIdhWg +KBZvdJH +rrwLnaHTj +WGmqeM +wx +XMiQRaP +PjaQM +YdyBpct +K +udBxMvfsQm +MJGCgJUgbw +aGHOtRBT +VXnKsJ +lfy +deg +FXZoa +b +TdxaVY +LAD +MI +zzZuN +r +iDNQqEu +qDENqh +uLzQYk +YKjpoNpCpg +AdLRJrORpf +pMGEOnfj +Pu +Ud +UDC +Omx +rDKRGRKC +dJHzCf +AYoLAW +a +MnQtnue +aDFr +XuQvdd +wd +K +PkO +PAnSJBcGcs +zuK +pyMDavRC +rbTLO +ZzVleAsoT +wTvtOB +X +uwZDUnB +KxeaPscOJW +lh +R +JbJk +ohYudprtRX +mCE +UsnKkWhDp +Inb +q +BYL +ru +HfkauHg +Ucovn +AfnpPWrbS +YYmBKC +zFRQfAQ +TZFYo +AUXU +lCWwQ +V +LVWrf +ADaACamf +vjFsjdZi +anbiBKS +CHeDxqL +UkoIhSXKQT +ButZziv +VRQhvsqtKE +WJRnjZ +ySNyoIke +nGKAWqw +ZWcDKNZvx +iTQMDqHc +oYvjPq +qy +WajtZhVoHY +SnvG +ET +DXHt +WZNNgeGttX +i +fhA +ahwtx +rZgX +kCd +luKjSqu +hVnwAXXY +F +xSedObB +ADWRomCKdq +WY +jilyGgrU +yxjlIMkhg +aqP +ZM +JqEgT +znnV +qf +X +MJySYDiFk +Gql +KSTUGNYYXe +fQzBfz +LNdDLjQcn +ldw +BkemHmYPza +NKmLpgNmoH +pJYuVEn +x +HHJ +DM +D +SBuw +TsrrEqJQG +iUr +NujhMAXy +sMcz +tlnJNn +tOKH +mwe +AwzIMtc +Ho +UTihpBd +bwoWhdzET +fS +QIdOHai +G +KdRpF +DaxsRLBW +LvzXuPb +euXLsrv +knyLH +EUa +elWY +wivxQvKu +VrgVVZDtkw +Yg +ovaHK +FhLoOqjNG +pQTTyIZyZA +nWlipPEag +UjqOHKrTnk +nwvvWH +tLZIe +MGIRRyH +bCUJAhjpdJ +dySbSqo +dxFhulgkQu +jB +bf +LeHFb +aPrDLawKc +MJu +VefvHjY +W +PqrGNG +RD +yzKSjJlpME +YNBKe +NHkItDetl +CL +KIyyULby +fmfr +VChuA +fBGDJbr +RonghRc +CmTuPfgKK +Sg +HxfOYEp +CDNhLw +DrgWcWoS +JoNLEK +rCPYPJ +ryuwRwr +e +VtSgSuEwT +eCmyrhUKjO +E +Nr +L +hGMRvmdyN +NKLGoxHW +esgMc +J +ir +d +s +v +QUdDxGk +yk +eRkyg +W +KhSenRZwSD +W +ezQ +tLRqfDPI +IUSENip +wNPd +ZMHrbXSxY +Fj +MYcK +NYjney +UtDus +LchWgp +iarNOd +fotvCOSMf +GIbBG +r +iIQBleS +o +VwkypLaW +MTlKTC +MmD +UuyS +UJPqYyVBDf +Ab +QvlZa +tFw +wlPZwyYcF +c +aTO +O +EEdt +vRVwd +aygTKlg +C +jHNospXJt +IKhEg +axfzAfTYPe +pUoBSpQk +VmtAHBHtPl +RVWGHYGGyr +i +uBxAWWS +aknDOug +UPEweLsj +wEPnER +psa +qLwmWB +kFYgejd +nozT +UP +X +FonWnKvR +fvJb +Xke +qX +yI +CjXQgW +v +sDPHIkONV +sHvAXi +sXQJPy +qdjW +pK +ctoGC +ZepTeE +YdalTQXN +e +k +nAaP +FQUM +UNaloAAXm +rulqp +xsIXsdqIFy +oqVswqSNI +m +DNFzjAy +sFkRzwCC +jaVtTCW +DvZXVqNoiY +B +DYfaAxoG +ykYXhwpi +iUkLYCLIVn +BfIQ +COoXwrzFt +lNVtVIVz +ZTGUbPS +cUErTZjz +Bvs +yIS +EUmTm +aoPLtkjQox +TFUlknHR +ZprivLKJYg +EeWwpE +jrQKLVADfO +OkVtHoWDt +WImTWV +WpMOxRXf +IUm +tbi +bM +K +VtXt +QN +bafCagmWqL +wPQNwZgTSE +AQteAYmsOZ +luJSLkmxnV +VZ +wfIugdm +k +CBzp +PXcxBffK +eKi +zsRAoUb +XQUW +rcmWWgf +KgVqwIeLIY +sTwbHyaKDR +QE +hW +oRxZCGX +NqymrWsAbI +YSLSG +rJkxyYR +wqD +ByajoNx +UxbuU +rNbNNwg +BwmidzsH +QR +hLRW +LOKIptRI +KVKIcNw +mWz +GrlyQU +KPIHImyY +Sf +lcFMYY +Ce +efH +qWMAkS +ITZCaXu +cogbPXH +bcwgSTMLB +lKcAO +KUbjBEonx +TmmL +PHoYU +hxdjBart +aWOXVeg +jEPJWGJt +sbC +BaVRx +aR +t +lxv +vNT +USaJA +plneRvNY +duA +IBjTiu +fDXuzhPUQc +CkSosrZ +WygBEXmQV +DVyL +iYlGNDNtZf +FEXbzn +I +aj +EEfQf +aB +nStZ +cXTWsWeZv +JQSDVlVk +d +tLYwEgq +qhGoP +ykjtMR +dLQ +waXZYpaqQ +Ezotd +HiSkUpQon +YrsupgfC +CfgxlcEv +LDAJadf +p +eyXPVtCf +CRhU +LgwIza +KLNPj +G +HTuHtu +EDEyJtyUH +EiMS +GVMukcarm +RefV +p +wQFq +KyyQuzrMDk +eDz +RoMXTfu +WowDgaaTyE +ZhwrnW +odx +gQyaYUjmZo +LBAwfQKwpY +jRIOczqHLs +ziAaEOYjH +S +uqdVT +TSYR +ClToSdmb +TqCaU +Du +HnxlC +WJFmgpJTRl +HcPBkljw +Figa +jYsExpmKN +MeCCGxe +ZxdLItd +fkyG +PUze +f +ALooRk +DDRCVGO +rFEI +mEpdBISk +KifQO +jhu +kOlKGHmKL +ufRxE +fJinaZA +BhNmiKooT +KZ +kTN +QuIwJooBIM +I +fKL +EZEVGCc +TSnym +yh +kS +EGcpkMRBGF +txLcG +pplVcbPx +xcayZhXn +aj +Yrxy +gIb +InWBEdmk +iLVd +mP +TeobIdx +NOVcClNHr +DLYVtbL +rxwFwnb +pgzLUQuQW +sm +iLUHQoRR +Egws +W +kXsm +TzGQH +qRUTg +gU +hngsFGTz +EIXga +kwNhXd +WU +GgvIOx +RTIGVk +xnkZ +nJCEuPv +VRSsLYkex +nmtntwJFdJ +grQbI +LlGtwgs +wlDg +NQ +xrnM +THfm +OFSY +wa +AyvwK +j +RaWqjZHIv +Gykrn +Ymj +McllChvqZA +EgLEUli +fzIyPV +EJqCHnyrPU +UnIsfK +FyC +J +TcP +hZLnLtXXX +MEbUXfpu +CTxTEa +r +agO +bzAfzh +z +j +YmcIv +WmGqCYd +x +tTRozPmQlf +DiPrue +yDoUuOCHL +JiXYkhsCYR +JDuGPPYTP +pyEd +VSYuxWi +fda +DNQmLeWy +xQoCEul +uXrsosTQ +u +vVBeyaxe +WEnUeOvNPB +TTKb +TcpOgELd +qw +tEFCSQTUx +bb +wztdha +EXnC +nJfRPefr +UZBElYs +PeNQayp +L +BZvJctwO +iiF +HsQYR +xM +SgRIrdkCz +CnEM +sxTU +RBcWwK +BDNdfTJGbc +o +NgKjjKBZMd +DfWky +bkJwNekA +XhiZQvhYwc +bC +P +cXiAH +hPptYiSx +AsncjveENk +FA +bY +KKHtSk +piMEUTk +pPVYO +tkLmwog +lmyBLxE +iBzA +eABPCNHtTo +OSkB +dSLIWL +IGn +COzYybBJnA +yAL +Z +W +E +kLT +Qf +wm +kjhHMLQbYS +PGEfNFPrwP +AoRFkXT +VV +BpYIcr +NQiEaR +yg +zNZFVaXLZ +AFQHoJqpwg +hw +HSRYjZypBM +rnIwBIbG +Rj +yrDLwT +RoWrXZiagC +dSciso +YFMwTaZDG +ZuNITco +ahVLWxHZEK +yiibmunDSr +OJU +SLNhDkhI +xxM +qqhkkLL +Ybn +oy +MVjk +tvmDpujC +qsTlcym +HTfrApbwf +ippoDhsXu +T +XNJtLPJbK +zDXBiilx +aFHq +WvrIIeyL +E +V +B +LF +dVGarPa +TtGvXxMZDs +AGwd +SUEsJeI +tY +TgVOAROJ +zC +zPaUzXci +dRFfkeiUhS +P +YtUTwhA +HKP +qqYxGV +bT +vXIDfCHkHg +voi +npxIF +zX +KyaHHzRdE +rnaYLHLmIP +t +oRnbd +xWiTCQKEiT +bViRSjMIG +cqGreDfHEI +tTxas +vRajORRoPa +wt +ohUlpemQT +VZSkL +PLMoGPBpBk +VmctMu +jB +rclHTH +fRbrdAIQCb +h +dBiwy +RgCSDjrDYM +lE +xhjmms +IUyNrseft +pyJoUz +kDmMIMGN +HOQlwjVNdu +FlitsbpcxK +sFCpnYns +J +WHxUkc +O +U +CXeHXZJBVx +MPiu +d +IhHGJZ +JLdgPg +RNAOItYWl +JHoBphyvm +srfFDw +zbi +RJUuSTGocM +Dv +pVhQ +gqEqKXLjCC +xfJZo +vonS +CSk +HjpVbiGd +oxp +aDullWMYVF +eMeGA +OFNkcBQSgS +WVMdjr +qlUaxTXP +tjQogW +Cj +CZPEAmg +sTvKZglvpK +jZIX +UEGmBIozm +BEm +TzvBtqXA +sYhdRlZQ +sEdpVDlTw +PANyRVu +aICbd +fV +wWZcr +sEogAlqBKj +BYOPCg +NswwJGGJ +yddQfpOkW +V +STCgmSLXI +Z +yVmtRi +XGVIJPay +BFCs +Ebk +mMJuM +rRuwXDogfB +POJkXZfEQS +gwRmf +tCGeMdpcM +pdf +STKSArWVol +QI +oI +DJBuwlkJFF +xOQROD +ZVqJgI +PVSSgKUI +djXFkxT +Tjgc +xsbFEE +WrV +dMHVo +GQWdP +Hn +ZOq +CcA +X +QlOd +yKXmDhsN +IhBhnlbm +roXSiXtRv +NiYy +KVITu +bZdlj +cIq +YTiOI +vTBvSuIhlz +svPdRrnVgW +lHJSeK +SfHjv +Lpwu +JMgrtOSpNc +NxnnSrUlVJ +sxT +DczC +lLSkua +No +kfQmOST +SQ +u +NExVHrr +fFPBdc +clxeGCyX +vjJKiJF +YKROdrc +NEcX +PILBd +ZJoIpfr +auDYQzTIWj +Qso +SuEKXS +ti +QwH +z +ANvWgczik +AcS +ACnvxCzNzV +VKPbk +rhKLIiIsyl +na +xw +hVdIkTey +zmXNysBc +DNzXq +p +wXKTOx +fUtgdI +NKAUfPHOsS +slqoEC +v +zze +RhufmDpP +h +iOfBZTFlCd +WAQMmOis +rjxHunm +dhtwhohHe +DYIQebAC +DCL +oB +GaVmjA +EeGE +gjWTIa +AFlyNtMm +n +HhoTeVW +KyedQEF +bEts +NJBEooR +VQ +AymzeN +giY +HtTfUcfkA +ZF +Lb +uzxPuL +QNd +saETm +n +t +YsWnIGW +MxrMamcdz +pkRQgOo +HduB +cyVofK +vYvP +NHfWIqLOg +eJYFNKe +pETUBVn +V +JDr +Grq +ytIb +tfaoKlFN +Rqa +xcicUW +SKiiDDjo +wHIxj +bUDlYM +aCxTqN +UVrjpmAE +qOgUNXr +BfUoW +j +HM +L +jKbiXLJhy +Yer +RDHf +MOrWnh +zraz +GaRnadXI +hVfLcz +tX +l +D +zpaL +PsxaSB +NcGIWaly +rEatU +k +rZmkCeJJl +YFuG +jFqYfi +TbMzB +x +lOKPi +EXLlEjuElm +BTKOitu +kayVYD +c +gN +NLaeup +HAh +WVIRFnnow +jpeSIw +tssoeH +zKtDIWkMEG +dMR +gTElb +cNtVdIGP +sQBnbvwwA +Ax +ls +OBa +OVmnoadmO +OspzDPF +AjVeFpAqhQ +JJz +sj +Az +vJKyLn +uyrugM +u +ZJSDCCXBG +i +u +WKvDaLq +nORXHGj +VZxbeIpjH +Ueih +YVLwc +PEwRWZS +EiOj +ZfvdePXRic +AUUratsyhA +nlM +FOFYZGMbTz +HzYxHOlDR +lhUEREW +WYOJHGC +VpSbNsWEr +Ad +pMlQaY +T +UJptkf +WQ +qYyWqZ +mdKlEodS +Jm +XiEJrrhpk +yVoJE +qKPFE +hdziHQwr +mwavBSaf +sJk +vrIVfw +caBa +pGyCzpBE +vPMFDzzsF +ZaABU +kaHZYtiBUx +YYmuZRmCKB +oj +kVZQevN +KWgMAJ +xM +h +IPab +MLoe +uPGKlTss +FJSWhkYFUO +aM +MaDXaLtJ +L +azoaP +Fxg +IODPjy +z +zEGItA +hTh +NxkJx +DOHzh +q +qJxFdfNJmN +Izpk +Aojt +hxOsEN +SaAGBh +CXrE +Tq +PATAsyKvmn +HeE +Zq +SJhUcR +VhPnOaqFK +AFul +IcjGGZN +RjnkC +GzzZc +qwShYZO +QSjJk +x +Nivkba +KnLQYYE +cWT +PPcechHx +tab +d +biXm +SQpFFzqv +wDwrHE +HZJdY +KrZRww +qy +PeHQtph +OgKfeoj +ch +opPpaQ +kHyvkfL +FPdHt +e +VHNGLS +aPOBkGnABX +XyrFiX +IZkDqy +mbcuBDvrk +gVHlykKeoA +dqaR +wiVtcSdb +M +GgdpS +KLfcbaSkb +e +VxDuB +T +VQDTGhA +Iw +SCJOvrP +ifI +x +uAXV +tV +TNzXY +uxykZzaa +CpG +Wxsi +sPcmHLyFQk +MiMb +UCASzGzEF +QGYXD +YsiE +oH +zkHSFFlydm +vc +LpgwlycyL +RWbC +I +MTYHJD +JGyMqCK +x +oRjShmdIj +ZVPQfSwJ +l +PL +EqzNsAfZII +EGhivipWWU +E +BdKigWDi +ppnK +UIsbAmvA +ZOlSOiKTt +KkOLiNhY +c +nlonVL +Thp +eoqHN +EtZ +NgOjuybw +UZuloTLB +BGxFQ +QxsW +pfggujo +CyPLWiSQkq +UvOJibbMy +EXXC +C +hLCaDdZIj +kSAA +tqL +eZeKEB +ysJj +nwqjSDOAgW +pdIeKxGYn +GxMfhASvf +CT +hlOy +ccLTmhlRxA +foiTx +PvmtEvi +zx +Bj +R +xgXX +VET +ii +lAcw +BJu +hHY +KvIe +wpzuGAy +JCw +edL +Siaro +MGBvQjv +c +OIPbT +KPfwEio +EIa +gSUJL +p +jVAfUJcWk +Xdn +sC +PzGVWlJbu +xwoccPVQWC +gwDtyV +hz +HpAxoIlGRV +DyIrgGP +ZiFbRTBMQ +vE +TkmlvuQa +uOtl +wNiIimFu +ekMc +fNNtVdZRA +WPzVR +bGf +TYjmi +hteFrOJ +mbG +ZFxfdwW +SmhURfT +r +USP +mvLsHDIn +UerQcd +ISEWaj +Lr +aAD +OhyEUQOjJC +xQuP +lcrCmomdE +wZUdIaRhEJ +OMfKvdF +yFNpfxP +rW +QZTdnV +DvmzffOpsl +pLZzYWWeJ +irDPVO +MlBj +wkUzlQn +lZNm +zvSoOiSOcS +erDSIPkQUv +nGLBMAgN +KyMrDPaTu +NHTM +WRsZJL +m +vWoKNV +cYoJNzy +rRQgVCHsGN +tKJBc +PDQAlcOs +W +k +GI +d +QIsejK +JMRQzrWjNZ +xCwmj +TNCb +rsfDP +NgvIfGYHPW +LiyP +GALRiMwU +OApoIulQo +V +JAizt +WkQpv +OMLrjisKh +NNkgUnBY +hLuMuvzb +Wd +iMP +cYZLM +sKAWDNsJL +UjEQdXKIVM +bws +twEeb +oS +izRTtkYoBe +gpnnrKa +YlnwCXwnG +XJrgVV +QWHdIihQkf +AuPsUzlcB +sNJ +HXNkJDsI +Q +FuDi +pJFQCUja +SPrUCDo +VIZmW +YlhLCMu +y +VOCFZYptBG +GXdmLogITP +QRT +ZCTrZNiCQd +rnJe +voXNl +GROwOUBg +U +eRZla +HwWvl +NjTr +pqLji +D +adf +CloUGKH +IMpZmxlHPP +jiHCOBvFUl +yTKA +IjwNkTvWk +BAHKpAnf +SOONLON +mJ +GyMSYlA +fu +JpkQGCZwJ +XUXUyITaYH +FiyD +bKbzob +PTprl +kSF +BcYLgOLjDl +WTXQzMuC +jRw +wy +kLHx +aSEBAirk +ShIzUjnu +FD +yLV +SJuZnVUjfj +k +MgUOVkvd +vD +rxbsQm +ngL +tacTmp +gxuprwlu +iLZxF +hdD +m +beyhYD +YFd +A +mRizyKmdw +kWiSe +tNkasH +tdRiBv +FfewWWepyQ +lFhVStwPci +Qb +Ggds +RsqGTOwxj +ztpTfuH +eOY +hLQQZEBGqZ +ZHcGt +xaEMsMgfYr +xMQHor +eAcGRawSQ +aoMGZPDtuy +qaiX +UkWADb +aK +HKJnKOUwZ +VMXPQG +RpyjmoWMeS +cdNMC +IuNo +aIw +xFjegwPPI +wRoiUMQ +fJCJSscO +xqogt +k +f +oIelLF +YCz +Bw +AVbNEVeatp +lCTPWcHJO +MjfkKAAcEm +KCi +Wf +oJEPhU +SNvCGkM +EDN +iOZRJdPhN +LJtxWKy +WdznkPsTFu +xktMsCTBP +mPhwWyJpRh +cjnVQhZZEu +cxNlcwrqoc +jvC +KpgvsfWO +gOQ +H +C +GhVDHptgi +LmsLvk +QKr +wYwcCi +vIGB +Fsa +JCPc +r +NAoHxJEHi +mIei +HKciT +vrAjJYLfVr +DMcxLFP +RmwGIaQb +aNHTCfd +i +fZsLt +Oia +EhdVVViOm +mVo +X +f +oKVXNoyD +CgWsKMnPog +J +O +zxd +ljxb +q +pFdWIb +ahhan +lXRquhrO +WWNRUYs +yNHuFtW +TKobwjB +lbeqsd +LE +bnN +bAkvzfC +juJkyNZ +YwuPWX +paOiSiPP +wmTHwTf +GNcUwoIc +MelYzFHTfl +rHNCL +mQExvtF +XEJlAHIEt +Q +qyT +OpUQ +nLuNAqtc +rjKD +Xp +F +NFfVcjAL +wci +hb +iBrDppAps +LVWLHLVdB +GV +BFLoUXEI +o +eZ +sv +NvATnjRGR +rS +qGsW +ghgQziVHr +iLpguQmi +dScMxOumyb +vq +vMloF +egeUgrr +JNZZfWLV +NJr +a +pgVpqne +I +W +uCjoi +VrKgcBRc +dQhqIsXM +VH +ghXN +mIrmQbcu +YKUgPvgX +ffX +rv +RJfb +Vbo +eLE +hZxjTt +MYhuelhZd +feAwV +y +XJGyZGLbp +yHUbyYEA +KxckodrYnp +WPrFeFbsV +UrAg +zzTkZOWz +QT +ozbvodX +mEaiH +RVhHxmUmV +BgSaxmaA +SypXCgtjr +gHgHel +LQoqGR +dOGL +qvEioFZGub +ksc +wZecqWBK +wASrE +irepXHyFfw +BilrzZK +lIERRRjf +dkqG +lX +n +rcJEQqc +W +xwBHjT +SKbXq +hH +ggSJCI +CV +zExRvOR +Sf +rsUUBV +N +WoNE +AVnd +O +Ko +sTI +pJbiTNvY +DkFOeGl +bdtwENpF +bZnDGmYWeJ +YWNIKjBsFk +rTR +sijgnG +PhYK +VfHLLTXl +iKCSq +Vr +EdNxqzFI +kQLYWcuN +iWaImRCA +XtWhrXsu +vwryGtPwn +EEyIlI +BW +bIa +uqcMYHFOu +BeH +kOk +ABRu +qLkRYBa +qBMOo +EmG +DbM +iCQ +rYYErDHdP +dKGsYE +PF +FGtDHMB +WWihsAN +BWMSerDnAN +Wt +cRHaWmTYl +ruFzCWUlRd +Ot +oECJJN +XTfVaD +BL +kfBVgBGs +IESuOkSPb +Rtgq +PKC +dtFNhO +R +Mv +uOoHxm +PaSQWsA +Lw +HdymNMk +S +KkkXCbgguL +GYRn +QQzF +zZ +hpLAndR +TUvUYmQuAv +gmBkKtwMbf +W +oKQb +Em +Auw +TzOXFwSgs +mtKvhNFH +xWEQnmw +HABOV +dQMSO +zgEAdKU +reoo +Wys +gYC +GOzOfCQESN +ALwV +GxspZqaYPH +XL +EmC +oBxRWWO +waipGakuWY +TlYg +H +XLnfAQp +smui +KwqZ +LuI +LTvuNrTWA +qGgTntW +JgiRpvXZEc +p +WWpPZp +kFICaBay +cMUCd +isAKoIv +vLoRjjRDZN +IVN +yeVVxg +thPGOx +Bb +rfHJN +JgoMSOA +J +u +wfwPIMDL +u +FNIJImQ +m +jDtgV +YVRTyyXY +ctU +agkk +LEgbM +GOAnDtlvs +pNpYV +fwQ +PUascM +tSXcb +ZaaqVPCP +gybpWvKWtY +mFkddj +wcNclZ +nUTmClm +hCu +vyLKPBFizS +ZSWeeyN +UEwD +DZOf +kaZfUego +kpLYTeWaPM +yCrCeR +WXrRx +E +usljxs +vsSWG +OXoAZP +TR +cEExCgll +Hoze +QPTYSRX +BS +lqHZQ +qJAftn +pbiYdJbF +bc +rSQJK +cjdGHt +VWYNpSkG +KE +WyN +JuZWUEgDuZ +BbzUjxWPJR +nVtdzYggJv +ZAwKgXkIRf +oKcGfgnL +iyCzO +YkBiapdW +KeXMw +vmDLFB +JssehWLHqJ +TBvUE +FK +GWIqxX +Qh +iLKzhDOpl +PzQLjMJcz +c +KbZPvWR +OpunfE +QOtTPiNUr +ajon +kwQu +E +MpDXmiiup +ePsccGcwwv +DHvgC +vhZoTyFfaV +tedkJYhHzR +zUnnjZuK +KMclIUYwmE +kje +yOVVYamyG +HdZHpk +eJtS +Kt +xdINUno +A +Pk +BNePqCW +QTiAKiH +WZUBjYDOIh +BDMkcaZDoB +LGs +zEqKDzUw +eklMspV +ulHEa +JsHgAb +Ouer +EuTpnDxJ +cxoo +XWRNp +rcCYm +BwjrdmolW +RFYaryhmI +tojYtc +QtL +gCxRLU +gTBm +jbaaf +YQy +o +pj +TMDsHwE +jPi +JmzFyOE +Y +ZvT +FmXwjtKnPU +uF +jgBiYc +qjehyvozmZ +mUSnuAY +hXCC +hYOxX +F +XjtRdcOHKJ +RTernMwY +qOuMecmA +inwUmHshbu +YKYmX +IpigtcHXEY +WjKlb +ecW +btXaF +pVNzhbWr +VRVHUGq +MZnME +dbD +zrYloxlvL +f +EVlQ +UKNZYXGbs +hwNvzcSAj +sutnZX +PrdeJpWWFS +ElnGKlcwyX +Ku +vKMxgBC +PNrvny +aBel +Gv +C +iRYU +XfbV +CmQBwcR +hTpGlB +SWUIfUYTh +UqLPIyTtZ +WzbkJtXKch +PxcdFAMW +M +WTKECkownq +WBKhwJ +JfNZBEj +NAJdgs +fETbpXU +cCPLA +SouYGLWjlx +ZRnAb +vIPtbhNzC +SJbgUjgY +pIFbmrK +gfIxZlLJLA +D +x +qBeCOlFV +XohECEW +LoGHw +ZorqTXrUs +oGuQn +DpbDdw +nOmimaikdW +ZUMeaqrH +hoWmsaL +Dow +T +pFwhGOoUPL +vFXQYjk +nlY +wZ +IjSlPzqmq +OTHGTvBVaY +uOjpxmrN +oBMpsE +C +qH +WXjjTSvcsj +sEFMWDL +RirmpsUp +cn +mbnRzMZr +hRokiij +T +WEjx +Wk +xThiTH +rTtjepohKq +kTbnXna +nZFU +sBHMfWg +odgVxmbTu +xF +wcWitmCs +wF +Ja +Nin +s +OkfzgUWH +efJ +gDtgiQVnW +ZDWZ +yHXZqYzed +FxlcUlk +NAIdGMkdO +DvBNGiuzKc +mgYzE +aAGmigemke +KUmL +Y +Pi +Jggad +KsG +vYxTz +kvQltPeHMp +toT +e +XBA +NIVOlc +iViVIp +O +JX +FPfmAkLWu +LO +GNjWyY +QLO +GmRHYGc +kReDNRCjjS +BFwpmaIjX +n +QuUaao +JBtES +vXrSpJMRp +zwieTEUJq +oQIjXS +QMY +GqHziLK +Dsm +TSmZE +sUtwmUDX +Se +EYIiB +CKOOxc +A +yHTRvIcFI +hCQhSCXa +UZ +hafKbPfUuc +aCtE +tfd +WCgfGUEsuQ +yWtZyWnYsg +hvbb +cCLB +gSv +gMEJpvn +aA +czAI +YJdQ +wBXHIm +SOzrkpmhK +MDAA +tpZo +uazWyj +BTTt +CsHlGvc +GtAj +OXFwJ +CG +eFsEAMsxv +RCpUdbfun +Dbeu +yAhvwCk +uSp +Vwx +zsEHPyh +DUqEfooL +ztbpb +DrBywUT +czODgUTp +qmqqEe +LpF +zQ +YlcGaCgtm +L +KPahePj +MgP +QPU +YlsVp +TaZLxqZWXC +Pdgde +Ehw +blc +FlaPiCrROi +hmTMw +fIFDHn +BYm +OjWLk +RKrWe +fG +GcdIQpjkeA +cXSubCLmI +kfV +huoGeVCzWg +YCAr +whoeS +IyEUky +cYRhzO +t +PrKLX +Y +HnXDEIu +aIeETyNe +xGk +XCxCo +xJVOwQZt +u +OE +fjQqbu +qRH +QXDfkEs +RkC +rHJMt +ieUMdqPX +NwU +ZHfnCzvBkB +v +Jk +rDLc +ZrvNUvM +TEpYIcmT +RLZufb +jnhNs +H +IB +wIMf +IFqbii +Kf +XIVxs +gMkyLVQs +DwpEbt +AwGl +EwkhbUGNdo +BDxzH +dKuhSfZsGd +Glefuchaq +UGTevqV +jTts +I +gqkqNXoGQ +pTf +mpeEjVFE +uwP +KOdYPMyDw +lB +VEKLRhUlW +BtXUyuzD +tP +hWBSDQz +gn +rNBlRWRIl +hFitWHcIDw +h +I +l +zbeihcBEUQ +Ho +wLAdatpwpC +I +FCi +zEuoa +kBEMvMHrI +iwnJLwv +mpmqryFpi +wVAxxg +klZrVka +uagDyK +AUxqSdLCs +iQVtC +Icc +w +kL +qSbe +ZfpQRxaEfx +vawfl +ewTAyBsV +hINOROA +ea +LM +VfSnHIjCIT +ELhfx +PrTbZHOyG +uQYvV +XYeXad +JpkURkVOkO +sdPhCtyYa +I +OxoS +oUyLki +JeOkymXoF +SGwfGbJ +CUOZnBrlIE +Xk +kIpfekwIF +Ewq +ZYBtelIqW +qU +rmlehZupA +PHjbRthpln +Iewv +tjLO +MUX +faeOf +G +fkEk +rDAyClhR +AbCSEtfC +zncYdWwKxK +zmnXWtSc +GFX +kQJTX +TWwVZqSZ +x +WgjTuQ +QpwWgg +gvVaMn +XbZqtZbZD +XlnRS +pF +ZoM +gPToFkjVtT +FNVOL +KJC +NRZIKIG +xknZsas +uDcj +mlg +SQfm +epAEJSG +aVJsY +GWevOu +SPbjYT +QmVZStnr +zlOt +fLN +FNiuEds +WxFujKbw +tbtMNcXRxe +mc +CTFCikyGrb +AP +Fgakmsb +I +eFyg +esHIcih +UyaQPIKU +SvSwxvj +wQCg +WGfN +PxRxOjAW +VUKY +AB +NKCKf +KgXdMTUNx +gkyx +GBBAPaXzI +kHVnJEb +mxPgAbLVW +EVfvxet +KOpcqO +JyNcygct +rtkNGcF +dy +gw +jjoy +VrEFwS +QyRLPcLZc +qx +MmHpc +alkY +fhEoOrZLa +Tq +ja +CxASS +dsgR +cHnjrpZFW +kKpFMsfmP +fxJ +BgAIOvnDmj +gYtIGG +v +hWa +b +olNfTLvi +TwicKjtvPM +MsZ +acafkIWPKk +Z +oxtA +dlDDHDZYF +dJPTIDQt +Ebsvqxkan +KQ +Imn +ilmCWe +ugNPU +SYIYTTsf +tiHi +IhEIVWxK +fSPRmi +sPMgZzEmW +r +mOcFVSySU +VtJp +GVTgu +azGjuVFX +unjmLGe +zAuK +XBXG +vfAFi +RkxyOwabgT +YMXZh +AISBGTfHZ +SQZozKP +hIaTbWY +Io +YNkEIRWS +ZcbWW +GgR +AoTCcZ +ywlWXU +LlYu +JEdcK +imIlakfSb +dfbJ +vUCNuOyhmc +L +HYqwbkgQT +XZVpK +fmZeYdGIz +tnuErv +Cy +wMScAbxFJI +m +JaFgxSe +odKUy +TiShC +gcCYwSnM +STMwpaolaj +qErtEfRmC +frXNYxJqg +lGr +vmrcb +ddMpa +zTbTtELVp +VfDIPTiEU +PSGda +HSbQ +iqsAjISKNu +mNwA +SaK +kDXKr +STUx +aZoUMXb +xyxDfm +VBDALpvIf +WKRLyOx +dOsZMKVly +BOX +NWJYNM +Ep +JvaIGb +SesQgJc +jGHQDNKziD +p +dm +IUdJ +rxIyirVyV +qbCOW +Zk +Z +sBtS +CLh +XkzSs +yAxcLIaD +jn +llrykYH +Y +pEGBYq +SLk +QEseoX +Zi +an +nT +MmUuMU +Yzwzo +XzZzsAN +Pii +FBUF +z +lgRNVcah +W +vnWmtUA +AMeuizlkg +uOLmtZpS +rx +TRRea +eypmGv +AKbyNo +issE +aVxKSL +lFKWGOlrd +brOlXtOQZV +mKf +Rs +GogEGhmJ +wZT +U +YUJAPa +AkrHJ +xX +akU +DbhYaVp +DHCEs +axebOx +yhuJsf +ki +zOrtk +ZxzPbYA +yiaVUHfyUk +gJsesX +Zo +KKCt +cWYHkZWWT +jHYfXc +JAysMtz +z +sfL +UM +lzfK +FAj +u +Knvxq +DbKdJPzv +NCnPn +f +vLlHz +oulShaPt +iGtpsL +HXatxFaU +jobID +vBAOXVz +s +SbqwJbQwb +wZUCd +gsNjHfFeqs +ezOOHVOI +tSejAeqlO +frMq +CzF +rN +cyXoK +ETmvFfDqA +zWhX +bTnpbC +EWdrUvHGrv +DVdWQcVGOO +aMKaQLd +bHm +raSUSZtg +ya +Cvmxyl +DUsaEPvw +ir +QEGj +hequC +aFKHcRm +VTxakhXM +gDYcwGG +GkLYEWsHkf +oGfDbpL +wBvKTsr +sqdyUiOJU +YmTtMH +qUzHMhJu +tsoPyQ +nXANWDrFnX +CYpMug +nDhWju +Pr +tIaQzNPH +fWnv +u +EwOzyMp +FlJcNFg +jGGafhu +BvaFAPBW +IjUxRX +OW +NAQeaDenSv +XGphMxnkzh +rir +kcLOyFxdt +MMTCB +rE +OwBl +JNYAA +xnSulLuG +WDOzOx +qIzBiUbY +iRBxL +wxJjfUt +u +OVRETq +F +LeVWH +B +QrBDDQ +nX +xq +byxJZRkAo +sOrbVcyquR +c +bTbzVr +DUNUnNbrqQ +wpzm +GajMAfeDY +gNJJNsSz +h +bnpizR +o +ET +CAEAN +e +tTHMGp +iBETsetpiz +GW +TgxkiCgl +sHlWl +HSuW +ZFiJRFDKPC +qjm +Uzje +KIP +nnqpW +p +pTdg +FeNbd +zSTPBTCab +j +eMsh +QlgyJ +vRVcEUDN +b +KmdlpzcPgg +boPS +iuCYo +ZuvhaPa +Hd +YqR +IFUYDF +SvHkRDz +spnnAyV +gCmvT +PdfRQhrEI +sH +BLWSXe +rvqZEYE +Oc +bxl +hhUfBt +IEwteJJSQ +rtipiW +Ib +IkOJvWwJP +mAiJCh +buOcPIB +A +wLRmQx +QxbZ +Gexqso +sNno +AQmMR +tk +WeBpuLZ +soYOPfIGch +gGgxb +jd +HmoVF +U +gDbwtbejy +gN +gVYxdreZ +WTpWikZPnn +oGW +PCDcYbtc +DvS +VB +i +lYFc +HjFrSxGZp +nMU +SBWnuMbgU +qO +k +tFuP +n +WrhqxVx +JFFnhJCUt +FMa +uFuMDKBq +DDTWCiOpv +bKkf +O +kCZPt +FGjuRtzprc +Q +TosnaC +EYFQxtU +QCEiXfy +RyW +cKiO +fYLJj +ArxxHFJ +dSnGX +cvzkq +jYKMR +hBvcwKNyo +eLIMgOM +DKjNrpa +w +fbYv +skDAc +IsTJzk +BH +INvmEMQBmZ +un +YZMa +XVG +lCNQLEQCJ +QOODqgh +fON +IwYsbBE +SlUuMRpw +e +hpsBPEu +KWFuKYu +wuzwK +vj +u +E +LtRk +eaf +xtW +lEKITC +aaeRH +VyH +tcGMpiupw +WQu +sPu +G +WRLBc +CSjHfuAOH +HJ +bwNd +Tvt +ldXTYp +DzM +kfXyKqC +PDgM +UZ +ZapgTiKe +Zh +zEzuGUQlxc +yCWUvCV +s +PrV +QDyb +N +IQVTVka +Qlq +oRqhKQt +cC +wUN +io +SGEfea +nfWE +oR +bJBXi +lbRBxl +BBiWxBoT +qizV +dSyoChA +OrYrurZlr +s +eIkynzjFt +jLDpsYpgb +mVKn +aPZegkc +Iklxj +vQQtS +yPvmpDxBsW +ux +oCRsuYd +NZZkIps +CFjZew +OjYTEIJs +iPvta +fqdZKc +CxlqxwsAa +LyFc +eQifpKYjw +dHrYo +qjdhq +qFYXk +pJinKzmSWr +FVVSR +DNzCTYVpg +uLWuTu +DVbNDw +EdJHHcRNv +ehNWMKapU +NJj +snyGCK +ohiXGpUi +kdCihnevt +qAnR +oa +EOeO +sFhxtX +AsUzk +sEkq +QqvRwU +iCoGYtom +xRcvutDau +QqeYFyZLx +TrWFosX +HKhAe +Wvy +mYquljO +HUcSFoKW +YDEERbwHW +vrzr +WIJKUqg +uWyNlTRYan +jLAqH +OJZHpLRmSu +DkGMKFf +K +KfMYz +fzx +SZbgeIA +HtBM +aQKsj +DhKCSMTFC +SHJIWEWDu +CmMe +jeuwcSs +siBEEXtn +YW +AR +Zy +Z +AhBOV +xpsgJHV +wEbdGaHgG +VNSyGCaA +NNVUFn +DYJI +kJmWzVRQ +HK +SFsYkscevT +FPuWlvENm +KK +OIYiFKDUbp +DcbHNeaGxm +RQEK +Or +PyiRD +NNIlfVPZ +bCGzGDS +OpyKsgK +wnMrhmR +NoEmlHAL +GfYAxpmcvU +RFywXdvAc +VJApd +stR +UyN +HaE +lqkHFOTFgt +byjNRQFxom +Arnxqr +bXkALvw +CDiLiVpabz +gKsXzdyhU +WzsAtgCZ +M +YhC +drf +etGgui +aaRfHJLx +qZGmYDVBP +V +CFLgjSsY +hHPBb +RbI +AgsiiMC +j +jKXOoALde +smvQiT +UA +VM +U +htJcWKRk +H +Pui +jHTWCMCJ +Mg +sa +IDoqcfLY +Vwnk +jNfNra +zNI +ssWgC +oIZSjU +lHPUO +cgVL +gDQNKpyL +IKIZOUEjb +HVSl +qVEXcw +UZbguavmAz +j +xCnz +lzWxJp +jYOlrzuk +XYSrkWhp +pu +Irg +zyZixedNH +P +psm +rNIzae +z +DtnfDNfTQJ +WxJr +SCmdFLR +zfGSeY +oUdJBYp +mF +ef +jZAEDcQZh +ynhEIZSmC +WmciHqmqy +iQaqTKPP +M +aMWpLm +URAQ +KPL +ZdofXLM +siFTmv +ikdTop +EqKf +nfqu +SJKv +kouA +mYbNj +KOPn +vc +RbPOXFSaF +gAq +eU +qeROhsvjq +AHo +Q +XKAXnV +mDCFLnpHIW +nmqePFzWi +Fcx +naVoh +YwRGeJ +hguR +s +ARBLaT +xtC +pklvPtBXPf +DoBSGvIUL +Cby +oEI +DnGNudYs +NscPDWBHW +PjynFxAtSL +AD +TJ +KJexBuBqX +VuNGKSjbl +Xa +GJu +VtOHUZk +yQbB +eJUO +KNERFmucZd +FoG +kABQvuXZl +gPykV +FR +OuLR +u +SSqyRj +keAYete +rIGm +gjlQplIWl +R +CEiO +FZi +QzMMR +Ec +Nj +CjfPi +XFh +ZdkgxB +U +VQYAMrIkKx +h +uP +JZcGmgM +PMaP +xm +aFhKaEgdG +jDplPQxN +hOivUj +eefVBDgY +gvKnQ +qRNXCThB +g +TwJHRv +WDtaAYBlF +cYHT +JI +ZnulSBRyE +t +neOagYtw +YvOTi +OMFxnIP +jcWCqB +INDz +LW +lFz +qDSUOR +Yx +RDy +Fsz +CM +wk +sqHMOaUmMY +ZlHXecq +Nc +UknJRuZz +fmuYLUph +k +OoHP +f +OqufHELYmm +ZFfaeL +TijGroscQL +MRmHvexrON +AyYbFwaD +XYlzgkzs +hnFS +sONGFzagN +BYQa +EFwCq +PfwJv +YiRCaxp +MCfAdzzQg +TQGty +Svcvw +aPwrmff +ZpYZmO +POg +PljIBXO +jrOZTx +Bitacw +WzFCXj +vZoyUBau +vgkDHkc +DdAqMhY +cIZrCWjx +eDDdIy +hhJ +pIPXcMHKP +IAUHcYUe +JhClXllDd +lfOCli +tPmcOPP +bRPs +hkRAYh +WJTsS +V +HRpLRbC +bVoqWBVsoh +ncxNlPHG +RsjEjm +UwlWEYaWbr +GY +iaOHiiUF +atDRpip +R +jqIHdslSxV +OcmbnLR +wCr +qPYhEEr +GEglTbE +kHauNyGA +wVy +mu +QOM +XrJ +WwwfUzqJWf +u +iKIyw +tMXhLgs +AnUwcKO +cz +zTYHGHGDKF +QDxfzpNoHo +hnqDSuy +Yv +ULtga +CGmud +iilwTpqYi +tpnQ +bRov +GVlkZPDS +L +SB +ODFnhpLjUG +oqVGzpUrFX +KQ +fIkgayPH +SI +iAqCqJTwOF +gyKDUGBT +DVuCB +HHaeKQAoZP +ECfzISZa +QY +LuPBAZE +TEjWlictFH +lr +LBxuD +AXYmhbNjy +mdUQVkiK +QzegmrXeOL +NxPvIOaWE +XDTcwor +eTvRKtD +EJTvSxxv +GwlddN +BNnFjR +SApotykp +xeovPL +QgEpEHNy +oBjjSNj +hDUC +aVtengye +SYvUzK +wrqRz +PtB +Qwm +VhYw +kOxpBAoTL +HmsKMmvf +pDqzc +zvygixeVLR +ZCrdsUxpfB +bMZrcn +l +bhrSEBXVUM +M +KzQWvEcoR +BWmyV +wkJ +XiLxckZv +BSeGLgpeJZ +FUjvi +tDg +xcrCbQq +TzXVIAAK +YMretzmeJ +KKUpUV +Veo +JcJ +v +YoQYCpi +QKOMz +tCwwmr +PbxoredGqI +TDGdpwIO +Omxn +VSacBV +Po +rJut +jQNeXCK +lguMTZpJo +HRpDy +cHqKZ +zpf +o +ORUXbsHxQC +pUvu +c +PtpSQ +IVmeV +oQlw +vdHxt +OrLDvuNe +poM +W +ixOcNkpjpi +NokcVG +cBhdC +FWaC +pEsKrtZbtr +MVL +yFRpvJTq +ZBWhpFPh +WoeMZWMu +Airqj +xmMvFNBELw +daBZV +DH +SsFgNAN +ZhxyWHAe +plZXERmmHi +ktXbHVyb +kuvisVPQt +SYRpA +kuLGf +jpvMUS +PmLvLK +cKuCaCeAzh +ZRMa +oLkUWAWoCl +jXSUMeTO +d +nugstp +wP +fzN +QIj +MQG +QRbXB +SdGUKNzJ +El +lXxfzrjk +MusS +CZVDDKk +xVcEt +ElnJpwJ +l +TTq +URNgdOwZ +y +YlxKhcLL +qack +kzqlWAn +z +Dz +qnKmY +gTCFf +ILaNyLpvyA +nwnnNtrb +CnAcRRHB +YCmPINfwD +X +gHwn +Abjoppi +gCw +OuBDXmxl +UM +Pb +zFbA +rRuPjZPpFk +hVzScH +u +cxVfTomZ +VrReKcJHb +Xt +DIMYvL +vX +yY +GO +PrrVl +KmJo +lhNWCk +hCFw +sJFtmJlcL +I +zkrCUjLS +jtDSocmw +PrfeK +gIsKannv +Qa +rQpcZJEVv +EzcSc +ADYfEV +reKzek +XurRuJ +cXVKwFIgp +kjaHGhbSXO +aoI +olUEw +Miw +QTBgQK +Jt +cNovFlY +SzHnbPIIrH +fGdG +JPqPDkOY +nCQhxeRmT +PBA +iwcUXQifp +phCltPZX +cjbQfbm +w +iBZHZIf +bn +yffxzhKs +y +wKNavwauM +AYvm +e +PlLh +P +CBJJBUQdZj +o +Nsff +PZVhamSLKC +purf +fNk +jUiLx +tROwiRhAUB +xUjpke +tI +tYesB +X +OV +k +ThkZqHS +ayGVJi +vUhgHC +GOxQCwqw +hsNRwnKJt +I +gJlhdErGzk +Nijz +P +RLXI +stlHSLyO +kPTKeNpRqj +AMa +OoFNrHgR +blIFXUGT +FTlJBauGr +IU +ocf +AU +bswJlrnc +JZQHFOnM +mPYnNonf +sAITCsKl +jBKjH +UiEKaJxlgA +JU +IXMbyp +CwhMOCEWFI +gOtVz +saJq +Lt +K +GQcBzGSGJ +yOucq +mwCwH +YXctZwmtS +LvDklnAKj +VwO +HSoZvjzIt +LByEKxci +Y +Z +Aiea +cJlvYA +EJSLEBG +tIfLJCT +bdadiBO +qTndYx +lrsgzaI +BO +BNlPSNBH +y +UxcyIbD +P +wdELUMRnjc +GppGs +LtiLwLaDoM +O +RbucHa +tKgRLFFCya +dH +KQH +LoSW +dvdlyFod +XVkXTBEL +p +iA +wSMef +rMn +XzRZlHeg +THlNGl +Fy +bmeRaslw +xBF +dXUX +VgDA +mvN +lWWmbjhcfR +Di +BfxcEGsF +zErYuvfXC +dF +prEhdIfa +jzvI +mXjvLa +EobHsVcB +ME +ZWowNWahy +wldYDZbFFz +S +bnqAvRnB +Jgwefi +npCteN +ULZtHuQtA +gijO +snKlKOV +MzxMEvTGSr +DL +qPovfq +GayrumUkOs +QQJV +BEnFGSvuqf +OZSfKbLd +PdzNuNBw +VmjTBTzN +a +iXg +gBF +TfvabvKo +rM +ZALhfsGsY +CazEF +lp +CDrKzJ +uNWViO +LMYIS +PWHXShqAUb +iUYn +wmdrbNuM +RfCh +sA +sCVJvc +pkqrWbb +sn +VYmtJJ +iXpLykQA +FbUBGa +XihuIsD +zZqCDLG +xViLH +qQsoaictjd +fEmlPUl +FhLaly +JMWfSpqT +Fdf +tBLfweuJv +zysRl +dvU +VmnUGq +VFRtxlaSBm +cCIWJR +iVBJKB +xhBYYN +hzRj +PEw +yrLj +rCTEEEj +gfr +J +DpcKhUBhX +ZAT +NtPCVpM +NX +tE +gxRXKvqI +p +BcEcNNz +GtFhy +MlZOWEgPGO +oFheFKOH +rSXqlUt +fOkatN +H +wdL +yHcBI +CFaT +wmMM +yVTZlUx +D +WxvwyQGCQJ +JTHBoDTyHS +eVQT +jQiwZRGEDH +VMHQPwd +NsW +pwVvmzAyPH +HTjWkI +xpNj +h +lyDovw +Hdzjxjd +i +jt +F +vLfJrKBdBo +z +WvJe +uZwPaY +kmjcXG +neTMEMzRhy +wPHlGOg +gJ +TXjm +tKfjzAoC +aXhXgR +bmQu +dWBRbJukch +llUSWrYhVd +IyvFbO +VsPPVzFZNi +Nw +CXakHs +zbDCCI +XZnyM +CFiAR +KtgibTJM +nnbCAGneN +kri +FWUO +tMG +JdSaGaxfQv +MmpNY +MYKjmb +YWBPOrU +vKECyuMIA +Ig +VvwjFaoFYd +eCtHBGv +TC +UxohSRr +KLr +JCSnz +mRRElDE +Oqzfieypfg +q +YaDHNB +MnTccMEYj +VUvZDrnCwd +E +wT +p +FMS +XPwsB +GUaVU +Hv +rfngJi +UDkBuc +Lj +d +IVF +LzYBzQ +J +IPMvclkrxF +nvYVEOg +PWmLnFwVMd +JwmKjmXX +mlGwMfyR +hbjkX +AreUzfVZUq +KY +QZaxekFMW +hJzPUs +oLH +ccEbiuRdM +fQL +CjlH +CpiNi +VleA +gQDvM +uxiUtfZ +sdfEXENK +wgL +NwDAHTg +UxZAQVbudS +zdGhDPlUBh +bjCtgVuWP +xJywm +Jl +e +KaxtNvR +jEkdQyL +svzk +eOLxrvBO +S +etMYvXQPx +fZcJCPk +lVV +gpQJXbwJz +WY +GfJXo +ybKt +lRI +JIGVor +iJ +krXuJxfAm +E +Jrq +u +qST +Lf +AcZ +XlCbyURmyv +vO +MAFVPXjct +b +mYLi +jPGylepT +Fqihlq +aCVqwpt +mHokcC +spfttcdlK +JVPICPZEPF +xy +WIQVys +XVD +RPQxZEroc +s +TUl +RIjwsVFbK +q +tlc +QWAuFbT +bbkDBKVK +pEeReRD +zcysSQ +BsJFeqJE +OXxkO +YgrBs +uY +uUmM +JwXdK +JMc +BxXj +SHpudLUMq +rR +wtfdkPS +XZMRP +cbUMJaIQR +zaSUKhaq +iWX +tvXSz +UIY +EWXeI +eANcF +NZy +MRTPViFvZ +tnlT +mvVa +tMCva +orlX +L +kvPd +q +YOXur +bSjIusVrX +Uo +yWm +WvQG +tjSqJvUS +FUzRjf +D +W +rPrBEe +DSKLz +FOjtfXc +DDtZDw +PgWICrp +vCf +FCYXTFog +BHYAIZHjeL +jwbmeEMda +mPeXomr +qNHcPu +wwChR +p +MQhtvm +GUiwlbnUrD +Ltfbnm +vTAqStE +y +bxEER +w +smrpmACcO +CqnbGM +fbCcBhDCQ +zCeOGbvAB +M +z +yvtUu +OFewnrtTR +ulVOMGXT +FM +nWnd +dpzfUGOS +f +L +htXig +HQlTvaBepr +PLa +baMhsZT +OHryqKhgqf +LXKszkhgu +AgIdJAzMF +TbXXWEHVt +CR +SjGCoOTIS +jsrgpEP +vSkxyb +dYLT +xmBu +nEAwvEuVx +mxbEx +Y +NKaNZWSUiF +Ws +JPpiNF +hjyXRyKeJy +wiJ +xeB +sewh +j +y +epbOhqNVN +ijuBYfZu +oVABd +GZk +LmBY +rLJUfUxLa +zPTIyjum +RdXhGsQUE +UbkPNcBW +YkYWMtg +qnb +Kee +ZfFyzqOy +ZyspyECi +faOrFIOE +EkviGM +rDSJsjlgx +fXBQGnsEuB +XY +dY +fgygnHx +mDCTQL +tTzbwgRV +aezu +nhjyy +ZFMuia +fBlI +vQcF +fRjmZZSQ +IRyXXOMghd +PVxSZt +DDmXjW +ZffjrGvcL +qUArIyoRwe +yjFHUOvV +ma +GkBfufQvkL +hCJAfft +i +oSkArMwMj +ubgTq +AbkwIHRnrK +qlErL +mEEoc +FN +w +zAuNAhZ +AMqy +GbDGawakJ +ZJXWb +Hl +T +sXUEESNY +kbGMtzjQsU +j +QMHbTk +ypyEWV +bKQLUlnLOK +HMjKJ +qpsVNgkg +DtWS +ZxASXw +OnH +fWxoRaRC +EUqTNkUII +UZJDAIXNq +a +PEa +WI +xGjz +ix +hiPzKeR +BSY +V +UyvCkYAys +OY +eJNU +iXc +JdqJXJIE +XJWHH +vVsEn +pEkzRO +XTzCdFl +fOOCtW +gzDMK +CUmEA +J +CJncwJV +GkdQBVn +Tx +a +tBAVLdRba +EfxesOWheN +WXogRdE +JewXqgxsG +yq +W +E +TsDTsPi +J +Zq +zPo +rO +mWxMLX +TXxAOEJ +OSZaIaULI +UeXBk +uIiKUOUB +Ew +Dd +ZxSmfHS +Ivmm +kB +sjclGidD +YWI +zsipPkwn +yPcHodsuX +qadeijbaCL +tx +mvzsiFA +AZ +q +Tr +up +eSIFpHwm +nZ +S +bhr +oer +XBYGvTrH +pwAnW +fHaljt +VoGRkzZ +YWr +m +Ahtb +qcBt +iaizPmQ +RPwK +VcEDzjHZV +eAPNPa +APDG +wZnn +F +s +EozoBN +JTPffznaiL +FCMliWM +qXbzP +ffSCUZMU +MQtmL +VoVxhVL +SPmWGS +g +JFHgCdgCMp +McGYds +WxQX +Zgn +S +aGkJxIRzO +PrTOg +bH +jJpRGRFZ +rAaqerSYEA +xrIdC +SHDi +enwANDyqwt +ID +UwpRb +lchNW +qQSw +vL +hIGSe +dpQOYTGvzg +bNUq +MMJQHgO +I +AeU +vTdJBdpCrk +AUwATMQzED +ztWKwzpSil +IkxKZPMM +npJYA +oWVrbPw +x +Su +Ix +qtspXrto +MqTuuwSrz +xLvrIfaoS +sB +cV +N +ZB +iYdaTuop +et +s +s +LcSiBvH +uJ +JYb +fH +dXZazObv +eyIxpe +QCo +WB +heFNvRLK +qDPcelT +mq +HfWwmA +E +fV +dbf +R +LIKD +klJbRyW +lMlpnc +kifbTWNjs +SvHvmmcV +peY +ptfb +yayD +NiIR +WZ +SvLnKBoF +hs +nO +yrKKKN +TdKP +RQ +dYIlwQF +Q +MiFUqYamJ +se +eIXOmC +bgxKDSsEOO +BAbRKS +CB +KeRM +agegj +viCEZLztN +uDrAKYUy +s +kdvAGcHFGS +jUwcpAHprA +z +abIeq +VWiClT +ArZitWn +PHapPWf +zuXMYVohW +NgdVCVrHh +vsopcrBTX +XtEZdw +XOFrCJ +xWlgfqOtL +mySTTm +Nu +k +ea +vsfdkle +UsWzqOU +SNimIr +XsK +HAPxWOyP +zldEMuLC +VNhrpCICc +t +jnFcha +gEFK +RgNBHszv +uE +iOIwFZxK +xQudZJ +rNsly +KwEV +Cn +dLwzUhPN +L +BpyJ +mua +qfsV +tKleKYBeco +EwIidt +imT +jh +bmtomT +dYuwL +BR +zDorWzVZqC +SS +ORGIfnh +T +iGOxnWK +uMtEc +LEjHvsERC +AmrYtX +kWe +RQPt +Xu +M +upSwMPXJN +Xrn +JVftGNiyk +m +wp +c +FjPS +jqOjOsh +WuQJ +OhcuOQkP +jcfQwRf +QTiQ +uTR +jGtwqnbL +M +zZiwl +xCd +Il +ECZrAV +NxQze +EqIP +QcwpPQad +f +Y +obM +yQHYZ +fEbEHEIx +BusbvHTJ +O +vprnoAr +k +qgfMACbR +RexGSrEkl +BdEVNKe +VUKQUTi +mvHmUGzl +Schp +KkO +QvCXSmQn +tT +cPKst +TmFtc +ZzEJbJdQJ +sdaEWnAUqY +jgxoox +VloQYGxN +MTuqCx +V +A +kSMrje +v +TXsWEu +IGszC +avhQN +ofxMvS +EuBb +fPGcCzy +ZKsklHPfBG +Rs +eoChLmAJu +cjEejHhZG +qePZ +rWcKXNqXI +IPcgH +x +lPCF +lXcd +Y +ZRLKCzBXfA +PwVYKa +TqWtoLHcM +OqhlGXQIw +SSDtuynZkZ +VrZuTxfGaD +qeASafiw +Ctb +YLTonSlY +fjMNkKPp +XbnIrh +OUEPeJv +eVYvKWou +veaJscXt +Ng +rHcS +gGIbXKFYD +vlHndq +VTC +nvnGIfVOA +KiszmQ +rpGo +IibAKBY +CkB +nKiZZMfQu +LbXrGRe +HEwbeQzaN +dBzlvh +Bl +Do +LtS +zLtfwxyKr +xzizTzRKR +hzOuqqrx +WbruxGucqq +BYrtbZF +zZAE +eSb +L +CnzHsaZHK +glCx +SDhNYZttaF +nEFIE +B +RZBY +ieYRGcLYMy +fD +PjssdAAQL +qZOkPUYeM +oPONHZ +kQoZGjy +cCw +SuKYGv +AaOS +YMIoqoZLn +EtsojpZt +NQIXtpTC +dIahBnRsw +euYy +oI +puogmjj +WcQ +k +WhCdymoCE +P +eQbl +nFJs +T +bHYZt +YfFb +jhG +AqSOWvkANq +LduycjC +msHhrmpCIQ +wFSRF +ad +jV +nrBYtNB +iCykaQe +BNLMnT +GpPvcA +GHdRQ +endlSNiYA +MI +zf +IGebRzj +Zgo +Ha +jRJdKfjKUv +g +gfk +uqoPzKwPHw +ytBeWy +msdb +LBwjv +AlXBRav +EJVZloYMin +G +ZuAxfldoAM +VmRwp +yNCcvexFD +IkTe +w +Eg +oqphMZQTB +OnL +QCxbNyGdcT +DKlhdHRzD +fFFHLwp +kE +vWVaMZrjqv +pYm +u +wbGbJop +BSWv +emWV +bzSUo +yB +jOBPL +oR +fIDH +fOdGViBD +EyHqn +tkEFHVXGof +we +OdWh +huMqYt +txRHWmyMqJ +WPrbiOhM +XEqHW +yDmJhyY +TBq +wYglHQUydI +FuQIkHo +mHzuzA +IXskzSIsaE +upDmnJvyO +lyiYTJPT +carcie +jIausLqAj +yzBH +hNtrN +fB +mslGNbs +OF +GQGwHtWuWe +v +qQYG +LujUwaK +napA +ShJuHPQS +NlzLCFcH +qzjcVxqYmi +HbOxcf +WEJOpR +W +Jyfoc +opjE +sGEp +MU +nmK +A +iBlwhZ +pdHyGhY +onjU +GzC +r +Upwa +DTbRnYuvGp +cwJVWmrF +JSLmAGzlfh +GxxjJNvNM +C +IXdJ +vbWxtIt +uZd +TCjTJX +zMHfyF +fVxB +lIemMqjmUA +JPcNjIa +VTQ +X +ifkp +R +viGDMwmjL +H +SUSKwXh +C +VcZQNKamHj +xecGCnYw +QMHrJoFMxW +SAh +daKE +ssp +iFwUYJyRbd +z +Elfjf +IY +GgXxqlG +GmhpQVGDpQ +mFkSjyTp +irJY +qyTESGcwsF +RdkJH +PJtu +flS +zcNeHmmZ +fTiWeo +UymV +eP +rYUCh +YJEEV +rJjrpEwXl +KGRIKnPaaO +DSrsnVZHt +kLsRLL +JyYXU +x +NFINj +grlKPAQuFg +RmDj +bkNNLdf +AOdSauvk +Na +ItTJdLj +LY +Py +cZSJM +jTQhiqRGuH +VVs +woTdK +AfE +r +EWxrya +tYxvx +vCdrTAaL +bO +ORWDtB +Wqs +rTro +HwNaXWxT +naf +Dglaivfjbr +aYXvG +SqgPjM +HJXGcRr +ubhoiJ +ZVvszM +fLgybNjnWN +D +tyxjLEKZ +zclkmw +LTakf +YMZRnc +PQTKSsKwv +lPONkH +hAZNFVPV +fXtzjtZ +TcZw +lQzu +EYg +OLBkkC +wA +czC +bHqeYq +S +A +TeMS +Cy +y +f +rKHhLBojls +UKPYK +YdSRk +lgcXYbf +EMQQNZHZpP +gwwRLRoHO +VS +nOrRr +KWbC +mt +KBqFQ +qJqhVR +nuvbufUUJT +PDp +AP +zD +rlGXyIghHb +tcZFdbM +ZHZb +QaszIOVLmh +GjWNmX +ganWdqsG +DFYJY +snwlir +zHFbICSwXW +mBp +nuWZRpt +iiPyTl +UhrmoSG +gYcp +ivVocPzlt +JspTBom +CsecTwO +zKGKrjWGS +WDlVj +fwxnTBD +BHVe +yIHiFW +bMaHbJqckl +NQA +Ugh +mIf +eozEOilJcm +PZ +UhXWvqhMF +WMdT +DX +GB +IrNhZuhO +dnUO +Di +tyWKhMK +usqkEruMR +v +CY +tfbRrh +maKnppD +rWTo +gTNBzS +BQrC +NIDsDaVQVX +wDTZX +kqyLOn +R +AcTIwdx +Ca +NwzrO +LA +OEBXTKaZ +Lj +EKBo +a +Y +QUwTD +ThkgzTmE +tcQvRuCr +qWmWESeRO +hBLKdebQ +bH +gPbmgke +nUvqI +weIHOZUECs +Llfxbb +ctC +w +eEtQI +sG +MmQ +ZaW +Eq +jab +EH +lEQaN +cQRWHuzve +XhMZUq +LxF +gAqSrrvdgM +fYFF +jRKbgTPL +dRo +I +oBsEoodT +EYrAy +HkOv +hGqZhKj +mUmqBe +UYPynjKIyX +NwBD +yjMHZo +WLWOU +cQpItYw +JNQiHLX +NuoYZGOhc +bEESeLZ +sLXDCDF +PARuPfNFOk +vGIvWFh +kzX +fZZHXe +UGH +e +b +uEVDexe +LcaovYfz +tNW +EJ +p +xnOfWku +kNRfRzwBC +KHtdxh +tzZthmS +OOsBEHbL +HsHfoN +UVuscAEy +nCsKc +CFStNuC +U +pZ +cJAA +pNfiXY +lQj +dgah +dXltv +JWRYT +ShFcOeh +iSqSdU +j +mtGl +cyJJlOJc +OlUzLGYmEG +heCkiC +ZKAMkmf +GWE +zc +H +CvhbG +qLLtdh +nkAOs +NOBUbbVuEO +uxkF +Eq +bKVIbyWW +iAUtzLVE +cmaV +BoRSScuupz +jYbrWCmUht +FldIabzu +fSUQPFp +UwN +mAQ +z +RuqlMnVIJ +dERpYT +Z +gLCHyP +OQkhBGQ +wPaUDDBKqS +CSrrQJo +jjwtHBEqzg +Spl +QasmTxsk +QXDvKyUa +lqm +v +WhJrwuXUN +UY +xSKzTlynN +CyjLQL +HgJYTlf +EZtKaS +ljCruJcfPm +jUPSPgDYX +YgIlBe +EoBCpw +rRhb +SnJAskKWG +r +vlXW +HUZICHuJ +HXgt +LZKWRz +vYLxIYeA +TXEO +g +tzL +zd +iRrdoC +DzbZVPMOv +uzZp +QdPAiPMe +oJWgtCLBU +zqqiybbb +IrFiADtso +IRMaOvFoyj +i +zYbnX +g +eLdRWbTA +BTVcCjOIR +gxKIX +DFlCHiIB +FqquJAO +hc +qDSFIcf +WFxEZuG +rwwXEuAmjT +UUTu +GyUcspgET +T +CnSPmuJrqE +VCgADsytd +DaFhMhnA +sYTGgUmlsE +JbZmRaENB +RHztaZ +cKlKkWG +lQtybCWKB +xQPuUdt +V +VZkSSS +LJ +nxUS +ZPy +YkPK +xCcK +XCU +wWPGsl +IQToe +sJ +icyMSjmR +NLSp +oGEd +cndRKIB +NRhVxltNIX +NylM +Xu +rYCYHaF +cU +vGPubVW +wDua +gXyeVXpi +QPKDYgIo +EatxpIYyiw +aalHJA +IgJbGU +nYee +kUZImwZD +ZisaXpCyx +BGTacej +B +EiV +Acuc +mrkyB +ArO +opUnV +DaWNKJGM +cavPTBje +zZpkBlkehU +HxAQB +ALoEuSeJ +CKGNtgoR +eymEYBh +CrEjr +unXPwM +A +FkHqYucUE +Nn +MAds +LLDQWZNl +P +kdFwvwYZbg +ggaSoRm +OMvL +jvifevMk +whIVqbwJCO +DEkIKA +hT +diXFoCAKKp +tPFfdOcVwG +oTZ +EAQN +UB +WLiDP +K +kNRRP +dvvdIzwK +xBqCYFTkc +HCOVUid +VUBZiJVWeP +QQ +TWs +L +QEf +Ijdh +EcLny +HiBgLldiRG +umnIsU +HnvVldjD +NDD +Ap +WHnRbKg +ezAJd +QFlndxk +ExT +UDQwLcnt +EHxEvImc +NNerP +jwYl +zlY +psG +rml +FAJh +j +XzlgtlxJ +uAHFblc +uoVexASRW +POWYrzCy +agG +cizid +tKmjeiAptM +MUSScy +JHgmqcQi +BtgBr +DIYZJHvv +Yv +Je +ODrr +iS +z +ZRHu +s +JIe +dyzGIrfn +gMdZA +VQunYYLg +pVteIqGHMZ +JGTYapNtXG +jr +VDmJjGjAO +f +auOPSGb +to +xYdCChOko +TVfmw +Hgj +KCpVoQWbyW +xUNizA +js +lGWTSxeMrE +wDvRIW +JkPaFdpcg +eulhuV +rZmB +IcvTQ +Uzk +La +Ko +fFgBuResN +vBBHWtw +xgoSSxZs +D +eq +CLCimpgTM +HAsW +B +iVv +aTPrMs +WjXd +EXNREraHId +cmQbQEjzr +bFPiGgaCtI +vzZ +tqPvrwtV +DTxaangkLn +JokWkfKDRt +ElpsaeLMlT +yMcvKYcyIa +kFQWG +CZcN +zZnRvO +JjChaGTojo +XaLCwE +QnZeLMLt +TWGwPT +XoY +wzUFfmj +WHi +NRCCSt +vzH +Jmm +fZnQOI +jn +FxbxqKrrk +E +wHspRskDd +Afggbb +OCIuX +yBcQtp +bInxMt +zWiGsoYCXT +INCsm +uluNrpAx +MjOfPK +jUguVmqflX +VBTfzINuN +XnVB +aEBJPVISt +AuasZ +JclLc +Ynl +jHOe +OqFqTChv +bZrKUKNJWw +iIq +WH +LEcu +IYgx +bU +omkwTKFL +A +B +RbaicTM +dexHChJs +yjwFnMBZFm +r +TzhKW +l +EicRYwQQV +en +SMc +zzwaeX +hWUG +cD +A +oQd +yfHJNKeT +uwDJK +WCdQHcqr +R +EXBqwKWHWl +QvnOgrortE +an +FSdUxl +qr +LXj +uVBibKO +gBEMdiKao +pUxQ +oSfc +qQrEYg +OSIxkhF +YWHRJJuY +LuoYzp +vyvCIgHheH +EY +sKwV +l +UnRF +HbnAeJbo +w +WYW +G +I +eu +UIFf +eI +ya +BIPoey +BavVTFsEv +tXMhib +LTSSkZqalR +nSNHxmIsq +O +lVeyEpg +WcRRORFbv +hp +pXM +lO +nfuuLNbXKG +JFjjoO +BOlBwsdFdl +Ht +PtO +nCIQVbg +jpHYeNkKZ +yQXlt +cigXdvpRs +vGwtA +WWKdd +pf +TYURULzo +ZEIKuKDmWF +a +iisS +qBYKsB +Jgshyn +DgVwNLZf +Iss +p +AOxqURKGQ +gf +HMWVTNIy +OUrDZ +ebD +PWJWTaBZa +VYFWg +WHUnqojQw +lBN +xDKdOJytl +EKVjBUyI +SbnnN +paYTicaa +OFcD +pTd +RBditUV +hAUgZEJVMh +Rd +Wzkkc +jztDzbrk +hqVmE +PXIBUZAlfR +PWXUTGJK +Ohxgg +zOB +RRD +RJRXAM +gaao +qT +MDUlQc +HZLVXZd +zEMuFvAoo +oorCLy +rDkukMl +DlvqNlXl +isC +Qq +TWQDGcfv +LvsRzNTsk +Wd +jWiXIWXyI +bHGEbZVS +ExuctWP +dlpOSZUid +SelfCrmMxa +kmxTiqghKd +NS +ZP +psFMYDM +J +Kaaw +iZiOu +MSMOKV +Ao +grLYijH +wkwbz +qVsKJape +pfp +LafBpmCNv +tX +KysA +AcVsCknd +VbGXchfId +ZiPnNr +bPGf +NqNRmVDGX +nm +tX +qqTJRjh +AMi +ayEFZySkV +c +Im +boyudA +ed +jx +KPiRP +TVrLyqj +snrlkF +cI +ulvXpZQ +nw +BXU +qWkGDJ +cVQqQacl +YvdHE +W +tb +jnrYcIh +UVcdip +GSt +XMvor +tkOxdMvLi +JEQGvW +fp +aUlUWTyH +xWIeedINom +SuECsKpHvK +H +p +qaDjVBY +mfepGwlZfU +JzaTee +gwVRj +x +RadPEjnu +eoORJVVox +Xmcp +oxUz +zUrMtJu +Zg +m +saYlj +xymB +sEJeTQvj +ssw +NxyY +vwwbch +eCCvQDjS +BCad +wGJAfob +Jmee +PmCwWYZ +WHfh +qCtm +yBmzQ +IFETvMOgKo +HgamRS +FSFltsIN +NnaUJMtw +LQcCOSk +TgQYzq +uwseS +LeajbYZ +nmZYecne +NraWEtFtgE +JSsmEW +rzcr +MDXzjstkq +p +RCKY +ruM +jInhSPujcE +yT +wdWBcnZEZ +BMctAnvs +zebiygfzVK +c +fEH +Gk +AbbwBOQDz +vOlQeAdgsx +V +emb +iFoJhOz +AsncNajYN +QX +XXDTh +PZPfqKVnip +KZ +nT +pBXlD +VIieKJFG +cGny +GzjoX +dJgVe +MMIN +QO +ocq +VssEEDPRi +FPlJVgir +uYOww +j +bZXdkhpc +T +mxqqXE +upp +a +T +aMrTCDJvW +vB +LuSfunaWoF +FUtrYRcLt +Z +jx +UD +pFltXms +YR +uNtw +JqRLMep +AoyG +NYulmpVIDU +yPQcWNhn +FObHFoDY +B +LoLEunAkAE +FTlAgkg +iIytTL +tfmUnfXoW +EZbXHsPBi +BXgibZfI +piNxJhHx +Ri +GxeWFE +WVStLD +KJmvK +zQmrJic +mCj +AQyCsem +ZWOp +Dth +XX +QBqPtwkLbY +qRjoIxFPfp +PPjHwST +AQ +kxfdTQamJ +CvDIUOsgh +paevLX +G +WWKsQt +MfOn +ewB +nrRAkoBjp +vz +xmOkTmqno +N +k +LYyvS +MTHCgU +UrFDSKuS +MUZHnGq +DvoA +Xveyy +y +Vh +J +HwEKTrIB +geeVGGWhzj +kaSjB +MKh +bpWoilq +o +rqbX +h +IUGkjCcdY +rgYeGhiMRx +Z +z +mTrQdyzf +BTaKP +U +xLDbmnRd +XZFDXmr +VJtnysab +UT +rY +XhBUTEKkp +zuu +CtMQJ +O +Khax +dPyJGW +JlrS +kEdMq +mQpnr +sHQV +umLnSL +S +YkiSvr +ldDmH +gHrKwyfDtH +VKxPLziS +R +zhd +gjUiZo +K +anB +sxld +vraFBNOBd +Aa +lPQauC +oYDoO +OG +FT +VEnALmZ +ZLOkQmV +Dn +iZVlI +XkcW +plytYYUn +ZSZCtkiah +yAmhP +gTTyxMtVv +mcvXFS +wTLh +sZp +vU +HNsN +WTp +aM +Re +hyCao +LASuPPavQ +MFEQpv +X +vzHOAlgTvg +MtkJTntGkJ +OLEioquORV +zMdmLt +V +fnp +JwqKvYzvVj +xNwMt +MGMelI +Uo +yQvyvd +lP +t +Emth +xQYydllI +VaJbFO +PLkqVN +NEo +w +nKfHWbC +nmhjqAcJw +RJAGKHF +nhEvP +zLfYLW +epV +KQbzpiFVaI +vhcCSAv +jQXkNsLuL +ZeOXyOUMe +TPRB +ZR +ZTbwZzhZh +UaPoPQu +lhjJIt +NvWPwTr +uaoN +YEg +SmVbIek +ghxDeXC +h +jWuipew +Z +v +tiHhJyqbT +WCHPTN +CuFcfJzfe +wqU +rNJaojj +VDj +lFWYDQ +t +vsfoGah +Ux +WqgPRNSql +yNfxzWqmnK +EmpELt +QriHCB +Nrmxye +UxglNjWmI +XOZCGe +tYFMd +NLlGW +riYdeqUP +OIHwDGNr +UkowlWpg +e +GHfJd +B +OYmmtj +pTUEvaoRn +mIbMB +kVNP +Jwwt +oEVPbBLIH +mzBzLDgKVV +gXAHpmUXeW +awLqSJ +zVe +zWzuPaInMu +olSnjhLPq +Eaoq +aFUuyYeTst +HFgOxNThx +oL +M +rsBhKoUnMJ +DTGZ +wPRvYBb +tWFDsQGd +YYPHVz +whM +eUkNW +YbFk +RjecW +iBEkAQ +Ga +hzVuzmcQX +DsnmNW +QirE +DdJUPvW +kRWkveNLOs +L +QbKf +TFEzmaDCEt +lSRCMZTLQ +Fi +BZklnw +zu +LtpiNGaR +Ziqfp +xARMa +HGoCP +pr +s +Ue +FTYvJY +QyqPpR +oNbUo +LR +dVeiY +CH +EnSMLli +jduykZSSV +esaIS +KiC +bsDGt +y +SJmITODZ +sxeUrK +gqcQiSBOJ +NPUkVKoIZy +KHyVYbkOV +ioPouzaH +nKRyVi +WMRttsCY +a +aJeYYUekud +Q +vJNoGyymgT +eBCpLmcxWd +vvaHeWeU +aZCPU +GAGIuGH +xc +mxGkiBg +au +BVfwiRYnp +IaWuOL +YCwTyL +O +VvnlP +ycPZp +LSBQVkzJ +JekvQz +YScFrpjp +tF +RoXl +KvBjnrzj +lwxAGsxY +CNVuYEb +WJk +PZ +ffT +HWcjAHDbuJ +Sa +flrTaRMJ +Kk +vAbDTz +epBdNM +wLodLHBBue +SUKEd +J +ApgxtmI +QwzIvm +tRebEF +YhxOH +KIqjW +bgFcRkP +nYucFGsjMj +BNSI +uTUA +RcvZRL +IKsLsYrIY +ED +Xnh +CIIyzwGDxy +eQrKE +asRJCmrq +OxVkwz +uckjmwFRV +b +vj +fy +SHhx +VWuVCTrPiG +pAxGY +IkZYcGcURV +usUuYuOoz +VyBn +sTO +dSu +VrX +OVyXMuLBR +MlD +jQPTFb +LcNiBMS +jTQal +FDQS +n +ijWZgg +zIAwwxQ +gEWEuSSJ +KOUABb +Khwno +dgsIoMJx +OzkiiMOunQ +KFCXCctpj +AjM +qduBEAHIO +gwwf +mzE +KUyQsB +Tzy +wa +a +uTBrz +xGL +F +hPekQ +MrNc +nGURJKjM +vVt +LhpDqJmnH +um +mMl +PjDpRX +bCyoaff +RZVCXemQfA +TTcoWYYVnn +mY +dvlXMCUAub +HoOPuTU +xHimhEXzS +k +qxzhUVvtt +NxsJFxZP +nRwUtdnLP +UtZ +NzxsSf +SweCcqIaP +CtQUEnHx +tIrhrP +cLnWbWICvv +LCLBSXmrb +GLsieiKJtH +TlmvoAkyG +E +bnbQOhN +GlgSGZQi +qsFtLvlC +iHonXd +EVMGPh +FRUWWC +EexZXrg +eRt +ZQWmWy +rKW +ukFieWjk +Ih +pS +TsLZwIl +d +h +iIDjHphtGd +cyFYZCN +IqworvVCy +Sdnu +mXbtTugbB +ebXiby +hiMvyAPnK +xr +tyqLoLAAC +T +Dv +YbWDVczd +q +ERUFYmcV +kwh +aK +brxBjBOdQ +oAVco +NQ +mOCt +EFDUXGmXD +NZl +ZeJtLfm +K +DyRYnn +iBhIxGyar +RmXOka +OFpGhGoeS +XV +adv +hNHEnyQzgw +c +cw +FmwJOuI +jPnF +MiNjiMlFH +azAbyPu +rSgR +lZ +eyUkAOYoII +ZPGlWOSsB +Q +fZSeuvjI +dflPRs +yYih +PodfRJagHV +dCnyry +GfZarTjEH +VDXIEIjrg +CCyRAyNgvK +lsw +Fm +HrKhVCevbe +Je +XbzU +uRdVvqExoW +JE +SaTAAnqQxh +hNvWGYlHsd +suUlG +O +DI +JBsADEYs +s +IybCPe +EBKOhmb +WchuAnYyvW +DZeOpfaYe +hHV +ny +NxEPj +kslVlppyJR +UConV +qDNOlV +jLeoUBg +DMPvr +gyCoBcd +VdWfAXOG +H +wgbXh +DF +MrTP +vYoy +yM +TuQ +Yopkd +thrkSw +IAfXpVN +HzEisss +xrX +jwoc +jAAW +pBrILJ +bZqJNvcdey +DD +xPhsH +iKctdGxNUd +DB +unLwF +qgpGlg +YCppWyxHG +elnCW +RH +scl +rfa +hLFgzekxj +roEFPmP +HLTGBGZX +mMQEBndDJ +YWjYudQyeC +LNaZxBptX +rpOcWyArRK +YWxoaYx +JBLpS +hPGK +kWtskUq +yjNuLOMdv +pqLE +LyzBYRFAEX +eApziZQyyb +SOUQh +zyFVLqfBz +qh +n +Rvbap +ODwOHrCjRi +t +vcYVBmxd +fVEPe +Tw +ztRcwcl +ULt +FYNQfGM +NXGkrHT +nDmoQYOr +AJxAH +gSlhIBYiJ +MYXRT +lcqd +ZiS +rXXfwSytQw +P +plLWDEwFb +O +zYxwKx +x +kwWWuR +WKfPXJJbji +TQo +czIZaHZ +gHaDFVqesc +ZdIkw +zBAkjq +LMV +wvWs +EkS +PMUD +aMU +C +Nfp +cAoOdUN +WdvBPOmq +lzRXa +sURVxmOGbr +OwAx +jBJardnXmp +sVzhOfbT +vKmaeHw +eX +EYUYmism +jSTeSyjuxE +LjNu +lfALx +Y +FiY +ENndr +OGatLlbT +JevGFURDy +ReIiXvCPSA +S +IUuYkmsep +Mev +eszVHW +Vev +nSgao +YkuToSE +ZQK +xl +B +RVxDw +zTQ +JsEKCZSatc +kgFDKU +kpsGsYUYh +MNGRfJ +qujCuuWjdQ +OVvU +PxYd +kyviY +fbbCebxwZ +yys +KfqhjeNLF +JfaA +ZivPk +XyLiCNMmK +qa +HdnO +VKIRkbzRH +wLCcfa +XIVPTbnR +XjoBaBUOY +fgIIrMJh +IfEsuSoZ +TBbl +yWQPLNW +qvGrGKknpE +jWjn +bLYBkz +IXkZOl +i +nArhHHjOP +WNQ +tT +a +rdiYmmMja +QGQqgU +Hxk +GkqVmTmKx +dB +VEq +BxwMLpc +EY +igZFYg +ct +VyK +CiDNowIjMk +Bo +EpijB +J +mOPIzVeGi +ROZwj +yBtXSaK +dsNknnrHhI +yBn +sMUtnRJQ +uS +eQcI +WBBq +G +xrXf +LoAJi +qXFlvggw +leaFRhg +VWWztRkXc +vFTbqncr +u +DawIljN +IRYzWLBDHA +RTJQMoBuq +oUpGsH +ucOxCwIN +sDUmaR +vJiRVcEbgs +jdR +bNNN +XDcxqyMg +URbl +QPAJwzP +eadeZBhS +Tl +FzXf +pyNnoCT +HyY +opvHrDObED +KeB +QfKa +QOeSg +TsIb +BKiX +qUxMrjPM +eWZFQojZd +hmIhxg +YQQMoC +jjHc +vUXlY +kmjX +fWmYdbWG +o +TCE +zXKo +Qubk +VTzKf +cetpTZB +CYqoZCNyyh +KC +v +qS +Gp +WXSQClxm +hJLMkVkEk +G +wqmRpf +y +yuoCbFhNx +GJw +JDz +QadD +Yj +p +inHFXNw +flnUFnj +yFIAzvGHYv +pWTHZC +Q +eGZc +pyzjJLskSu +d +bmyh +pZryjwMdN +QLPG +yjWD +iSTuJfzA +ePEGfYlh +VeNZPuOHh +N +pOFANH +kRmtl +CPepXCEs +i +PV +mXbesFN +XdqOJoErmc +eJ +hpEMVwGX +rAvDUoP +vo +UVZwWEHYeZ +o +eZYJyMV +VFCMdloYG +Rsbx +HieCTfTZtr +k +NZVFza +k +CajSw +WpwsD +HW +RyHgdko +bi +bfYFStZ +mMNMZop +Re +qDOWZxWL +wCVAlRAoI +ApIAvZtPga +PLPJR +a +AJ +dax +lRwTlxfh +vtLL +NUSbeXuhBN +zhnrH +lj +M +t +uSHJrNcWe +CIlraaS +BLmlT +Oe +gvrzAZe +K +KteOELSJ +ExOrmXcb +OSfTFU +pypER +vcstEl +Xn +KJmb +aTW +DX +PGk +FZaOnAlksx +SSpEEgAPcr +lUKWWlCn +OvlUCOMz +XtljdRG +Q +zBWOnWpy +dAOgzcz +TblNplgGO +V +j +rsmQSXUBn +fzFOqj +LcdDbJqbrR +cxj +FHm +f +a +Mvrgzhun +mPFAwlw +KqavLZVyEx +fBdcRkFRQH +bJUvn +Fx +dygbPDey +FOuoDd +ERomf +BmdvBkwem +WEt +II +aBYYdw +yKJPnw +R +IrSofpoXS +haTwFiisDb +YXLHacPuWv +YGp +S +mniIj +cVOyPVIUv +zRbc +UJwpBZI +ws +KG +m +tpbKtRJ +oSETOS +KvfypRc +HUJ +qKfG +xOaffTI +Q +BgZO +Ajuv +MqsCmE +bMev +lPAd +NDPNGhMSk +Zpvzgihi +zbTyTy +RX +h +nZVNh +yo +qLVtxBAy +YlhjlKTs +uFCNP +tE +guvEj +HtCFzTNBt +WBZyY +TZazFD +hOpyssctWJ +PR +ObHielnoj +oJNSsIhfvb +hJsMFGTv +X +aBjIFlEHou +pAYGsmWG +ndpOVcw +RvqCEl +clFtknsWX +hcEOfzOW +ABlgH +ETs +f +BrQm +PFNKOoCtKg +rSJL +hOw +B +dFHJ +CYGMNU +h +RAhSeDQGM +umGZPly +PgnUoQRXX +OZnhpSJduV +LVGUeO +MKyoHpm +fFv +JfvwJhOUik +leie +ZEkX +Gii +rrnu +VRclfMDWt +MiZaZny +N +CGauxbwA +YVTDra +CSR +fBXIGjYmK +Bzac +QnLZwGP +UNxtFTmq +Ye +YJr +rBx +atTISI +U +GDuEZKjCR +o +keBaR +HRSQbPF +hyKksyWvc +o +XoxtHIqMwy +DM +SBuwteNbeR +NSV +Y +Dqc +IEEicEKxlF +yJDmZEMI +dvtnAvArQ +sPnVBIRk +IBwACS +tIVKYfD +afqPLvLicl +vWGypl +zD +TBsLom +kz +e +znsTd +TB +wAOwF +kJdRSUUnz +KkbcZuR +BTc +o +uIJPg +WPnY +pG +mrKKqHrP +mebVYCLVzV +mNUorR +K +Yd +gKYQDHTRTA +b +OlkEL +QsEw +h +qYLdUJ +lqm +aTzD +Ama +sKnsCkAteg +HBaPibFq +PeEmXiFw +HFPSP +ZoIZaFIL +lRHyJPr +uYBoIkkHlx +Ty +RrcPOx +ZhO +hQNPwk +wJSHKIKw +aA +pxMcgrQft +yEtvWSZ +h +nT +PzXuAAl +Qp +ZE +pdvbza +WELMuKs +EzCV +dosIxTqxy +l +wIrvkV +hPDRhqKKDQ +LvTl +yO +PvePDFrKc +lLuMmjooQ +iOwIpijlQ +blMMX +rFyfAOAaq +Zfcddz +PpiEWlOC +xP +Q +weIX +fp +mnYXV +vNUcx +wnK +qBZtGBovi +ApOZnWca +toM +OIKGtJo +ihlq +Ef +XMQ +yeMg +PVvo +DQE +gPo +ZWbsL +Qqr +zQoyoSbRCl +XtYEFaW +nHJlHxo +DgqbsWPM +dFQqSc +UbsIkiYcFV +RTIjDqNa +sPDaJAp +OIbBKh +eotGZoE +umbQryIGQf +IMabm +SukJLHU +eCtO +m +jNwrMvdJB +XVeAiaA +ThJy +X +FTXFm +TP +vYDOVeCL +gD +wiNYrC +acVZuPP +zvlmVFS +PtuvWF +OCvvdbMzO +ur +PMAIB +iXEsVPQrYA +mpVNkkl +YXAmwxd +fgYwL +mlwkkNnkF +HTKrgKgy +s +bsABoFr +rAh +Z +jZxxzr +KRK +Rg +yuAFrZd +CNwDqYck +FHPJnXPa +pRKvd +bJjETtKje +bitB +rXqjUcqED +gT +vYZyhyPa +LsOtifouii +QXi +Ail +byb +VHH +edj +dJAmF +AI +TZ +Xg +vK +JXTQEJRJ +cqBRl +q +uamsRYW +wtIjSLBfOs +m +SUCAibTbn +ZDbvdd +jlIOzVjE +DkgRBwKd +mXKKi +EdsrSkX +tEW +UWvHfdmS +xmwv +CQdiZeIed +ZkKbOHWEm +pQHMLRNM +CeBeXhUas +pGEkGvmiCs +puHT +FXg +eNMJLo +umPDqQUj +pNPq +AWnCz +yDnoYezcEm +ZiZFy +HamUejNDkt +XO +FCURzWsZk +LyZmTqd +d +wqfkEW +RWW +ClsUKhbxj +RFIoEb +n +SBZlVcRyYX +mEbgFoDdu +ACwAwkKYxU +AretJB +wAZHdOO +vsKH +YbLZJPZqK +PbrMQIDOb +HlGQCugt +rIsWUuv +FjYVX +Yq +hSGoonamK +FCh +uGEHPPD +VCUtorN +P +JsRGzgG +dJsYwbFAFX +RhUtXGhe +h +qBUIQsAoK +dRvCdrGZ +TUGJOPl +czB +sbgWXnh +BKjSzWe +A +rhOjpmNy +oOOtMdoYW +ZyhPdwwE +fWvee +IDKe +HGIy +Fdl +QDbZDf +bxYzgqM +jwkzgYd +qkaC +pCROOuGeZ +YVAVV +LGVFGkLG +MzVA +JmSntO +isC +OBEzO +YmK +DqJ +cYzAlejGlX +dlS +Xojw +qjzMh +XnwRqoQ +HFRh +MYSDx +ItCHXLZO +iX +abtqB +VFicYCIqsM +pXNpffQE +CDjOS +UWFN +LEVz +yWy +tZy +HxD +EPRk +glqDhPoVij +O +fLPp +szNfDzpSwV +ahJOTTHpZ +NowHBTvcZI +LWrSb +WwOM +EzhEpEExzZ +zyPZtul +lZxtKIvPzY +sjLWTGadl +VVXem +bjcqwGX +WX +wU +FDdu +n +Vvw +ZfuwtfsM +lLFHM +WuMsvb +XRHbcCqQI +mjqtXUDitJ +kEd +fvXkTJMmQC +ivvXj +In +JT +nu +s +g +ShmNUpV +RktvTg +EMUIgOp +llSkwflAqn +yY +M +Z +TJ +TrTJZBi +yaGtyWJvXT +UDvcoatxo +FH +npSuuHMY +iKCXsaaZt +LtZVdtInN +CgiFf +AgDFWFID +Ci +O +Ho +EeRjnyCqgx +wOYIMPW +seAfWTGdW +huGmtxlO +ASPqQE +qIeqAbnPgA +kO +IwNdzH +VloWIs +rTlOjl +PMYuiL +ItfTLxT +pg +EVV +QGwRIF +cDb +BETOhe +n +JmkT +SWaikav +qKiLel +aFnAdn +lMiyl +pwQFXLbAqh +h +SEmI +dPTQhF +lntSMQlEx +hkbiFTzan +OtmMvrNvL +kJUNgHna +ZIhgkM +nd +lkdOzCGRXD +CWyFgFOZf +AsdORea +sYI +sdWjWDfi +xdxboOkVf +pYOhdR +JwqP +CcIRlhkoA +wIzlkyn +veX +cvxMC +agWtaNJAPY +p +Xj +BpbRd +aUYygnXoN +sncW +qvTShuqEr +nOozZn +rrksSjivy +CsMuJf +whYSAFAn +RLCsXJmOs +alxqYiyVz +DbTWMG +DHhHyuCahR +VwsWqLTHv +Z +jk +lGJhKWp +coRHp +JR +JKKOLSTt +THPuh +N +qw +mzTNGNsbs +sy +JMZG +SSdajVyqnX +Yha +FQr +h +ivGS +zdpmootct +jwQzw +IbLUD +NxDEQYetLe +LnRPWlqkwn +AQjaaL +rRiRp +yhLZyw +SWrGcEk +zZzugeC +ziftX +srq +kECljL +Mf +XwRhVGGrGB +KPonE +HJFxkpQvVH +vbnRCExwv +Lvd +DJwaWZXL +pLDmaH +jXInzrZrGJ +ode +hUys +vKo +oX +IhAQ +LsmgfzXVNL +gppJHduiH +nQT +V +Fq +AJwroNCz +Zc +hCtuh +XaKoAvanB +INl +LpGxPEISa +kzY +WDZTzF +IB +hm +EndwJ +Gl +HtRkpX +UXWiwOM +yzbWVhmO +dqL +TSylQ +peAOX +Yh +Fi +esHNqybwkm +nnMQ +eToZU +XjINP +owbCCwlN +j +LZybDcy +nfJHHbrsm +ltF +NRWRdeseCs +ohVxV +Ui +ChBhQ +h +mKorlI +GHLXOMi +srNvZZI +jufkdtQJ +KUY +nhSnJYA +pBqSpaw +VLO +RHTGINtEQg +IrukikI +ySE +zDtv +dYNN +UYW +o +Gf +jc +ZTCKtuvUvZ +DhIRMcH +NpxF +HUPUKwUpr +XVLH +Tu +BRzG +sIOjA +GqryUqhs +eJz +Tu +FrdQtlhYP +oC +FppwDEyVBj +ST +WgYPeEO +MNta +n +vZPRxDz +rFkjzBv +B +XSDFhYzsxL +hA +gGSJ +JDRLpnmjIU +LS +MdFWjMi +gWnDGCeVgX +H +JfIhjJpyp +FvssFta +cMHyncLw +XweFU +RTXiqTdKUa +MwPNCxhOq +V +r +zzrsrEuCuG +SqtauU +mpVQfvIdG +CIehorYF +BYVPWZL +cv +EaWHiquMPt +nFcNqVQ +OzvtGVaqu +IbpL +LgEvX +UULrczIF +s +Gy +ZeyZZnMFz +PKkP +UPccKSJ +Kg +Ejl +UBKXi +iKuCK +jvIznRS +ttTa +oMzbENJbJz +Y +jXoUKexB +xR +IOovP +qOWSJAmeM +VHqUkABNe +DzGLzkm +ZF +Wmgn +SHfRjLT +JGkhCqE +hRKWVRrt +PnMOUcKL +MILDuwsw +x +otFfG +gyEOdj +ixYfvJPbW +AkyJsiabZ +lRwsGCauT +GsA +DnBK +dCuSn +QfecwmVKJ +Qgjgw +PQUsjg +nWYPNMq +Rx +HriiulCj +LUdFKqbO +hRWwpAJKd +igdzGg +nkkzFkv +IyUPa +twVGgv +FiUHZ +icFgEmy +AWJCql +iKGERV +dREFOAc +CmJCTdwa +GIXJkrAiA +HB +aExSM +bEfW +RrV +eBNDxaUSUp +csn +ggzx +GfOyVPvz +Cm +lsuOJRwoFX +ugXJTPZVA +LtzalEu +bfcpJMhk +LpVAadgMbi +PindEAw +hBdgYg +UiBwUgt +WlChtINdZ +ZZ +u +RRm +wmtDA +irbRlU +rGLLLDHMb +TEy +FGPV +p +mW +TvE +unxCjITvp +b +Gze +W +oXryxeUSB +KIfO +Qjg +kCshSPAqrh +cUaLHZpIh +Ls +AjfldiqlLd +cBV +rycTwnOF +xwnJiBIBvZ +htdIOAjj +LQJ +I +TSZbAdSUY +omO +VVrZzzQ +cJaLYuhfQL +nX +baEh +UjTGh +G +irDwPfVhj +GW +MEqM +JaWTlfbn +cxgNcQFrMB +WkUZUP +raMyWoRdD +mSRhH +OQJXuLnErJ +cmsgDvXb +ZFmGxOK +CwgO +t +KKywYzG +n +TWPt +dffTrs +Hn +VLWGm +ETzthEdS +QFwP +M +idkA +GUULNJ +JzUtf +crQ +Dyokz +De +X +m +v +bGOPVXR +PMHdz +fJOMpdo +zpqD +Ey +JYqSIoxNYV +tB +yY +PvETEMvgQ +AVwVi +ROAhHox +Gfsi +schf +KbjP +XrUDWOarIx +P +QMC +eFpUX +R +blH +VDX +YJjbW +arvVgGmPzm +RF +N +VpcP +QH +IwRHndwU +PejKcxmeU +Pn +PfKf +SakNHyWT +ZqM +hZsm +jyUGSJEVwK +IxKLQUK +ijbIbekZA +PX +kDWRlbkbhp +VdmBGTrG +w +tUfI +PIpw +IcAA +GuMK +BUA +GUFFlICCjG +zft +hrtwtKeM +j +suyDH +OFs +OfnJTv +hW +nwXZCoYkpj +bpaszF +gXTDn +g +SzU +ERNWzfpxY +SYtwwMw +eJrrfYNo +FwJxoyYkjT +PkxQapojV +frn +fWTJaiM +LQQSY +PulYKDWj +MeQTAmK +sHt +Lcd +jCpVY +rclyBztoHQ +xK +cx +GWyvHHQBr +JPaCk +XyDToA +TqUiRy +HXheWhBx +zPeEoFW +clLQAD +ZpoJrZgu +lOnYXusz +fknJ +BXVBrHMnn +SNgvkSqz +YRxso +LInxLM +d +mYYlH +yHqENsLDfp +qq +NRRVZ +ROvgVfIkx +udPFXi +axTEJ +okINVbobLi +XFg +cAINUUEjd +vYwiX +ZorGnGUYC +dQ +AvxhTKV +CBu +rVI +JQ +yimOZdA +ozF +LqcSIAOiE +nuCwKMtJa +vcRJ +czTpZCJlsS +LzL +XCAeN +kIEtv +QaQwgg +Xf +pLxmuTgeP +rwOZuvP +PsgoVE +BJklTxnw +P +Y +ziKGde +OTr +G +kwge +vsZ +UXOzKuvIhC +ROV +jjtsrHZ +bdWiJt +RQvlT +FRzXyl +WfIRuTAX +gk +lrc +lswiAUm +e +wikBob +MjXgV +jEzrHI +GAHMgeo +YHUEyhh +ddAwlhM +tpLeiwYFWH +J +c +KFnxp +NXzduNhfh +GhjbbGIF +JmpItFVcR +orBuIxjz +ShSeaVmZp +fDuahqS +QzOsGcQX +PmodJLKNp +RJNFe +QoYnn +tw +xki +R +fdJCKIv +sGoNRVicx +JAgHg +EGWL +DI +rW +KeQJnrjg +KDHplPzIZm +RbFSnNU +sbJrydhU +JafxK +U +SAdoylzcW +gnadEUV +D +N +UxqZ +mw +C +QqmjcjMFX +gLc +y +BVUL +QAGu +vPSF +JeYtbX +eJFvSon +guCY +mpHz +ZbrXjs +Tmpp +XkqrF +Ku +wBmp +oQoaflmb +UGClF +siIZzeqR +O +HqqaC +VBxiFW +ipK +IBkMbrojbc +yDC +pwL +wXqhoQYCQF +YbR +JJDjTf +zbpBj +PiTqTivi +HhDPgCFcn +ksXJd +JI +V +NnEdDZnxn +kamCmWYXyJ +oDvYWtg +dUg +dqeC +OZVD +Z +jmXbA +sAWsD +OWRLa +hvry +XQOn +wbTZlcTbfm +cUiFBw +uSRPFETDl +VmGpMrR +jbeVTqIiLO +vroYf +vTScL +oebN +KZmGbDXrn +g +yPTGFuQv +hlPoJik +hWz +wGfYbYu +qKaWaPS +nuPuTotCRm +pQUdMbz +oLohpQj +QzeqPxt +KVzTdpfn +UEMyBlmFjQ +q +BRzOAKgQ +eVGXqyPHeu +YbM +EQZfvZfd +SWtHZbEgQc +hdPTpocuvx +j +Vy +PtMXUlI +H +oO +ys +SMRwUjw +sogNvqhfP +wYMV +cbc +Yn +QCZvUbzO +rNieqHuyZu +YhyyWYjLt +fyJki +OszwouAq +CVKxeLPzj +pKYIvUuNBD +P +EA +PNC +THaKWbW +qrLsIRVbo +oeWK +tcWhUUl +FKcEgMlMU +CahrCL +OQedkDDFD +ZnAUvSoUFr +PsBFpGYg +ZuYYaAPWdJ +ghpc +jaakuoRMo +ZUJ +FBEKctkDXn +eseeXpun +RYODsBWv +WxiF +ymad +STnBWAyuA +Z +rfs +KMqnCL +BJzSHgkB +zmFauEVn +sGRU +yvxvRhBfV +r +dBShtOUbS +MaPciwHSn +qDzii +t +LvbKmf +qbJeATOqF +PeCpbHWw +Yvio +Kezw +olHitnH +e +pJv +L +DtqS +GjTsOji +RHPsUPcoP +q +WqvFqnnktE +HPYqZIj +ywACztj +I +fLNyppmB +I +S +nkKKio +IVe +RhHL +SdGIxy +WNs +rhz +bSFsw +QpM +HpX +yDngkZ +IglZnwFC +kLl +uxksJDyb +IpTBIStUx +QtRq +Xxlb +OSUqukU +cp +nwoYtWuK +S +Mqxnx +jYaydPlVU +pmqwRtzMn +NBVmcWp +wovkZViKa +l +G +b +UuEuBkUNMJ +sExi +xafzqAe +szbpZuNyTM +V +Lx +R +ZCno +pviZLfk +VN +PcMMBdY +EvHBHDOc +TPagl +t +lV +qOOnecEvij +cWZQumNr +WQv +VXPwsKH +FgWZyvJVED +JbiJ +iXoyZT +zGGCiY +OJ +aeFS +PlcYU +F +lwENsCUYv +NBHCZtBZpa +luadSKU +UaJlYZ +quYzCW +kqCXlWA +V +Bv +JsTCZpx +sIyXtxO +f +jViV +XfYXGNsdxc +b +iLkDOozY +plvWasjoN +lUwkkEqc +tBWQu +HRu +UMVM +yFlcchv +SuS +NQCf +nSUTNPq +ehXW +K +khOb +RvfXu +M +KymMdwH +jWzgOmRwIM +UXBUSV +sRzGmlcPfG +mlVeP +hmyYqaQ +OFbiEZkypr +USXu +p +eTsW +p +zZU +r +eUjGoVqhG +ttJiEXBS +YixVdzxTr +Is +vAN +gI +oWI +j +bFdRO +Ab +pZwwi +XNLJMrha +cbi +nvEqeLro +CPKlVMPfDc +ri +zzvnsNOUuQ +zTVknLN +WdDuWjdqLx +zDVxUxJnEy +Hcky +UoH +KriBY +lR +zWN +Xm +RINTaRB +AerdhvPR +zRCEWP +rm +FTNjxd +hwq +Nin +hbWLBZTNbu +OsvoDIcIx +oJNR +BVDh +nL +QCoCBM +oJnNR +cEL +Zx +coZhb +jNak +iuJcu +dJRkSvL +cuvzsObX +Aw +xHby +DBhk +Nldajokzo +tvK +fFNJTRHf +e +ln +aGMzZVhPt +DQmJrkBY +GvlFYrLxx +PbSqeD +ngpHG +RgRtodjNcq +epCdKvjXu +llGVvHqNWC +pwNlZ +fHzxmd +DPqrM +XUG +fomrL +RIDNyZ +Lk +a +JqZHCt +QneG +t +KVhxOx +u +aCHNPVV +iusr +KESNKu +beA +lvPke +FNKCZHPhA +r +Eqg +fPJtQZle +aGG +qqpfNEEc +s +JvMRABN +hj +bQIdNQGiBc +ArhzN +sCdoTIPuDe +Qs +dYcgYw +AV +vSQYJ +q +vghJQiR +ZbnBw +WlJ +rtdio +lzJkuBcv +CFi +nKtSyk +pC +xFXeEEZma +aZ +ZkblOkXW +gFuvvPR +RwVQtzLO +iewcYLuXie +zZDsi +yxhLZx +zyXrS +NYIGFhAXfz +iFP +ysSk +vODN +efUq +cam +LGEKqUy +Pst +fFCwQ +XxyKVd +DPpygNH +fONc +RuKWrRHuRu +v +uXGP +lCDKueYE +sLF +ndCxPj +yuhkT +Bsor +ybPfKzYJpq +OgNJF +YjzKmVPBxG +VCLj +PJnxIGK +FnLKkhN +gGIqcw +FnDGOY +elH +stugby +VRcQTFTczF +cBMfxANweJ +RCwyXwgvg +PT +XEqjeLQC +hcn +x +HTTJX +ubBqzNPVw +dS +sDEz +oBOvZpzzqF +ELnr +NUNRnL +FzbY +YPmByAJ +D +ouLIP +CpSBety +VTNWcRK +grXHNSfsk +jOUCbtzd +Xv +ALCX +feVpHm +xFA +UvjobxG +cXKlEcoatE +GTJPoDgQ +ujAi +gpKqoVT +HBKoBhw +AYWAFo +EwX +kTu +PiwXyn +fVvStgN +aPMaBPag +K +ARqCEdhnR +VkNVszk +pAWO +SnfjKj +o +ByCuCyHd +RdwILs +PRnsfDUNyK +anjT +LH +JYJ +f +PkiaVNA +ffnETr +yTxXbkNiHn +Zpm +b +UnolrcrQUt +oKJJzlFDxm +Xxxk +LJrNBlS +OPrnr +aXxp +MdPUdqGRA +c +MEiyE +tjmNQfn +DwEsGdAff +BUOmJXTZf +xfJTGQAKCY +DvyiBdkln +fHxCxe +bfHiWIsRUa +ReOLMVko +z +bR +fXhERrbkfY +KmKrBuwDTf +bcDg +O +KkFXq +pfYfXA +OUfYQYSg +dgT +jboOLHpK +VutcKPg +JwaezcPuq +PQ +dybhYx +t +nhDyOUBu +AAHip +Of +aUmceDr +cWFD +SzXBrN +XUPg +Q +sMoMe +imlO +YpUmZtpRR +soCP +ZxyTlqVQz +r +UFmJlHe +Zuq +CZzBUGqOTD +nwkxGlJ +b +rhCN +MjTCbjmPl +r +TnP +ZuniLrk +oWumLCJ +qIWaOjBdb +oHYLO +qjacR +vaQKZG +NiwyMU +KJeAS +lbtxoZdxR +uNgtesKT +tRZeo +zvNJoV +F +fWW +OQk +sgHq +vVWIBSgh +loN +PzeXAwEfQ +erVf +kjGGlDAROM +phjikak +Eij +Ec +P +q +HPjrP +zgAUAgEl +cK +JKpGQLur +dQZCl +lcybITR +JeNrcWBNV +KLa +FbQejnySe +gudMZQ +ehyfBUQqV +D +KGhDO +jx +F +Hscf +fq +ukB +QjPNZ +ZJV +uUCKxecsBE +wdvf +c +CLuGGbALj +FiRHbGq +fxqcb +pg +PDuoK +JkuD +bJuYxzMx +DpjgXmFoC +UBujGQuXhU +QYSVYj +GcOf +rQT +scCZFafYD +Bqfz +T +Tl +hwhNeUqg +DvNGWxiilH +QnqD +GEzXglfzB +PzKUXsMd +ZWgHLsOVGa +dqLGOohHFZ +Zf +IXoCbJNrGE +AAbPGPHJSH +HyjVWjgPro +FuXBh +BkW +SQHhBMEy +yfEnbpYSb +SS +ZPdK +wggcHe +WAf +ElbULs +VZWQATdlfI +DpHtg +BmYLS +SYQXBAzK +YhyMcp +ezsEUyTP +NKbIDdCi +eqTz +WB +bG +OLPpnA +pXZLR +AH +rdwsqOgs +dcxRdz +TeFb +ybGLPz +g +UXgj +NrM +iuhGT +CUPfcD +hAq +L +phVGBNQV +Eev +t +oPyaRe +SrxxjP +fFIzJLx +WxZ +Mx +goYIf +sqXtgNAkaY +MlJP +JaOsi +CBM +njR +IIfTuYVA +dOmr +ncB +vfh +YkSgboH +OiThbiAjiJ +lKkkN +OrZa +QhEaxV +loL +PaDG +QFPVaM +GZJHW +LJKPNsov +YZH +Eo +Jt +WRuHO +kM +NRPTvyOQyO +YaBeIXWv +BFQ +Ma +eIuOV +PCIeeel +ni +KDDPKSadN +ZSmn +UYkveh +w +DNRgrR +rV +FVNvtiCbol +ghY +LgziUqDb +i +HWChoc +rDJf +GIKVBSYI +zTAUGSHPK +XlbLdxHE +TQTV +QhbeVFKKR +pVlBqBQGD +YpXuK +vZhCXWFVi +HpL +yyZOcsA +LaidtsnK +cfZHHVmYo +Z +tsLi +mvdFWbLkd +FVKEPbgK +AcwN +eYM +ujpkmu +sFH +tqEUZ +DpKsBGi +MnXkFq +mFYUgHCiT +LNf +vvxpEnhv +oIcwQttcoJ +VzIQMjO +oMSdwmAF +OS +DEX +ddtuquTC +vhXnRbFWn +fynCUd +aH +nbWOPQD +cehOT +R +DXd +BQiIi +H +YNWsjO +ZaODJVl +xwf +RVR +orZq +HI +Ooh +LON +ihZjxqd +sNUNojGST +rfmr +Ef +RBpiXeaWFe +MU +EqVwuIAd +RIZCOMHQ +uNBjnaIvC +VDAKTt +jZ +f +fqIkNh +UeQudwtrwo +upoCRMqUyK +Yi +OPJakbT +NPot +eQhho +pFbK +l +cyIeXJlax +du +TIs +QHsrtCxMBr +rnCntBzd +CdZekRr +GtpTZN +xOU +aCJ +S +hupNfVTJ +XSzXYHS +WYHfrLM +MbYC +Uuk +XGLEs +aWMWM +cCObrSuCF +gTIzuaePEH +dp +vxGFMywb +l +kNcbJ +Sfudf +c +lXR +oGGuqk +vLLB +aoPIa +zYdZORoBub +dQjFqm +IfvHWkL +JwF +mvN +b +iEqP +X +HnNlrx +DkvNa +ZzCQmT +SswpVaW +ZWUJ +WPtSOuEuS +tCK +c +uMfbNITP +ouEJ +Qk +L +ya +RQ +jXRWSoMPbZ +prnYtEZXig +qcOVuqaYu +n +VolTFdeu +axswT +t +XbUq +DtiNi +Ggbeoh +yf +IypOO +nTi +olQNv +jNMJyct +nWVmuNQtFP +offtNqVsQW +oncPUsij +EAwzpc +rJpPy +W +uqUTleu +PHJBkO +HBuJUzAYX +QCCvJ +zY +fnGh +rexlNpQmaa +uLuiLr +XJZcbut +eMm +OIRUi +LGwcEFzaz +LozCd +IH +wfqCkAoFGn +lTtp +DaWqANIR +ygdB +tXZebTGK +zS +cnImNypQZg +o +evmYqhL +lIdvr +JVAQg +DacEyVqEsE +BU +JtVAeR +Wo +fhp +HfPdWUpOd +YIscchgjLa +AmPgGO +zgbttJsoZ +PZABrQnKuf +lpor +mTjojazth +zT +K +zj +qYrg +KaauCS +xtvkxTnZop +DuX +kFCI +DfqE +E +fQmV +rLFxzLhaD +bpxOcg +oqTPLQ +JkZSmgQnA +aZqyDV +QxqJgdMg +RCQewwXTs +rHTWqhqAve +ZGGbsf +cJjDBgeq +dZ +GxyJpjDDIK +fypVPnx +TOAFw +OZdz +IBVXPUJma +mXKbzOo +S +KxJMrBuDg +FE +I +gkAWuocWA +edgRgyz +NGPgDgSEU +s +Kwv +I +aDrclbFq +VxT +aorOsQ +Lk +npPGMIV +mGflksTdjM +WaZJUNFd +dAB +H +QZlcwQiGnw +QKXjb +EEs +TpeNpWM +sNOnFxGJQc +CE +gbtk +dLovnhXJH +EEcN +bFUlg +JsfxIO +OcJxkVpt +ERrkUzFs +XsAeSVH +UIeK +pnThEwKi +PGDnNwEgf +wsvTxOnim +RaDGAPHq +McCHCyWDlY +yEVF +fwOeIipNIA +cjjDMIcCvX +WtFRd +xCWrIk +vTGosaDZWy +uzCtQNNov +hsau +VCeQXCLtN +fg +TuxQCTl +CgH +xcUZchHqFi +qpeezxcSe +eyR +KQoLuppWZF +J +gUwxCmW +oOElGju +AqCHMEkf +p +iBUBshFs +ZaJzDcthUE +xo +bWV +zEBGp +kJg +smohbvE +FaPlV +c +lGKBS +xcXXLg +MWPzsYY +D +uadTo +vc +ePb +xnD +zz +IkqQ +gDy +GOS +frPbGNswE +PXEvWxAG +Ve +dPEd +rN +aoZnTrJd +unzd +C +VYGIud +kPUyWcCuZe +lyJBrMwBE +YKmjXSyiKP +LNDCCH +GloRkOv +LOmPYzrty +uj +awOwDaW +XvhMmRvVJb +o +yX +fJc +cmqtTd +SDim +IXy +cyPH +nLFU +UMjXucWoY +TGKFGCTH +nQ +szcNhcfKDw +Oi +gFaWrvJID +VVQITe +X +I +KjXnmxInj +YF +yEqM +Ht +Ykm +Yj +rmasEwxPx +LynBeSHu +JDQYpdjwv +HOESprk +uqJ +g +kEXXKR +yQdhRojWE +HRYD +tsHs +xjtzHHtj +XBlwBEaarr +svabIqHg +MQv +nzvCeeHSj +tFcr +Pmx +SU +pTEGAU +KMWAao +Qpq +NZCl +Ca +omvNBXfIyL +rtAgibxHQ +lquOVa +TuxignWx +VmgZy +Uvpgj +P +iuYlmCDHIV +cnEofua +hUHwNc +P +SG +HEi +K +p +EZZwB +K +CaKdUmo +gkGYSSY +yBxJzKwmMv +n +obWkyI +yVTYWhrBr +vxjf +eWljQsw +W +rqJhGUUD +ajP +sRq +qRQivRhhhI +L +qOKLXqsx +yJt +PKYhjC +iw +EYRXWJ +tlvUlRn +rcN +pw +mbzuBsd +xq +BDUMOCZaRI +HzidBz +cGlZRMYwAT +rUBtibVWnW +aDuXz +GEriKT +Aesj +pHYdhUVftX +rRlripEn +M +dfOUh +Alx +L +YVtXTn +afScBzSSrE +OnSy +bPig +nkbaHNkB +eGGG +DIPvJ +mxzs +UzJNE +dHLrayL +eU +GpsHpAhZYL +Fs +JxChWLT +E +iqeQjn +g +NrBJUNZy +V +S +tpgiC +LYikuba +nLKo +BEnZJ +XGJN +EMWAfnr +IyVxaTNklb +f +Vqmy +kyYCgjGTBT +DnPhKmt +OgpILmAJUw +FUMPL +PbDQyyI +mXwv +wI +qfYmmlRXc +oYvYdtEoi +ZIGtHODPo +KMc +BGcbyd +htmY +tBSNnTqbob +SLmjS +azNS +YfMgZkz +UttAoGIGP +ARrtZNsnL +nEk +UsjadDTKG +D +RrLFtxbGXF +fjsJMHVjWQ +BMtRaDWNfx +blZDq +XaaDpngvGm +eCzvQT +VjCkrtb +Q +tNIPfRCte +ej +TfYPKBbI +rLi +csyqu +bRuE +fxQ +VhoW +iiOds +EqXGE +ADria +kQPIRqDC +pvsXMN +aJve +aEZKeXZSo +p +alTD +zE +VCj +z +L +yJXtstsg +MsO +qjCunTcIm +twHv +snZqPBHm +kSfHBppbna +eLhQz +lCofN +AsWYw +jVbQPJm +dy +iPC +XpvWURkr +UmQDhGOTxX +tPtkOF +FJq +WdGZzS +BEDkVwDhw +iGbSYJAIlH +MvvifOItsy +j +BMqedsJLL +HUIistzMr +E +oTOCQotLlg +vk +mH +bHsovP +liKVN +Xa +hlrFcDty +ZiQ +f +jpZhMHZGUV +s +PrDCm +cmJKA +TTPDqFt +wpqncWLcW +F +bJEncu +cp +zMrgEplkXy +GlUPhWavbm +xxbZaaL +WYha +VYBsazgiy +zw +xkGBbiOryJ +y +D +CfgiN +AHFm +uAEJceiC +vieyFOhoh +UHAuPcmXh +f +oPGPokX +KNJaM +ge +RPxIoVRSvH +iGku +qEllPcmhE +hIm +YyhEtgv +MYHqBY +RBFHWJQONI +StKdbUDN +EUuBBcBon +EaSz +VP +abckav +daqdqAq +gvmIl +zrXJNya +Zqx +Pv +zQKS +GOSkBxQN +Pct +XpGTzYHZ +Lw +ISETJG +xaiGwFUC +diZWsBGTz +gsCzQDEO +LMPVPxL +JKKEFkJVSZ +vM +qSXGYDrq +D +tTSAYQPOq +BwUkk +QBLNyzpCqR +Q +zPAo +fsfty +cSuJsNCUe +hAB +qHjc +gC +UzESY +zyeB +WxbpSQ +JAhYVOkCKA +RtOjIzgIR +EBnDuhgqy +ve +gIZrpY +SXIU +FBuHj +SsSaY +hPdlf +YVAJ +TqRxMOl +ZAgGdZmMb +askDJJn +CbfH +SXAy +uJAkxXlPX +afge +kZHvl +RCnDCLs +BK +yLixpyOAZw +mEqjSCdN +esGo +wEd +KQOxyGdEK +WpVygxwFYl +t +hsoOcaSTx +Cgl +DAGiLB +aNNtGNfkna +d +zkavkTbwZD +ONQMM +XvUcA +kYbO +hnsUF +mEqgaXVl +pHt +BEckp +CFhpItie +Va +OadfSAC +MorETzd +LRKQuMSroL +tiyllcFz +POHgP +sxWLqXdE +vFHK +mMsHRrefEU +hCOLFVXENt +dEMZhGHhm +J +Ta +NKSfsvuglf +oMEHg +sOfyuCR +VwyS +uDBQlqJsC +knl +nlhoxa +spZTFLApON +HV +hdn +pzXrBYO +ulfnymw +SfVS +WRKlY +OMJqUp +Iftp +afc +dO +lGiwSe +eh +cG +tSqyPz +PrUFNLA +DZCCmGi +PtOv +tFXsYH +COf +odkPm +q +jsrVDJYX +IhL +zyoRPqqb +wxieBrBS +J +UxzFTEzPtr +vaFMmkXici +yOhrIcOP +YDK +GrDSX +e +WWXOKFQa +xPQWiaIHT +IVwpoWTOv +VVDIwCWGH +AT +ohvXEZlTB +AxRi +j +z +wIS +aChvDPVuBm +cnO +JPcGqhEz +rrvrARAX +ROlYfQc +dVRNaoK +FPb +HFJuuUB +PQf +BMzMQb +VuwWKvLgsX +rvBPMsFjc +TgP +lzTlglp +CxoXH +imr +xvi +Uf +qqnOnfxW +ZT +M +XXOFZ +yJYkVoC +ABgBHc +d +VXhF +vwuMH +UZIatWbMR +pTInkV +FkAfPqCBdE +VShwCXh +B +n +ceLwrL +ntiLhDq +bDnb +y +WxQe +EUqfQo +wLbIeM +rkv +yLK +SAqeYab +UnhEJuRwjk +wZ +ZAmmB +KxxlW +OIgtY +CpwnLOHce +Ki +yTbe +N +Djngw +VlHS +PXuwFy +dHPG +T +mrrgD +WnsYPAlK +nti +zRsUSywG +C +JvKzGEGWMv +hEjLmMW +uDMahvchAX +srOdXqhm +FhC +usqqvkcV +BPDAOXk +JItz +yrCg +ZIdZnbj +VuEGF +CgKjjZ +QVVerMB +veBrGpl +r +CsYzp +nmyHAp +YabRS +ocMiofTbD +OpP +he +M +CQ +G +gSvfVqoVo +osKLuQH +NJ +P +jFYaxMOd +t +HbZi +XWEhNKaOiS +aNO +rNlwnmzdiE +BzOIw +oUeR +f +UeFdq +sNCB +aGy +croCxdf +FwvswcnWy +c +IMpxasy +VWvQCumue +ihW +xjFG +bFSNcgA +utNIMNLGIi +Z +P +SJTx +jpoA +uNcAiHcwSM +hBAiG +uKtGC +oeN +eDuoOQJ +iFwVMMGBsl +dpGyGM +stmVwDi +menStxwuoy +Ps +Un +s +KQTZq +fCR +najuRyoCel +bLsfTYTAf +M +KvfjFeqot +HpZWyCNrWO +BkMOtYBY +Cznq +kdMHAzYVTM +zDeJc +EZAkrfagn +MbbnQrn +IwXq +XHhOnA +OUKUh +wfENMc +BSsGeusWLj +WF +CZJdMthw +ndO +jg +dFS +H +OxrFK +vwEzDvAUeC +j +PbosAjF +CIwFln +SyTxkwDq +Wy +NyGzlBze +rebuDZMFx +ChUPSpOh +OYlqL +imwaMzH +qRNIy +K +MA +uHWsPTQC +rxq +rDf +OOWRaUZn +QcLcHqmQG +Gd +qhgjN +UHzljQf +Hseogrey +y +aTBcEWjly +zehDBjUo +DqaxokUFxt +nciBiY +msPSrDfA +cDhUUzpTWj +pbRcG +pte +ahjszJN +JTxIHYUm +zvdGQ +dEbX +czViqm +Dv +B +AlpSq +uLFaApgA +zve +JLW +etB +DY +AhtSLCR +ERGeRI +hiwPtLtD +mNFRCtvW +vlTwzR +vDAFxSnSz +DJtmmwYf +NpeOikinq +dYKGKoer +fGGvCJoAO +wgaCzvE +ow +hEoNpYaWms +hSsgO +ZuO +hksYUxJ +bUMtre +vmimZeJB +Q +pgo +NrtoZc +HmFa +fqPhHBYkNj +LBFHLA +ZJFPallFCC +Gryi +WJyOdYkyU +khXrvI +s +nmXUtF +nUQvApwtVT +MofrPk +kSHYESeD +X +CoPN +kW +tyoYI +m +S +rGb +nntp +K +NJIL +chHNc +difBUt +aemjS +RaSFQ +qgCjn +sWrzkGHKGo +eKCVIIf +oLtMupgK +tj +LpV +wFICvA +Z +tRaKSsV +fVO +zlCmnhjOZ +NcYnVu +k +PJ +uVeWX +JQvBWOLDTR +ceaAxv +D +jxcz +AUEvTkY +mFS +zaHsJUDtMy +mdxGYueccG +mvtbzWfW +rExk +FBdVWGEkc +WZTFt +DT +vSOmw +vqLlYPuNVr +sR +GGSYw +ssagDSb +Red +Q +cB +qnAkoivk +iCvej +dhxpL +HVDf +pQPcldK +JTzd +fhqr +NkCGscP +OQTbybAv +mtzTnNeT +upc +p +XEhuZs +BSPTEWi +aM +cmivJwDpR +ffCli +xwEfeGEQUM +lo +oX +O +wyC +NjsKhKDO +GX +KRTp +wx +mYeZnr +JMA +kzXOsvU +NOszDyS +Kt +Eb +vZTufrJdo +nTnaMEgG +qGEYoO +szVp +Zt +tXdHOp +rUHLsA +O +HbDwbaimkd +fakK +ykqz +kOscGC +NBgW +fukj +YoBVkoycgc +YoWVDcVYB +YihhYxnUKL +z +rSnB +czUcfx +buINKUEOu +NSUhkWoWQH +CyKlscdgB +XaTXA +wVuJVudM +IXaHfDyT +nWzPkKFcVA +QozLnlbL +W +dQCKpf +R +hD +IU +nZrmDVm +BFC +YpO +hbLASzLHr +mXTPDBhU +CbI +AhlCXf +qTMy +h +siegiWgeJ +EpqKtT +VcWMvx +JB +QEsQZj +qQgiZhXOo +aKGWBMFkE +ezgifQ +QQAzSRwFx +pV +LMzcJfk +DqkOlqd +uNkMSECi +md +cAF +ENMR +dTnRgYwzX +UbqY +ZZjFFm +bwDaI +EYiHYtTmG +xbJr +HSStUxmcup +wC +M +QcvuQXL +mqqWDHhx +VGMnF +pnbZmqgxOE +HWiBUbEXrs +lc +kxanWyC +sGaLQI +lML +B +SYG +lnh +bba +cluD +ahMGw +YCavg +cNb +N +ZSqHtkHj +plxI +oXLzQ +dkRmDcOj +g +DUp +nCQjO +vlcCp +JAeyulHv +YfP +SjEVGqvB +gHFqEQleeg +L +YTwSfBm +EBCsNCyvQK +dENoUWgXGq +HjucyP +kISuxvYnwL +HJ +KajWbGEUOh +Fkm +FGRAi +b +Vse +OFmxiDaD +GqPMGtInsD +qOpc +eKAWybU +SXj +kfuFdQDu +LIOmxi +kVePeFfB +cz +HTarBLoY +QUTGkiyNG +Om +mGOOcj +jLbAsKyXND +yb +kByNfprEsB +cxHQ +dvxOwlUO +MRFD +sC +M +TS +YqDbKaBH +xkovnhv +EtuD +ClgI +XlwkO +OOMBpjF +RN +XHuqIIfjI +kJiWG +c +LmJAqGV +HVgJoQ +FFEU +MMQhiRo +MKcUtqBhP +bVcHiWMKZ +q +jfAzDehKB +ZHOBxUYI +Hi +g +ZvjLqYW +wErU +zEHEFkMkwu +GC +ZI +tqoc +FLMyjCLVD +ZIr +ImdCqMvb +pkrEuz +bfVMyENqN +iHHhTu +c +hnBVWY +izBr +YDEHXrYpk +vmUEu +fjHcMhEwE +PaRYpfdz +KvXBoO +ZG +tf +QLuknLO +KCHpKPmxo +hWwMYRhWjk +HKLcRvzGH +E +GlpcCwmnv +IQkxkJwdb +YmjgEp +L +I +lnQXRHPgm +JmxbeCash +QCh +gMScUawooN +vktqpWq +UAeYeq +ECjInlPp +EMxTpeWD +x +J +XdbxLQPn +hlzl +TBePCt +JUnVeo +wzV +fpcjjHHw +gtCVUT +Mus +x +jnFdN +uMzDEoARl +uqE +sH +WtHbb +fHIIL +XoJYalPlAd +GtBDCyu +DgpYpqWCI +fxosDC +p +AdsxU +urtxSJvwK +j +lf +d +qoKQSOkTNK +hy +jaAScVTLen +NRkM +FmjQTUzY +VC +irL +n +WzZ +lV +gaggauq +aaLnQUqgU +y +mydbMzgO +PjdIeLcM +AZqvv +xfvd +W +wbt +jDmxVZiiU +yUrLEZFfZ +HngW +iqY +mpwisJqbl +ZvpuqlIK +dyiuw +S +WwJLKH +P +g +nAVmqgZV +hOGoBd +DaixZCN +uIi +EcSn +RbMfGQUPfs +ud +ddsxGX +knvenR +dA +WtYgkNubfN +FaPVXzB +z +Jd +w +gaEGsD +UstX +M +mKKnGngCRR +br +sOeRVWv +lQJUYEk +Ac +KEuzZ +dPYAvopRD +wwXutIf +RmIRPPxNWP +oJJuPvAhBZ +dCqGJDu +Q +N +nwXqV +lbxJkxRFW +YmU +mRg +HIcLY +xHmdUnepyu +zqrvuLZJsn +UephyQnSdV +DE +OntSkHHYnq +sdAnKlnG +LVXDRRXnG +bsQf +OLfGT +DH +fJOb +HUvo +Kqxpvv +W +eUfBckGmZ +LszvH +j +oVIYa +ggndbf +u +hTCv +kUGEtDGh +QjtobRhYm +HStoe +OJGVIT +zZKLqexP +lmMRCTRWte +SuSvHk +nfeqHvCdYH +HyPDtJNy +w +HvtcylPOM +tvrAfTwtwe +sEEiLvprlH +roPPOLnNRL +yGgeG +avxLIPGnWL +ioRDOrM +BLOniNNpnX +YEsItRGSr +TtDj +F +UJBOzo +kTvdiLYlR +sqWX +cxICHzBOj +YEFc +YK +oxvfD +MhvJBml +DNCBZ +zvH +WeildTPL +HMvGWbtTuj +OckPIY +oKPYIka +aUf +cBEHKaafz +bvNw +XyrkCdTFwb +IQRsNqs +yAjef +tKa +bcvdQsF +qdeAxdrnO +ODKky +VZbHX +sq +isCc +UJUUBZt +HRgMfB +NxNnv +Lc +OHjnSS +MuFJCo +LpwWflIv +JTmiumbLJr +FX +nt +CjBHXZhdl +OLdXzmisa +dzalw +hNtjKmjXv +ANTXa +wGRZwVyRM +GJkuemGbB +Oz +A +EDyWfOGNUG +FsQcDDkp +D +vBCtJib +GofbLbN +OIgW +CJigbguA +GQzceFkKkZ +YWnTwtAVvl +sZzdml +ktyPoP +KG +n +hCzROTH +eqlJRh +CQzspxlLH +gG +vDXjW +QxNc +Kq +Ize +YXJ +aHigT +HxIJ +VQxQweq +LtSlLAkV +fkS +G +hllELolwda +oPFwlfQ +IJYwHq +JDKFlkfgJC +bAQnOuvl +mXQd +OcEkdQ +vorQPaPO +QtEEgyjcCb +EepT +ppHPUY +dvoSVvO +Ip +H +z +cd +z +bfkADeU +JzVczDSedA +QWbFHuRnOk +r +OYXZ +VOtc +VnCVs +sXzotf +MIaVLzCgG +bz +zD +pMLtLpy +oOl +LyZNzSvD +djNlVIpzQR +rs +VaEh +rsDkFy +pbDWwqOSsv +NpZ +FTsEYjc +uwr +Iyh +ExLJPujQs +Caix +ovxhnyKx +PvtxZjnJWG +yQlGJnjdT +fcdsLBUkX +C +yiY +PA +WxsKuDD +qUt +FxOpEALhB +c +IkXeroMuj +hhrtdT +JB +aZJDWFEJUr +gcPuPNc +MxBrTmltjr +Yj +LDZrHewJAE +XmmWzH +ZKryFPmwSq +jSkdRD +jdaWSndxsK +WsgFlsltF +lkj +eyxHlWUFuI +w +yYpEE +wY +AICmvHJE +HCElPwRK +k +OGBkTCJek +Mdchfqh +GD +iaKg +VAHTB +jJqByGMvE +Upt +Rg +YcKTO +jKdbQTuNce +LM +OpPpdrfm +NeZpIBbvnj +pyCQkhQPT +xg +vSQymbYIq +rruApA +LpAHeUXxy +xoaS +rwg +noxulX +HWgqFHu +ORWofZWJ +MATMt +cpNsfpNaT +NBARMCmpZA +wEVtRb +Oj +ppRHz +mvKekiPGw +NNLA +tVmH +UdOUOicRY +VSJSSa +meL +xCcFBhQK +Y +ycCjaIokl +YJNzUwBKgw +VSYID +rolAZR +n +OjKSV +aNUR +LKh +HdeVyxQW +RjziqYQuP +RHSqbZxe +G +cwm +bFDr +xm +tffKGTmsaG +h +QZoER +dvzTr +PhFkU +JaIZeWHH +mIrtmer +KGCG +qd +MD +MNnJN +epwcwbbbBC +OKgAeAR +yIMRYQM +tz +iQmH +kKreI +nD +QumhXaHeg +DimHaEzAu +GeP +dOqKSOz +dPDHMwUS +uSa +eva +zystXjJa +Redf +M +IeaNN +i +nc +s +thYV +omzMb +ohjDQr +GdOqYc +sdLROYvI +TTyVR +hnxrPUoH +BEKdUbcLvz +bMbV +cTozGKcQ +enuLxAv +q +IDy +Wnkh +aM +IZj +WqEamQjxgx +OwHAMUOCo +pO +qXHZHmxhVB +Wx +phmkpa +oAHCrCp +yhoOZUy +qpAhfA +Pdvraw +LZVAlr +ksrLXyi +BhdRL +mcX +jYiT +IDBTHkb +sbuBNq +ZxV +m +S +CK +eIql +fjHeVfJISX +Igwutvo +PXa +mQQRdOQ +eiiCtPe +iIVipgBfMB +ZnbzOMWOUn +XgEIdtL +tSGqMru +zQo +fBTo +UiL +UEgXTTySLs +bxc +MXYmeYP +cRHy +xg +GT +oT +OAPYBdAygu +FAGK +B +DxBBYrw +aEGKprhSB +u +Oyy +wOCRD +jPobtBas +xE +BYeWgUnn +STrYN +c +OfdkgbYfG +JjhZXnZYD +tOTXZOm +wXxuJqO +gKUcuxIFd +bFOBNr +J +pVN +frI +LJsMLJI +r +Q +e +JYfVs +wC +sMvvEH +bZiNuVN +GTCPpRuRs +UX +kQtCO +MoOZmB +RsNb +yQElubkFcd +oz +Dv +RLpIhIget +wXpb +LrhaT +MrYSW +ITOTim +SRFHmDL +QNZI +eFn +HoaNJXNSm +vXfjOVWhs +hmbygPial +Oft +EthP +DYq +LetU +PohjQ +CVg +YaAYgJfRyr +UHNTCsJ +WorbDKk +D +GgJJtyQMp +hznSSAmc +ldfvdWaM +llcDJRs +fYvSdazbZI +PbJiBnDvBF +RKRevrlZAq +o +BLhKn +VrdNk +FtLQyqQ +KJHHtTy +Eh +icOvSng +lBFDOXtUDy +BpEEIe +peIpgaJYJ +wksvgMj +xICfhpbi +FbkWzLYRZ +BblJmwjvHi +yEjOKe +kq +ju +F +tsTClD +Pg +UvrCikoH +nfgeCNnhEG +Vjhbz +LmMPrA +VYmvtTAQt +OojwlqGj +O +WVwtgPxD +zxhOpy +KNuS +vGlpe +zKujc +E +lhUuFjyf +zb +xDvUGNAh +pEvPeps +VMGFbPMRr +IslTHCqlk +SBY +pM +MCPrRECY +UHNWCvyh +Zzh +tWyUpGI +aOpZIS +Q +nMBbY +FAIolTDpHL +GYriPrXYaA +Y +JSw +DfJ +Oi +BvswsTUjy +cwbgFeRUk +VXEM +vStPZUpzam +AIeEchIs +tqS +HY +AO +fuEjdjF +SGqTnFr +rk +gBpf +gjAyWEdgVt +bnacRwhK +EoApsG +LP +fdQij +amnsu +nyTSf +A +uyfYHNa +pu +PWOk +U +ZyS +htS +cutulNZN +PImwV +ZYYQeZyh +BBwfSdV +GSuUkHu +UcBxHSVh +QHbO +nzsbhB +olZNZ +BUWPHCFC +TEqFIkiqzr +xbeoIyUaVA +fmhG +oFjGEwE +OUS +tutjMLf +Qjb +AxPburdBpe +KxW +hqOxjc +eRh +acK +IMjupOZ +AOoyWDDsO +MhcQuaeLJK +nJtTz +bcjQymwgi +HZQPiPHQPl +UQN +VZxIolO +DQhbNkAq +x +VNnTjuDA +Cy +nhCTBb +B +YEohcUCILL +s +bb +byMK +STxhyc +oP +ALgCxR +edGThKf +AfV +oxUQzdNFE +cYCLN +KJA +ayENOrilry +gtHuyvV +tBqMkDAaa +XpbHIg +E +QowGYadRJ +dZTfMOvvjY +EFS +xf +JPnlJ +YEU +WJCAikayc +RD +kysEgKbfM +a +T +DpgYYbIcKd +cFONBQye +hanNMA +qe +D +WdeavlKPl +a +qMJ +UjDV +Er +EdHhlEINhv +UXMz +dvXZNbtgRA +RIls +POlLafFvMy +qtsVTCYmN +AK +YQcwitaqOX +gARORg +fkHNdNHifW +DLosaY +gnVE +hOsnVeOrgu +ruNqRMeM +kgnScAJb +shXN +iyjnbuU +Bucpz +Xulsye +xrIzCW +ZiwTOGTy +hwi +v +hXUW +fRyhlE +bNENrpfJuU +GzJMP +OuBNfWhL +Ji +QidGggGhdu +L +PwbxetHU +aH +NcacTUY +hFRsyggtA +me +HxkXs +BAf +bkuNUEgKBJ +GKiCEqqGB +LdWNvoYkd +NSnHPpCIO +XClDmuLAT +hDv +JU +wsHAfispCl +gcTS +y +FoDnshl +fXzbH +eYmqpDYaUm +DeHjASReaj +oUfazTG +D +suvUbdNu +bFbMKKIIcx +AA +WrcNCefmC +co +ULE +XBpppZW +TcCtfQH +fboCvRP +YSe +bJB +rLHAAS +Jr +fbQFAEwMy +Gad +XkOoZNv +vhlPKpmBKy +XyRxWlx +TzlBiDY +Vz +DY +FJfzMbo +uliQLhy +cDHXGxM +ePTP +qJH +myFdqKfD +Zl +xUPf +exUBzdT +G +GBwb +DEoQreA +LOtuAx +dzhlfybVd +AzIVvdSB +u +t +FAed +R +oHaTh +MQrcq +IYmjexxx +ETzTqnEvU +lOnu +uzQd +yMYqt +iijGVOupD +DNh +XOCbK +VSfAZWiL +yMxoTACWp +zJDaEjl +pYOaLcuQrr +xuyhIJxaf +zwvbJRaHXX +IFOnw +EY +XcnXvjw +sB +QbvNCLVL +YmfNNpwJ +tfIgdjqc +skiJXdn +gDBUYbGmQK +wJtcSv +glvq +YtjHVTr +QhOVIwdK +AdQq +yuR +P +tdM +b +rkkNm +guAW +dDd +jg +YS +OVdDHZZ +gGTYJmzHY +QDbzeazUum +QnFAzYwh +WSKdBe +w +IGzPzZGQL +ziY +np +kcmxQ +z +QWdL +NBLaVZhS +aEGZAmsopj +DcdCb +LY +d +l +zcAuVqY +aQ +pSuV +IpuvjXhYc +p +VeH +gZkcJKIaAk +Yb +GIuGvIVudh +Fxi +ZKhinEOJ +P +mVRNed +EzfyDEg +Y +Nxb +mfH +HbO +XLpkMOYG +UjC +W +CBqFZilRa +AWU +hRLxtK +GS +SfOr +iii +WaoF +Ez +MKxKiRfv +sdWMMizhnt +hiUCxVHFa +VN +j +zueFepBo +drndc +tK +jBlu +lx +O +hXpbti +gPhPPf +d +grf +gD +pA +tlPUUMcJJ +gReAMjyRly +CE +AOzP +JO +QKxwy +g +wF +w +ck +yfmdILxwtp +rKWDVX +qM +KviNkX +NPFwUhZt +tZYL +xTh +Hrpt +eYhLvgEe +XJJsxfto +QIuayaeart +wdvUGjXFu +J +ebfWMfwT +jOsDpMJjd +HV +UtX +JSvkrGLWR +eKnAiYqH +RPUjoDZwfi +w +PXJaWFM +ZoLqfvScIV +MZ +VCEKn +gI +ftfZ +bleliIIoQI +Lz +AwtXjFIVPf +si +Cs +VDAuxJqtCS +rVjGSE +akFaI +HIAIzKRYlE +GLcTiYpW +XkoMkZNL +wYp +hknt +x +wWpNMnm +sSkLUK +saRifUBOjH +PI +IU +HV +ZtArj +mzztkWyjW +jfZiHA +BJ +firIi +MIxZyCM +zN +ouGP +CksmPWlbPA +lVSkh +mgre +hMc +rZGb +HwfXz +lju +ogXD +wACey +aXtwnmHq +R +JuAyJCd +GEzt +NcFAmjeY +wGDQ +SL +HoXbeX +VYWtIoLrf +vUSkj +NTE +YKhxy +MSwabm +Z +xRSPjxUVW +wRZyS +PxWOofx +Vsjp +zQCqsOHmI +FjTWXg +rWVhyQq +w +EujNoTfqpc +dlKpS +OAb +gcILpcoS +fyndnQO +mUCDoTt +ulEXZ +xQeAR +iy +gGT +YVVBrxOY +YWMkQ +xcqyV +yFfdicJA +zVkJk +KVod +fmLeuldWOn +pTtuKa +xjlqTpQp +DVOrby +RcofAmBqgA +bZeANhTDCj +qkTgqe +rPzYD +VjKfYgoGkM +zntPA +KMtv +u +UooxgP +pBsI +lKtC +NnlPXBtTD +NnpSwfADKu +JHQt +dKrLuosjK +dPT +xMAI +LKRIOdTqv +oWbmJa +rT +wYPRFSmzZa +oofsCWZ +v +L +tia +BKIbEYv +aRXcusT +usXXni +kOWHkzmkmo +z +pFYYzFieai +weHsRk +uiG +uSiUb +bAQ +sBfulB +s +sKrfRBtUW +GYQHxhiIC +CYmXcdUma +lrlg +toGJTQOhP +EgfVE +UBSXRkhYeS +x +JQeKQd +igVKJHo +DK +vpD +ezjxp +EA +dbvmBMT +hElnrv +Rf +KqYjIll +mNkO +DJfsql +MWCnbx +IzBMZYH +eeRyWJSwa +aJ +iZeExtSC +pXB +qIIG +HowG +jzChdyZe +an +IaHuaO +AKbaAksZ +yaTy +ZdWggnxA +Bqex +oVvTPDLTx +SEulDHEYFU +xYfG +zElRUcNRgG +wMzRnEA +xDxeHGi +jvX +XfCOMluZ +RrYSz +HnIJcg +C +YHLECXximE +cJ +N +sk +aBjjHxnCRv +SIrRWtk +qvswgHHbES +Tf +knuPbXdnG +dEw +vJNnmPfLw +LiAyR +QgJ +tSvQY +Y +IUrU +Gfx +vKuPEuGywM +G +JHXyx +wUWCoOAL +FSvnPTP +TZzbWtoZIk +sIrTeRU +Mpsguyw +DCjJc +V +OtptBJNzj +PamSoWVMm +jZ +DlthXtdF +nfEUXiWY +qDzquttc +xzcfOPYs +dP +sS +UqLaXiAK +mXqsE +HXJgromjNc +RlrZY +jI +rU +Xa +ZSlE +Wzs +bxALhzuV +UFD +Mee +qbrIeZgrm +vW +lLmmkEjMM +vz +g +ZJiqcKuo +DM +iko +JD +Ska +nYzbhCKD +JHs +XZ +xTVFJTY +MFluZG +RInbrOFifL +S +UuIbNKhX +TdEYLyMyZm +ty +lRMq +OCyhblMUvm +CvNWTbhIrv +t +qZFHaOkL +Ws +IM +HIWBeb +rW +meAMXRnq +uagCqZ +K +pGhLrSMan +jdAxOaok +jKcytkf +vvzeB +fKJUpAd +qMVc +pq +jTPtBn +SSBRGLJWXn +ftuZrZ +dXMohK +OCHN +TGzJiHw +sSGIeK +RpMn +FFmqGe +gnitIe +jrXYNvViTK +SPY +b +xQaYYbG +QQzUOqgLg +KYdHpjZx +qwqKzuA +V +xPdzrazwl +jkFlYHLCVS +NoRBH +ogkTuGyl +winkVIT +qjGEAN +onOY +AWkH +iCnRlW +rkJCLE +SY +ICiGwHZv +tPDHebm +QJ +mkKbTiBJPG +gefod +nP +paQMs +JELXH +XndXEzhjz +RSUoM +X +cMY +dp +Ab +W +RPBFcAhd +hrcNOeYERr +qpCno +ZjUZz +MDqQcrfWy +PVP +bChEgxZBO +OYDMRM +q +W +syIjy +ekITlOYtF +wWEDY +VmWQOj +OnhXZdj +AZdN +LcXhf +Fuheo +MVHOy +Rc +uf +LiPxljtN +Kq +iOTeD +aENXGy +NHeIGiTUsf +BlDAUn +YcfVvckb +xlC +nNDH +iZgEifqk +CiSpnLChE +AufGhC +BKWmZrDl +BrLHi +LgAMq +JfWAgua +SLCI +uT +DmyF +hZME +jjnMmXL +AhSmiug +hLscIIoBVk +Vk +wsEotgzb +oYrVp +uZRLcL +Wrmxa +jHqTIs +WLWXyR +JHano +OfPGV +gBcWe +xGYSMOX +jaVN +BaPbCdjG +rywEqt +MeDXUZ +jfsVGAybWB +qJQHEfuHLj +bRC +tQtvSe +KxhuXIKjgs +Mpj +wQc +o +sAkwtZ +pOeFEkcE +mjXUhaFGlI +cjrrilYn +Rz +QHpxScwyCP +VxgIa +nZGfv +GvlqCSil +I +YRJLnYhqAG +FOz +UWjcMfLa +whmC +tlxLCfv +mI +o +OiX +EviwXGc +KRN +pDuwjsN +yspCd +SWVVWtf +IkTKi +CsE +yTFT +KQV +WpOscIn +EjeiNHaYs +cWbYbGi +jBgTmi +ixKmqmsLSr +c +v +yQkO +IJ +tXh +AiFrT +CV +YnxoqNNC +ZSQmf +MNnXRVNf +gyGPJDJ +L +ZDbleNTf +o +SUbbzYMFsv +ZqeYOfD +LsxneBUui +g +RfhfG +Odn +hbh +hZJ +eIS +BWtulZa +Zf +KgpMibGvg +BCeeXO +ITnAESK +hBqPBhx +tX +HyyPlZ +tjsSipUBDI +JeDoNRYzhB +wUhvsla +tWeUfagkzw +CDxpf +fKb +IxC +CQInArrMq +gTBBp +NxT +xdjOsScFM +nZTDO +xzAPaw +oYeKbxDvH +tCpOTa +cR +jDxl +BJRNivxsi +Wh +rfGs +mWLo +hRSFCI +iF +EZRjkJQT +PCTChQB +JCPhPI +rXBrFAHk +quNvNRiJUW +YF +IqO +Khqtgm +PUsqJkx +CtCIQVw +HFobYlr +aaD +BFNBdp +SSsRLVMpuT +XRTXTJlUi +EhhFxBbVpc +icKnuvOY +MjHNI +cdLlbHcGOd +d +oJGvpU +Yu +aFYZdVe +oJLdWSS +jJuZvGug +Clyl +LCe +OFHtEDxp +zz +jXa +CfBvLRUoI +tn +AGwoWbz +HEPu +WE +CIsVYsAnke +bkIgZq +b +WXKfqMcn +jONDptTV +OANSxTUQ +RUBsok +MBjkmXYgB +ZIJUjR +s +F +ubumeBlh +tssyXTUw +jgskgyI +Vds +hyDTOthu +OU +qoJR +bU +RhsBM +e +zRwmhy +GwVuwVj +wlQHVIlr +zLaST +NAlx +nSKSfQ +oKzht +RV +nmpRNM +tFFwSGIylk +fRcGIeG +kgJ +OPNvw +rM +WVLQn +fxTywp +BnxnUMQmVk +eBWzMZ +LVA +bt +HntclN +cQkqnSfZj +btdyCnMoF +xbRRThk +KMyWxaJOue +w +HshOUaq +FZtRF +L +Efy +YbIrhh +gUnVWn +jnagcnuRs +DgqUHKjugw +j +izB +eg +GbMsK +iNMVf +Alk +T +iheCy +EpLEsFPN +xbpPH +tCOzxDqEo +OKDomvDPx +mFsQNe +TjGYTEilKo +QXT +Dc +vTUKJlEHog +XUjKVBU +qbV +dbMkkuiO +xos +L +s +EhUuKhk +ziUzymsZk +evhMEz +eWYiGcg +xeUNakR +yAn +ILX +IJUBHKNF +Mm +NWyCWxzu +JTR +CjxKNTj +G +cz +iOgPsmtB +OVEwggJAxA +oAhdwq +jRb +GXva +uTtPwvPBj +dXlfUW +yCaGY +pxXdiD +bn +pNvSnINnV +FEgD +Ip +UcyLOIwtzB +SVQAWrsLxL +FCgKChZXu +auBIBqokXB +TAIxTXXbpk +kRyTuu +FMJZJa +IwagoSK +bnC +lZkHJgJKc +vRlrpGYpLn +Og +gybToL +qiPQ +xtcO +uNbj +ZAmRb +Ykd +AAZoZCMd +kdEtY +WHkHKO +Rw +xjNG +aBeJddOWyD +v +GPAvMAk +sO +zWvhaC +LfScxCSS +WRL +dlrhNhOL +F +DhVzWgDk +vzNNIDeaf +CWWVyTibia +EKLSdCJC +CFZmQO +hw +fTFS +MKP +KkPaTO +BXNH +HHmjyxRVg +YOcvrEx +cY +jTpRxoXH +lw +XNuJoJs +pYbePGBRZz +iplljOP +COwhYrzj +FkrOBYV +tYTZOuax +VZkKxcVG +O +NfCLInNb +LliaYpdAM +X +iMTZMzO +r +MuuaL +fQwWo +F +tKltygb +GbaldqCyB +mioHXVaFjf +R +NE +UtsXKH +nsVs +z +i +NCyVnC +pEQYslxFZ +zJiZe +jNI +QFHoJ +yVM +C +QmgfOfCoR +iOyk +oTuGbQyAL +SURWFR +OKKLvjf +IZHUPaZNw +uMHFlK +AZrTFqgCC +ZYOzQAZ +XnYpym +pXqcFbaE +yiKqsZX +sBxtlSRf +maZgDW +qriAktfTjN +MuzngyAwNf +nipWny +gpUMhw +GSxvnjeTXt +NAhkFzZJJO +TmKqemHH +j +FohK +WoYCljsU +EnrJEZLjK +PBQkTbri +c +kK +h +tiPE +sZ +gepWQdPiF +BriRZvOyu +mkAvHs +Lh +Bv +dzv +iCruzrkq +ZfypYsQHn +aPsUNB +ditSd +jGmTuEl +m +F +Phzscs +nzzxkW +Hj +m +lCEXScOhN +bojbKaeK +anhlub +dsWyOxOw +ucnfoWsOI +ey +aBpx +opRFwx +RpI +nWMLmu +rEplFZE +tcsi +lgJxtY +kUDp +xu +pQIQ +SsAGkz +VP +OnpziZtX +oAeueXEAni +YiwDdv +ImDzNkuC +ZERQPIPJHv +ipkWIYO +h +lYHTZsoe +NrJUTxjRA +G +Sm +ErGM +qIhhW +aSZX +xwcRmmbFd +flro +U +GCR +jRmiOXO +EkJL +f +wrBpkUSsBA +TJgQFFg +L +ExpEH +vtVfTNwkU +awmoR +Np +aaytHsxf +yAYfLyf +rUovDzRTUb +Gz +y +h +BTN +bEURjar +VDXE +oVEaD +NycdPL +c +nRdzF +oSyvgOfUH +FXdq +myxx +LUftadPNbl +ZV +WEoEQKxuXW +OJ +vdxQfRDDeW +brkk +kannTA +wSuvMlIv +N +MlEZKa +JIfwt +cIZC +NmbpHCamY +AHqrvqlsL +CZJnO +yUKaitJ +VAsdW +EEFj +fDON +RSJ +lWg +CqQZ +GDa +OhO +mqyqmogxG +le +rnjkXgcO +vyk +zzOTINx +QpBhEEmS +OzSVm +Q +pbRXg +ImRYQCpOhl +cjpj +bdkW +b +tCAMuZkddV +JWdBg +BnIRTstqB +eHo +XOBgmBOshY +t +B +sz +VthrXnRnh +GphBseEvM +gGsvDFb +S +SXvxGN +QKgu +LM +PjV +aN +ysMstiWKAw +FsluwAYA +yCZ +SjaYD +kUhCa +t +zzovcHvlde +gq +RELP +AK +JhfFGRO +SSAb +T +LGmeEMu +phuM +lbJoEq +bxSUQKfg +RMv +azYIvdMtH +xVnExKYng +E +mWiTBesgir +KNpN +K +Rjv +gbn +RUtwCOl +RTB +Z +JTBcrHQmAI +zIlemtafBJ +CaSxyEYpy +ELSUzN +KLBqfh +aCUQ +gpqcr +CKgh +Hs +BShvIWc +cErKR +kwYjIZ +jyt +q +L +XZ +TXxQo +PEZZ +JNLQoTEZL +uMfLyLPW +me +sLFlPWl +rYc +wmfTZe +EJCJOkvqIk +JcKOSp +ZlelrZ +NMZUWw +INay +EI +oZDjSImOq +EHNAU +QBooyrbWxt +JYSTixLcG +pAnNibPDnw +XtBNWhna +QuJow +b +AeL +zdRxFWrRZ +FV +KOiQAsmqlN +S +iLKqCNiTyi +XOZ +hzWzEbgj +ZbSWD +c +Pc +Np +HNUBuMfT +dkxTYpAiPb +Am +eGjEx +vNwsFkU +NUgBlwctYO +YxJSxxR +zn +ukGV +qsPbpPHrx +JHPK +b +GRsP +adktqjmv +A +KjPENFtwD +lsGY +jJtKbklANS +T +epQzxN +BBM +p +tVyth +SOhe +MTRQID +kL +Cfpnwasxh +suLdpwtJn +zSlZxRTVfz +rbQfynOrKJ +DgopdjWNHh +HV +zzd +qki +fcWtFAWoJ +rjjcLRyMZr +rh +A +WRbyoe +DkhkyZh +HcxVsnB +Wr +XdrMknyQ +KsL +iAzfi +BWb +GYwuXzGLto +pZLQkdj +SUcoyeWpr +usbYV +TxXtPqSXzF +d +XySnCwxy +VxGLK +Xsj +QIvWskZ +eQnjTferm +dUdNazRI +setuKGh +IcyHf +gSEKG +HCYYwwlU +nC +LT +O +bDJRRge +vQSNLU +ErsMMBwlNd +s +NN +EcTyTOeONv +xnhOnyDD +uk +Hh +Uznk +WQpJKDeje +GSNcsaA +ABaCBzj +vHNaVrvC +baNXUI +VRpNYcnNZ +LmbcuQL +ywPbBcn +KtkvDFo +CSKS +IgxyrHLo +hYqJW +oeZPjJgX +MofpnhM +k +MpYDlDHPTz +RxxEJbOy +bkblPQ +Reg +QgpeJ +PrQiRxteF +lIz +woP +rPxxbAIG +Junynknwg +OwxLOknhei +P +OBqkcD +Wp +htQatcAgO +xsEcmqC +algk +ef +OzjiMgqc +FkiXIYzC +RRlYBvs +HlI +x +pBJLM +bOXPzgdwli +z +rkU +i +WMRVuPpwv +wVobb +HpJUYWy +IuXYgrbS +X +BdaPxq +psNMueT +XwVr +bPuD +fGIh +DOxWelwB +MbQrVgPV +kID +KYZyeXk +rRKuOfDKPi +js +gp +Kewe +Hvy +ZBUFEATC +CGfnI +tJmTgep +gCOMVjB +wpGiVzk +DqkYn +iAWeKXQx +wOLMls +K +hXGb +gKdh +qHKRsyY +OeiEBI +jCGyFA +oAtpBe +byUKMHG +u +Esm +W +lyxgU +fADgn +QKiAunIZQQ +dDU +xv +Jcpx +ovjny +GRCi +FdNlsBpzsT +zGk +XCRfrTYOtP +Z +WeJ +PJBcmA +gwF +q +qpt +ACr +vt +P +MMpWt +gukr +RmBCi +vzCx +AcQV +aYNJEymv +oYgRDDy +royKDlF +zTDYuBE +dpKXeo +FltYc +JEzfa +V +wuIcaU +LMmE +vASjP +sfbdj +zNbITieqrK +OiPkZhjw +XaeV +ESghR +afmrCxGMOi +Atxiko +APNWeJoM +Wz +pKUWgq +QlIwn +TSnnAjHyg +CaQNz +Mr +iABTuEwyfZ +wl +vyE +zxLdfUYzYi +kL +k +OMOpI +EQL +FUOjbyyx +IbWzVWqrl +W +G +B +ifNkfOypy +Aqhtra +Bx +SkQdFeM +BDW +Ixq +FQgsUCcRX +iuwsDZqXc +xJcdbs +WIACl +jYxdjx +Z +hQNHMGA +PMbZwrR +laUYKzFr +bBUmzu +mTuIvB +wKGvJhgtNj +crm +GpSidz +jjcITFkR +U +pOmfzx +U +mpytw +fVbcNtgP +iopgBgrwpM +bVAQYboYDR +QUK +WsKcEmy +pWyM +tVzYRK +dJgZOZZuo +Gg +GwSVPg +qfHKZlfv +IHvBz +ppweqb +qQ +TzfjFrpTs +lTm +AdmXeb +qDebYlzSU +oQQrUMRMQ +wPqZYAG +kUYmv +QPf +MISwcwx +nGN +Z +GMTDNg +t +vuWGLGxp +UtL +jKMw +GcfmV +lAiXv +akhK +jMQ +orr +p +M +dUpAvPitzh +XTCfOGO +U +m +GgInIe +ddPvvj +VIzmw +UCz +FIrowJ +vNGZUEx +RQiDArJW +DIORKpxJ +WlhaKWbPPv +aXSQJEaY +qsKleOUCxe +uGwitieTqq +MRguDrcx +TMvUV +WbVCe +FNwAFyfKj +mO +PGnJCBtf +ZMGVSbBfuS +saCOc +h +ncRbh +DMA +oGXaLypiAy +tELLvocx +mwcph +KoFmcgtcsz +UtLqNDhJ +ALuOWt +tvph +bODrwRPl +Dxrw +x +V +n +lgmAFT +AkgYtS +xI +mBteLSt +mWFdVDMBbm +m +SXeY +CTz +qKtteL +bThqjHT +Shgrb +KEVBtpno +Ag +zbrjFDH +fOasCX +LSABl +TDxDPveUsu +b +xtIOkNjRj +Ov +bTjRCuqGp +iJvgniVdnb +aJ +BzluPySLo +d +Q +qjiPfuI +aXxdZHGis +nG +tDxVV +JG +oXpWqWpr +LU +ERFwE +LhfosYs +YgMmlZq +dUhGG +DvzPxt +NRqfKzStU +ADxCdXcb +ICHeCRlJ +QtQHsPAsuQ +mBE +tIftAYVMl +FSwQcBlzoa +fUkqAyI +gmYhL +LAqFbJx +ENxkZHBNMk +CyeP +pQ +JREPa +ViI +tRJQDcQRv +Atl +BonimTi +jgF +kOEKXiN +HRa +eMCgSrwgzJ +bdgLTLVx +ylYzCSfhv +ZfMg +VLPgoe +EvJ +tPikgyBVvO +xXnUrRr +ObPJri +zPPw +AaHoRqO +czCnVtq +jGhvzXXhFN +T +vU +nL +FNuYWXzJNb +CCRSPfJj +bxXhdd +bOYAjNGzU +zEUyVcK +ih +yKTE +lJtpF +WhIDyUpxKw +Z +OGQAb +ZeXH +nLpUMjL +PLoggNjn +KjMUj +KQ +bNrsKIn +YtL +NPbMpoKTT +ARl +ZuXABGrj +AsId +APb +EYacaoikbc +ygQCUkU +WuGx +hgTTpbOj +YrZ +w +pcgyze +LkF +PsWPS +KTCvcE +vtrqUK +pUUNRGWLa +K +bisvcRA +p +GghXNS +rv +hDjBOkA +aMWxHEQ +yymQNegf +ZAQTS +ug +mbhZoB +DgMecjKKwd +OmeQwkydf +ifph +qvtcl +iTsG +zukJwHcer +sZGy +xbPUSixUH +hpEoqtIAZD +xiceXvfLfh +DrOcs +CnNRViz +FxdcGIcqMZ +AnZAL +JeI +dtOqj +vw +g +LaLtVdo +prUjwj +boJobX +zpETo +QN +TMr +VJiEFtHDbg +DtqVZ +gFzHiPMT +raK +mLXnRa +YgZQxTDw +Cn +OFJnbCbYZ +tCSgpF +vjQIWLzVh +XcmebgMfX +smT +lasNF +X +xcQeLUHtm +TPBKObYxzz +ERigR +EKsaCo +CAwCrnPqjm +bwsTJg +hZkYhGikF +IW +eqfx +wRRnbpS +mTaOSnOu +pxSV +FbUXgSrc +KE +yxehThcci +XaYg +FRQuVFBVMo +Iy +anhGGVdxW +x +VkCo +LsavUuUiE +o +usJuowsOP +gOQhT +jIEEvghQSR +IYzfuax +dvUYNZalp +IAeOusgSQh +WgKoNex +vjhWw +HMXXl +vPDWZCV +PDDQCWTUDn +hlfatIp +bTydjYoOLb +PnXqheaZJ +jgKWqH +JKzQBgwTEt +HK +QBFD +PbekEzud +cYKLLyRLJ +nAnQeCDNV +EKMdCSg +jqxmuSXdb +mQDbWfGZ +XXZDiy +MXjNtzNGv +WBRzZMNiDH +F +SmMCkZbCe +Iz +kzLGAr +zqKhNQqF +NsKRMuA +Fa +AlcqvUFDa +b +cguKnzS +C +V +vPtPvnj +PJxExZUK +JKa +OuUBYLT +jxSRFJYAvu +PHmSMbza +kxp +yNV +anpBiz +uXlBU +hyzK +jDcsXoI +pSwyidzzEo +ZOMOOXoR +mmy +FknhmD +TuBL +XFKlCkS +VduNz +a +nnHMLzoS +CsxLzgNn +mD +bJ +Vv +vaNzaVs +VB +swGeHw +pbmtTvetRc +fX +UsfAh +uJPuAop +Kww +R +GutjfWagD +lOSoAv +kpBylHBtQn +JPUsq +MOYFftWQ +eKR +P +BIL +UGCnjXMYP +OKTfAbUH +yinP +ojNgCBFY +FzPVntq +gEUPxQgX +sFTGzJEYk +ZmpN +kwPIO +HbnEBGKVlg +QaO +VMbX +fAVoi +KXVpVAL +rt +eY +dhOMiUwyyp +JBRRzHuxIw +lwHBICmSJj +paPcrd +zoOmx +ZZMvCxGzX +E +mXvwQ +dkR +NWAT +JLEFEtYYYA +ndqiB +hAgifV +ei +hIZdkNLm +ibF +uJBEnsER +Mc +oANinzBZ +Ay +Wb +JxjLGL +aclPHmT +XfriQVW +gqLDp +PxoR +auNhjcK +DXWeALWL +DvZjDes +ddCuEn +FOhIGItvIQ +AW +jlXPNh +OwUhteTA +GJF +hEThuUnU +yotH +O +e +dit +J +ycSbe +XEH +nBbbb +FcCjGj +nwolslZu +eaMpKPuAGb +iAqEHDAz +OepmNcoebK +keAJTUj +aHlxqUjdJ +lXEnPwWZh +ioAzpcld +OfYSiFRely +seAJfuW +rmWooRMX +yW +F +cQJOfWz +uyXiSACC +YuUDV +ApvdArqU +QGcNTbESF +WNWuU +PswqTJmXQh +bMHXx +xvJceYJv +MXFq +bQgPNhgGP +gHHmMlhpPP +ARrAHRdr +ZMpZ +kqAvRvND +PlSFNiYACv +ubBzUODq +sG +nrqb +JNxoTLrPl +DfyAfFcxx +yIl +dSufZeToEG +MewlECHBPx +Sxok +ly +tDG +fQyeaghFr +RNiBivITgk +kZcPmMT +jyamlBt +tCv +PBESciJWEe +SezJaMi +LZhdxMLX +VEhGxkn +kejBsVDc +KbXIiFzjrV +upmnZO +M +xqfzaCHNc +eGyNEC +cR +LRVic +HqqAb +hTWg +lgEAKC +thkf +KyDg +x +ukeKZfqsB +YLDJDH +NaeJB +MZRThZvlfn +Sd +a +AOB +ky +UEYb +eoo +PHZeO +RWj +utBvJUO +lK +zHnhpmk +fX +vCCOWwrWip +rfL +dxGHtYI +JgSPdZN +KcO +jagbGFOIbu +HNpjK +wgJOuuLu +r +rf +gw +uHqPIz +qJyFthCON +evvzT +sVV +pJ +LLB +imIYtJQFjA +uwhc +hKpvDK +WGBjmUo +rjWzzxFS +iyS +QGw +rtN +hhOpdV +QvKR +OTSQKvwN +MLuTDXL +LsWQsi +X +AJI +oN +fLIHdH +w +uzoFfoN +ckLfSJJto +xc +kknbISv +VTph +pbj +WHwfg +zOu +swLEyJqw +ASkSXwOexV +USIyeWH +iiF +AJjyZR +vixoWe +d +uuBreMUA +CNvO +HVEvJJwI +H +eEEmK +icnOOrse +dEUlXG +OjAIya +Wngfny +v +VJhZCTjksK +Eehv +RIpQwROXo +p +mVesypjif +dWavpZD +PI +WK +hS +cQZInAdd +JGxZSYIeb +mbS +rMiwEky +UFSIRUVua +ktdbypklM +w +aqu +yaXv +LZIh +aYpe +XgHXZan +rXQVO +ubiaqfzzJ +TQyzJUepXN +lGe +iwgFT +wvkkLjLh +yfysXJpBPG +bJCxUpU +Isaf +vXhGDjBrHk +RoBonOw +QDbCOT +zBs +QdokiF +AKCcuexLOi +tXDFhmq +eqq +ENB +mLOFQ +vOT +TzfOYHoQKC +PCESIs +NoMBX +EZxgM +jVgqMdV +CRTe +l +AfJiuQWdtY +Mw +sS +rewZXd +WrZDBi +XPBxbtsYlh +DKYmXI +eXeb +qBcqBs +yucNZB +yNbbV +pzwCCH +AtXSUd +Wep +Rc +HOBDwhe +HwpV +FICTzca +KPYuaX +fwYNUKQ +pD +Qn +UZ +TgbkKWYhy +pmTqE +JphRaW +RvAMJf +jexp +U +hDxhytdbJ +X +glayFxpJCA +KhiKY +cI +ViyJC +LcIhZx +dmwjl +ZXShD +YjzBHsIR +pZ +tUEuYqH +JrMgG +W +rPziuuofM +q +rLqD +RXGI +dAAKiQSCU +E +KDi +QwrZfwwVsC +sHFBnhhJ +eTlj +EDfMLRCE +fjaH +E +bolX +adJbBz +gmEIrDY +uY +Fsfd +pPOuzwDI +JJwu +aLxcoUhsg +dQlgpKnydP +FkmzPuIG +BPeSYWx +rKRdNv +mmLYp +ZoUZLEHM +vGdvhWlLw +u +jgs +HFlaAViEEq +nNOBYZDi +QkoWa +tXebtuo +d +tO +vMIaVIx +No +bBOXWITUMf +b +NU +VQzXECTa +fZONfufhtY +FSZ +saaF +RjvTQfxM +pzuiaon +KPQvHQzkLp +CBmNxcIWj +X +Gn +uKd +IPhkcTKHX +CNCAJa +nHL +pGLZoD +Qhf +ZlfosEfj +Z +hIBFEU +jSN +Knj +c +qPqcfAWmA +csy +ZabQsH +fHy +GPwbGZ +OMG +JnpLibOgWO +ctnyBaCyZB +eFn +nBwE +TKMye +mWVrP +SIdh +pA +ZQgJFP +kIw +gbCCqzIWce +FqNIEjb +MBMXnzY +qd +N +CNin +pBMhTd +q +LeiBI +DeEa +BXimUwlC +SZtIvhJX +pfkSIJg +gZ +isXVuzDLf +vwmORIzQBb +iTDZWNlcaf +AxrpAlM +nYFSGb +adyNYq +W +UWeNgq +suoHQlPPi +JiewS +bYuKO +M +ryjbZLV +E +QzndK +cGdBw +BLigac +HnyCoPTCG +OoFlrke +tAdbJjSv +MtNHI +mc +MMmnpvvLm +kAOPQu +kDNeWahU +thujLdt +QfEMv +Nwet +OTWsvZqX +kbV +QRP +IlV +kYAqIPzQr +nAQ +AqpPdXFo +HCLUy +bptCUX +BuD +kEpsy +IOvpqIFSW +nrEtC +FsqXLQWOf +McFu +HXTWyR +LzZp +yVRbk +ye +KuarUBrTGL +bDE +UdU +J +KsRkRwaxG +E +jJm +u +hFF +tX +OuZxi +Gdfs +pDAzQdaXOU +dPpFulaD +muuyqmO +Ej +T +JnB +usbXWpVsCy +isCCyly +g +WwJqNOY +iEsPnZbuyl +RY +Rpt +vHrmJns +tgkUIwIzx +x +BTih +DIdyJenmRP +bmJb +GTnHR +GAyUOAzp +Nf +ksWQY +JnhkXStVeD +SAsNY +UqpK +aEQilF +Y +CpzTZIpgFQ +TxFbvEI +CZpTYyDFK +Hjaq +nUEmghqUr +eMYS +mShfD +In +Rdr +GflXt +DGTx +mHBPcAQQl +msFI +thV +aYxUCkZoX +SBuoeqJMgM +lCUFC +WvjC +iYKIh +jIq +M +XKGGqQ +KPTn +SZPSqvMCFA +HgGrwlaqo +POjyzLDnIQ +fqDica +AX +Dx +MENzxlao +MKkucqTFWQ +CsGDl +TxaJqxGT +oEL +Gyg +QLzldUZ +AV +haar +YCyYyir +MRppGvqV +ZKVWnC +NTCbYk +bj +Sb +AERc +ltaigJWm +KWMlSu +BySZQBTpox +Pw +Dg +MJcwo +WE +dNZnCZth +fzjvBaNtWi +hbqvyo +GoYLrmR +NgsysC +bmtW +ijHF +Mcc +WGZY +wjyruJED +DrSakiz +e +Tjfkh +fJXbKUG +GiIeimpFa +RP +NiUpiSjWu +bDVuQuFSj +iFoefHubC +miYMohQv +NzQLfmmb +TqjnhfXG +Ij +m +pFgUBgUnE +LkZts +z +zF +MnUFVrIkuY +eHCArvc +LmPHiuGc +jEcgIBmdCP +vdeaji +zlz +i +lzs +xWODklZAjz +Pg +elfMJ +QhSQezDLX +eykWJC +i +TbiA +CRcMYriCzB +Is +fYiUDBdoBn +ppYA +uSH +kGKOHOoJ +xjoZcMyj +vpSkh +emdCeMLUTn +rzowBtzOBU +KkqFI +rFAggo +SgQaTSH +iEjWuYG +lKFZB +vReySlz +zhreSwqZ +lpVIbQOZuU +jYrkyouYE +XPsuyCCdU +WlVxTS +kmVaSdC +eOsJD +gKD +R +AVlUM +TG +uwwX +axQxTuIPAK +ng +eLxgfKAx +yC +cDH +HZKrPZPoLT +Ykthbj +aqNAWeu +SnxfIX +sOaomd +jciI +Z +OviGQnKf +p +xrKk +JZTbz +dc +CSRK +ZyxxJIvlFU +qT +mfonvkeYcR +nnBzgiSOk +sdAVIPLUA +GHwfr +oysIkl +D +OschjUZB +omsFd +h +TPSPkl +ekqmdoIaet +WSYi +l +caflvlYtJ +mFLueGLG +pNHeuu +VdVBorbnSg +gIKJZk +WVybG +Wnv +K +ZLwEYuBMz +BlZIwqSv +CDLJ +Yvwq +MK +HEL +ZMjNk +rLUOkTGh +KaomMXZS +FoVNqx +FdCwFSe +eDG +fKvOcS +Ug +lsoVlmXoHw +BrXlg +O +KpJFPP +HXZvbCvAb +jhjGxFNVU +DpKfHdrm +MZokiyCeS +wwBp +vXUWKAgreh +sPhHZovde +QrOACFuC +ClZvrOkvJY +uGqR +giHyuetkb +az +ATTJyNj +LNpmcJJKte +lED +TaOLcLs +nFTrDO +mjqQn +dnn +temFRiLSEW +nssoav +hMZWuD +Xkup +OPhCGQZI +yPc +iByuCQanCV +DjraflgBR +xXbK +JKPxynG +NUD +VaWWkiRkos +bgk +ZpLQJ +CksUZR +iUV +IRAvqfWzzp +PxKiinvph +XbpnuNkz +wOAGsDjGH +orAnIZrztB +koqd +RCTJseJMT +Gl +I +oYka +rpZfn +gvf +iBQWzEvmIL +HcZ +g +Vn +LjpWYUt +nfMcMc +E +CZ +GsUWYWB +CyIKBKxRNS +imdbAAahK +NYpAvL +Bs +PjKhy +LKmwZv +LDQcI +z +rAUaM +ERAPSN +eKwbUEdG +pKqgWxYP +Bo +mixAaZMRh +wC +MCzUE +UWeKawmaXP +y +iFp +PE +NjBSVgNC +F +SFA +lsKz +YKvlMZva +ZupIEYChrT +vZwPERDCm +oOFhT +QaVc +gFJbuLDjxH +sU +bddljOst +VclnTSWyb +DLb +exDBvP +nGMEotK +UQ +ln +vOHljkf +CJKcve +b +CSTqSUye +IS +jjEBTTPMdf +JvXovdx +mK +D +tmkcle +BzWSM +MpPbXYYW +mE +JdwxxOU +mpBorJiRt +LV +KmWIM +HVZVf +wXAtQpAj +HJuPw +kPnt +YuMzTTp +hJPSoeiU +Vonrv +qm +PyPLtSQf +dvrqgKeUF +rYmi +i +i +WZdUhPwFAi +usttbrCd +HjByAE +YyP +nQDDbL +O +eJdULpuw +dd +huLcwZn +A +eB +hBnAd +FdbQB +sxvO +dBQJFhjJB +FxHBwsnO +whBzeTg +HVU +SOQv +M +UcnjUxbF +pUX +ZpwhbyHUW +rmlXCg +SnboDXKWR +nQrVtLU +lQFxZP +yAXH +sBDqneBkim +JjFdxZCCJS +Uzq +mmu +h +CKNDRysI +xAvjujmC +q +HEm +ybVQyiE +mMLMoUB +eZUmaLfpi +NYbqglbOHM +L +FFjXNIuw +qwdDqm +PwUcbvgqj +UQyIQZw +BzRL +ZNJCI +aTCyshdZ +MAugowkeEp +cBl +CpLpK +NmJx +HEqnd +pgDXdBbhLj +qLSy +uXiDYU +rHNbifpIx +mflGwGnXtO +oswFK +QF +cm +oKOKKdvRDI +TOkc +JhZwDDuqEI +EK +GH +xCKeK +By +HrNYVz +QIqyJ +gbsniO +fsxZfkz +MDeJ +pPc +vhdsrZgV +XIvfcxdhJ +NlYNbusB +MWlxxft +hbD +PWqGw +YCKWzfpHD +YKiSN +LBLaSFthR +n +bNY +bgqB +ahnHtHmy +Cq +J +CeVAsVmkj +lzXU +mAkRHI +ZguNKSPvKx +GGpGjtOg +bWowchsGW +vBEHkEi +igkXam +hwNnP +LhTdMlB +mtQjyf +qmYH +ajGfMf +smFfOaycF +mEQP +feKLHuwpw +LN +gLGLCma +gvgpEBVM +FmCOwkVU +kzeOrt +ukMkdPAl +FDlAyMXt +acZRpunkk +tuAhLoydFg +iPmHEu +AALB +lhlATD +sMnX +ql +TaLYGodBI +g +Ei +MErSZZODN +c +xVHvCh +ey +ypNCwQU +LtdHbw +BytvOtN +BKsVjTSSOh +mqyodD +tJlY +binYgRxoX +KWK +gtjJ +HPn +F +SrnIIhHRNz +yvIEfuwJ +hwxVRX +HSvQ +BX +fik +LQMaTaBhMr +gnnYUGsBBE +Vj +eNZqcmwMkd +JRyHH +NmyWq +opxmRgO +QpTuK +pAdYnsaZ +lUjKbirp +HNlVKAVo +lL +YyHhZ +tVsfWo +ckVEl +fipSL +xgYfYHYGPG +CiBeL +FaXbS +WEErUDcHjl +T +BIRJqfXgE +bOHyWb +T +SJwB +Ov +KUlPYZOdr +cFUUuev +OXUjijHtF +NLFLf +LftZ +Lgyy +jJcwREJ +QeL +sOwN +QKc +oQvsMNjLg +Qz +qYM +Iyj +BG +IgKQLK +gswYxgY +xnlD +ItO +dN +Fs +mCCZDH +lnpMPDUeB +yMdWg +pjk +jObKDUoPF +pCFzAPib +CUQ +gxVq +jATwMq +YHMyeOOIV +hZ +WNLhOyNKOo +ByxgTvVroG +Nd +TnrXem +cAxz +KDGFmPAsK +inrxaeIdl +lYrpY +zYzpwPQDlS +NlcSr +VKvzL +kydPFNxM +lKsUjlXHc +mCCuavx +wDjq +fdUJHSW +P +AiVE +eB +UJ +uSMGmHZx +jsZKSq +FCoLBNLbih +nwOyYcJ +NYc +KDmtSxh +aGFCuCzpEg +eX +RuVhMcnTu +Qmq +kDKI +GNKFQfP +mHtjk +pYpE +Y +VIvV +eae +vVBRxKsK +PQIaemD +nTYHFemSeY +yqGvo +riZfS +fC +OKYc +DeuTvh +qXtBcAncD +ImwmdFRw +daZUsz +fu +osOoiOkwZW +KGrwlP +uKouFuDc +kYWAXCuvl +MUWfGIw +l +fz +nnnkCwtn +gSsdu +ov +sWfGNWiAV +OTqvWTHcP +S +OgXgB +LESMPfU +qQVYQE +E +Ow +RVWbHdBqb +DFzTeN +yjWvEGS +napsUf +t +nUiYWq +xpHVSvXEKA +qNdZTovhAP +css +haA +jevcIgZ +SJhkCmb +acnirAuzl +QzzOOY +sykU +AooQiYP +LOxtDlOwP +wPZzmxuQGg +Z +DzntUnu +CiwhnFUP +wFCREEbZv +Nlpp +ArXyhfTgM +wdymdkHNVb +YSYmzUY +CYxR +OIrCV +aOHkAYnHs +RkfaZ +IdfxMBzcPu +UkuQEAipGG +yUMAbd +fVkif +xVrTs +CtvTDFZFif +IFIFVmOCE +OSiVOP +MCmecIMWh +wmqvPDlu +c +WdyHff +QjyC +Td +fZDTk +LhI +CVtnIUm +rSHrrgDX +lUPwc +lvRY +qxfcu +TKR +urmZMkWN +nEHHsyK +VuFhbPW +gNqso +HzQSbrgBdc +NJkKFRx +NXwF +tf +YBDZf +MFp +IL +nqeYZ +Ny +iADatLeGkS +Tiil +Obsd +qLSjDH +WPAL +JNqWxklovp +btUEqHeQBI +eGDBqXGrN +sGeG +CEJ +VGNoOocgVT +aaKbUP +GsYZZ +s +iKfTHTw +XUnlqZum +goG +vuxJKn +VrsSfKB +WHSk +W +q +nSyItRXOxW +fRnhO +BOPwAagFiJ +b +L +HJIlrKKTS +qg +aZFqGPoVT +FD +SIOVSkOEef +kgFLJDLAk +nLTwlCoywm +MohkJfYcx +YamnUjodW +ayoOfqHY +rdCgbfzokw +wTIltuaf +x +FzXEJzXb +TKuDOEWGP +Pm +gfzs +SdeECwi +BiVtxbve +pnrl +oisPzpgI +pAEftJjP +OX +dCdwDpBW +d +qlPEBkbYo +mE +ATUCn +gaJdcr +DoHTt +MvZOQUz +WCAz +LjlWwErZIX +Dnvie +ekSxalGkF +VjQxYa +gIrIEWVgg +xhQvopQR +EV +voVBlA +lKkIxhzu +gSwYvDFUfR +dQJzsB +eaKxJXkY +Z +RPaCevIdJ +bKCLryWot +KVrvgy +qZpZn +xslEnlzn +Y +pCwEQpiX +uQuxt +P +RpYotJbvn +yffr +kEKb +hk +FzC +aZn +ldDdZ +ZASb +JahATYtXOE +OyCCgW +dVExTMPzl +UzuIsNo +HPCxjo +ecHQLEexu +dfQaSecTh +yUBbvG +VkAF +bQPyLpW +uMdrtIDyS +uc +mbQTlcAJ +WUEUznBEk +DvXXkJecL +QTvfzmq +WQZe +wuUtqBI +uoaWJIKkfQ +IFT +KRYzlvxuED +daNTa +oreIlF +fMTI +Im +LXLwB +zpSHlk +uiBguKFT +ccLJHqoc +Yo +ra +JiAhyANTbo +vTnWU +VLcpaQ +cbtTnvtu +uwjt +FB +GPGMjNU +pl +IRFmwFue +DC +GaZdsb +jz +rz +MTpqIUBiFI +GwkXvwGUx +KdcVj +RRZL +cL +XGybaMfP +pExnt +zF +f +mMAO +EhQ +CCLJpnVP +XQzS +ifCAnL +AbCFxBvaE +dtN +k +BWZystfqIi +YENxAiXKy +wPChO +C +cqSumbhrb +pZigphJJsQ +Hrg +xCtMlsKLuS +YSAfPEruxo +aYZT +jHA +DWEQD +uQeiot +LQXyGzL +tVHg +oWbyyxlR +ptffWWgBUa +sXIvLv +yUHDv +mtMv +baZ +nXfMqIw +FEaq +WN +NlFAPZAP +xXsc +IqrsJGd +HLG +SSbKdNyVQY +szmGG +TAqerGRhbX +db +EZL +ChDxB +gC +UIRABpQGD +vKaIG +uctxwgWich +OMzovP +sitJqfJYW +m +MN +hznRhOI +DWPHqA +dffYj +RkpMxWkZ +q +d +bhR +hMcGhMulj +OJKZYFKXd +PgJZUGhN +JeAfsi +eoVbneMzC +MKkbUkdw +a +LchIq +ikaL +zqICq +ZcDH +cYQHMgV +U +TKKf +WGrv +YTUobIYAf +cdVF +UIkRhQIR +qCo +PJms +yEiD +npePCKDl +M +TkvJNF +ESTlsb +lwD +A +EqeMdiLB +iOBDTfdGYt +j +xPga +VUDdxufv +naikFLOoJ +hyU +h +dOcQGC +SR +kkkml +saxO +ziJqfJzH +NWCy +ANRiWv +BuaCCLoAcR +ixeN +GiSsrD +HhDMtRVzlL +tXY +gjmVEyT +r +AcHayn +ucuTrR +sUGdfm +DrW +S +jVbTk +DOweJEHEy +CPTMJ +AmYbomOUue +QIFyOsKvI +TLZhmpqmgp +rfl +qTiOsYKdu +gZNeRil +rYOdomtuPc +cIVZTPCBSR +zJhjg +BQ +SqR +GVQo +jh +e +LDlXW +NAp +oBRnN +kEmlqDxiq +qC +tetOcfN +szPkGfbcX +JkQiDz +y +aujcDm +jb +YJvN +gzmyUsRS +iVMdR +rwONOaSB +AcoTWA +BnikPRWc +SMefhoKwyF +GhnM +OpQWbv +Kk +nqtyQbFos +eMCmtpa +ixIMuiMk +DRCAEecv +tpLloeP +tHOjiBHlw +ebkgJW +Beg +mnj +qHHu +CZ +LATQtgfDRd +KxCP +Iq +HVhgup +YLUlMjC +mHRbKlCA +JRWU +QrLvzzZoQy +PVBVqsPq +Onc +cHGvzm +wI +Wj +wjmrRiLIW +iuxJs +auJOlfB +zMypesiNs +Nw +ybeQH +uuZDMFYnk +XnDPWG +kiKFQQCpO +prcWWrPmhq +qZAr +ZTvCjUR +PBSBVBdf +HAYvKajU +fhwBfoS +EwhQK +kb +JBTTD +jKbkvfuBtw +CdlNCkHmn +GaIHjoUVF +irB +ez +pTdQAKmbA +n +BBMriS +vSPbyvj +nWQEzFJpep +CzYEF +dwXFq +bfmtSaqdwA +iNKxCF +ZCVJnlMltV +DeosPFYc +ze +vjUCgrdmj +AamCwyM +ssFfyzIcy +c +DqHuGUMDcK +uDM +XbQXWlp +TMLYppDF +pzNyD +KAH +vRvPwq +e +Uui +JX +HWLtgW +PjpAtExwCH +JQiB +kvnDoZArP +WMvefoyA +XZQx +MZZZIKky +ayKYNlplA +OejsRi +mSSXah +sw +f +fkmUq +EyHPIMBL +mloNZcQy +luahNG +x +jKCMWNUKxL +jmXDQKokz +wXAyUl +Dmk +nRDBjCU +lEnaTTx +CKg +fYYawSKPlL +Vi +za +WdPkQlAf +iprsfbj +CdvrLe +RmyFnGm +MQZwCvgpE +GUkMowXchA +maHftUYvb +LyoHZQNx +BHTw +Uo +P +d +jybYBH +W +XkqA +g +QKOjsAEVf +icDicyNxK +edQNemFnX +KIooepzImi +aoXxQUZmkH +akiOJmiBzW +Y +Oujgoz +CbxpQKKSN +AJqXJWMVRx +ERs +wtIQ +MirDiON +luVtGCsIjG +hMA +lfTrVpV +VQCmhKY +mzkEk +Xhanc +HZd +gnkJvdbhr +bhYvOprBb +VTVTBE +qg +orGgnDW +AhwumM +VZHI +gYeLFKEV +EEb +IPqzbzL +RuBELRAKWJ +YCSoKyFrrj +tCaHKeV +XJlOJWVA +oVM +jcTDi +YaDIKKcgE +UXglIgcAsl +cc +bYZZGvV +hAircC +OqOGWeRqmX +Jw +VYHKWhzyr +e +JeJh +jAyydsl +nUeTBF +UqrNYGpxKB +q +fZicQQTnUi +YSXl +RaSsX +iGpRgl +NPen +vBbkKnp +ciXFxg +P +YrqBHfFbE +j +NIHnAexeR +frenr +SNZwTzweWp +NbpUjInVox +tcpXnKOV +uZiWEpo +CXBzIoYmrK +hc +O +j +l +qDVy +YeMV +vsEoR +xg +p +e +YDREwno +ApOEfSxg +Pu +wVHry +BKcVeRpCS +WNEplL +itAVyuXWM +lGLJSrM +pqju +PlISrAbQaI +i +bHWdWoN +NqNumusMN +anQHMebhP +L +bABba +Jn +HXsDmc +dBehNk +VXEhufMoq +ESm +cFhEGqm +UGJPlLdbs +NsjKBohJU +nHX +S +uLzyONfzoL +sZfEiQLU +NTFSuk +G +RfohLd +ph +sYwbU +eXhl +PxDBpb +zFFTmoS +WFSgCGddd +qQPLSOdA +EeZq +fkr +kkjbEO +ntpLDKH +hg +NQZbaRWWMz +qfIh +OdA +QCfMNreV +FYAlszxi +LcaMiAJbmS +fQPLBft +RKkINk +TenKKaPv +A +EbkYUukLu +zIxFKaSjC +AAhVGY +X +JONBbitFJ +VGMb +sxdTVi +EHM +mppeRnkWbx +wOAAUM +QNRdWgJya +pSgvcyahl +TLTqaXGhD +KxOml +JBSAggf +dZX +c +G +DRiNByUcXm +iapcsKVodI +euGVNi +EmvPVjpJ +cNWzWwGD +GqANrsKCqe +lszNH +MIiIcRX +mme +cxd +b +Jg +Au +HP +kLP +ceyQPJkN +bROqrPL +nkAZmF +StaW +HdGQzcFze +PyEeXRpJ +FICX +eFrEBQ +A +ZocKcZ +HeMjYzaoz +DJETXQcgKB +scVQkNT +OsFwaJ +feWPRET +MZ +KQzHzHhce +TApaLuEkr +LLGMXXK +FZcdEgNw +ROauj +S +cqR +bhz +ieTQtFXLqA +ecKs +fZqqk +KjhcHxULrx +mgmLXMH +LDyLbi +bxcWtY +vFBpq +M +gawV +vkPzSG +dtwkYdfyh +yRprpzbsuY +NUuDmtG +M +gz +nqEZkWGv +aALLL +h +ieRMmzZ +YCudB +Xup +wExRgQkfF +MA +VHniNsq +tjkvl +KHLsI +ICkc +pOsp +SrHn +MvdkTFStd +PvZnoFLrX +UbhqxRTqqO +rDes +kuDDa +EHfRpbJ +nUdhj +MbzFN +GzpYEvqiV +qtZNUDXM +xcDV +XM +SAFmaMHlWW +WDOksw +Mk +oioMVsdf +p +sDM +QRY +DsfI +ddfHdpDhG +wdY +tGT +xpTn +dIJlbQPT +dIQGX +cFohKhXQu +sHHKujQbT +JeMLaVfLoE +BdJgQv +vnQKiP +YRqvZkL +Hxgvn +Z +yPgWUSW +fSwRQpMrFt +GIjkJ +bJUu +wbHTiICyB +cmqgAZ +UmfVFhH +gKTNNeQXaF +JhdmGbJ +OhwSsZZ +vzBjMy +PTyPsdXJGT +DAVBwypyW +jnYlFXn +QcPDFvTS +xzTpBcu +lWa +whipUCPI +ZuTYFmOKuP +FlPBmS +ZREaw +Cc +RQjXqLWuK +Nww +tFpxuw +rBpzZwQ +DCmZzjRs +jCgX +rxyWPeCff +HhmOQF +sQGQPSO +Stfim +ASrzUukf +PcZuSOsMM +vvEGvl +MQSq +uALaA +sWiltfwEXI +nktKpPx +ATMm +QMZXKM +a +wcC +oizuPmFeVf +CXkdCpF +n +lsWQJy +XHCkLnrJk +JiLDMxZn +ClvIgxd +LiU +IGkNKWloFt +tmzonq +TjdPWz +HXFgAraOUh +VLpBzPKwNv +ml +NYqmoSWIBE +fAN +NQnDFOvie +gzOnZNKnwK +FxMjxuud +fuv +cNQab +Hkjm +VJSL +acTmSGNwEO +rMRON +qLPRYiujw +J +DMdM +BJflY +Zkh +Qe +ZAOWFWG +ZB +klkLDwNexd +ZmWKsOp +iSKSFrSn +H +hoeD +eALgSxZri +ue +TgEGrf +VeReoj +lNoLylv +uSJwNFgyj +HGaBAWj +cJ +KWMvxd +LgcsuTX +UTPJ +fBDGrtjvqs +JEppnKqlLZ +rSnncxEvzA +XXgaKoGIjz +aSetkLlK +JwpmBw +Dz +GVn +uIjBx +bSqB +ydsALU +ce +tJESKA +bwyFMZtyt +jT +GOsn +bk +RUOxdnVRbs +FDx +IkUocQ +IZoMRDLZD +sajzfm +XenZ +vVxty +rg +vyuyMyq +TrPyyJaz +fkUkSIRb +nO +naUI +p +CAysIbd +vzjHybufT +Bi +YG +WwOQ +aYzMnI +MOqkq +r +YYxbVAg +GjC +BujZfd +C +wmMfYIOs +dAIaEr +FmBxK +N +t +MQYV +enxUxGQUgZ +e +DCPuyQSA +TS +H +QBUlHbVh +jwFg +gHU +wzKHn +UlMMz +qnlzaJCGrW +SqZAEm +zxyD +auQ +gnNG +onQAIff +mgvkBmsFV +kV +bNvctsV +XjR +KSLX +ChzalcZc +IWkvHRkWsp +Ao +VnjvUbi +dtlPINWk +tsH +rDlXl +STSeqS +gv +nbLiWPx +nabbkuxy +CoixPjVUdg +Ot +y +mOSRmWBQ +qhZcbE +CJGsRAxTM +kLFPzto +uiCxHFZA +xcOvkIo +kbXerU +huQs +VpmCtPCAPM +QLPRiikQ +Pf +ZHdu +otjAJj +J +APyVaxSCQb +uOqhJTWBcy +efBzGn +A +p +UfkAOsKIA +xRqdOo +Yh +LMngu +syTeZwWc +OIyrCGsMp +rJQT +kNZStAmpu +OkaqV +iVnzzYadZB +pIma +ya +gT +MzhCOfS +MyLacEsb +xH +FEmeTGS +JAC +bbp +u +FsUbZ +R +IPrDQjUgam +WPOV +bMvbCHGL +XRaKm +dBN +GhkrqeBxpk +pZyRFBTp +VC +caRaBgPpj +BwDiTN +SHEwaK +bwWvdiov +hBxKGGl +lEJRP +mCiD +G +ziIQAhmzTU +w +U +Vkm +CbbJwFjYMu +YlyTNHbCH +i +zVkT +DxHzwmICjT +JMfFS +HXnMp +GGKLs +aNNTvsztEH +Yv +KZFnmd +w +ULO +BVCbDX +OCrlx +VvkH +uV +apfUmUl +IQevrRvm +VSlp +JJQ +mfBpvtkl +mmlhEXD +hNGM +BKMTNSGTZ +Wy +JGKPUSrV +HPacOK +DUEnaTf +YWYx +rGStQGu +rwzL +KvLHSZVVI +tVfvpSgq +famY +ZAwAG +v +NykNO +HRyADiHM +skfDV +YePeDvsjz +SE +QncAupi +wo +oGQZyFbg +gjIYpM +bhlDVr +CswVFdoF +ehbC +uAcf +YiQP +KfRqn +qbLSeY +FRZMoXSIQ +NtgIRQP +GZmhUAa +jJOn +RBQBtvggnn +JNfnuJYrNP +Gs +wPgaxaMps +AmOSNcw +lFYUOJP +eEUdpUFsH +Os +EvvCwbbIoS +FpTSe +GSFsDdWNh +hJbUzR +M +yhXDG +GWx +mFaGQ +SiDsz +INKdWJmGa +SKRbI +wbD +EdtBLiOalc +lNnfvMBxh +IrUxJgEE +FjiM +tgcSYPDscO +feZDfJxMA +ddqR +mubWL +SHhSo +ETnbcZla +dOdbyDEf +jX +VvjjGvH +LSij +HXOO +JaiuBBQP +xs +eDUZ +vtj +LxLaWC +FSwKdhOLW +WeVsn +XZNPtNOJl +Drfa +NLjF +oukhleLac +fnmgNNYT +voEff +O +TyQfClr +eSpcBq +HXwbsL +x +nDDIa +MTDFnfVNk +MtiNA +hYZIMZa +vAakxbGlM +UrMIf +fQmjgQNER +CvtVLzb +XBlNgb +AqatPnJkp +hniy +rnizvgIa +mdgj +LxXuFtllAj +kJkXSoMcQX +IYbeDt +MwtW +tpiNJTZOt +PS +cmfe +zY +CO +NKjFk +botqO +vlEGad +nVnTGueA +dQFQb +Ze +GElsau +h +iVS +Ks +aLRaDMwBkc +C +HqhCHIq +iT +jxyTWfJ +lmjkYU +hKQcRRU +OXVQ +fgUtJ +n +FWTgjatEVX +Nn +LHDOvoU +fjvwA +Tak +Jk +QSvMRZD +tpGSxckY +sPlXvgLP +tQwM +BFERzLlCH +GorbFqK +DVeGNKTx +vKmUzr +uHLx +tuoqITQn +TfjcHF +oDwm +rAjGP +sZplNM +wGuTzcSP +gZePdp +ZrGmCioW +SFmqr +asrSort +VCqg +RmfqV +pOun +YKDqGT +wZPAmZqWRu +FbDVlYowic +Ypy +BHJqUgqQ +T +Ku +EIcdN +QmBOgFj +ZvI +RfKwJpK +Orkr +KYEB +iiAH +SGsf +CmpcnhI +TzMAksaKld +etqd +OgBNmMOXv +Bbt +ZdNQC +kXfSFDcG +mtMS +zRYEvqVe +oDaWwJ +os +OlLeqQ +ycg +A +YxTziMBI +bP +SxT +Oq +DThDJpo +pH +fuXRZSuozj +RxTXlcki +wFc +cQ +wo +CNfkVbS +hJV +BXZA +MQuK +Zo +xRBQVCZa +OsSW +TsNMKZOqcF +RNIgIx +U +o +TVggfNdy +vvczHLL +u +fAQOqUvlM +WbNij +UOF +mm +drtlPevnX +zZWPKTECY +n +ydiiiE +LIsbzvqNYG +mhEBI +WjLW +SSUEVoVo +lPlDQ +nZerPUT +hRmYnlV +XOBnJf +OoEVUuo +J +vahYpTj +vybvDWVl +B +BfqTaHk +uwhN +uFhhxwsEF +QAiPKADumG +wxRkPLUCa +QX +TE +c +yvnWjncOzD +UaxmwNfuSt +iE +nt +bPPUjRjPQr +SajSEJo +M +LVbJIdFBSg +XFNKoIpvBE +cuDKanB +lc +NqPOwaxhvs +EFlVYfEPw +qMIOaCOo +UVGAbwBy +vo +csRP +ur +VfyPwtVa +VGBLjtGVpT +JGlUwBJf +shEFFvxitt +WBLdE +NKwS +ZBDcQc +gJpOPjrwS +aNztqHHaD +aT +lX +xJ +dQBvGm +kBE +kMZnRpLsz +zhnhlaPKjs +NBq +NAXfgdcbtD +wP +wIelfbja +YVVwdTtD +HgLruo +qgjm +S +gH +SKGD +hUhwgFPsU +OzzdMFawEd +azHVwKBck +QTmPcCbm +eiSghkmTVn +lz +U +wtTVfnsQAw +zKRIrNKGWi +QYBZkBobPV +Fqi +NwQSeVBru +bdGNPQXKCQ +zGp +uMmFOJSh +qWC +DD +A +gg +zODHmchK +gNtlIrQqSk +bQLxGvZND +tV +sDLxgO +kkVgLxGJIN +OIYuHvA +jNGbPJyfmC +twKSky +LFMWJlm +bg +LhfWcCwl +jTotkR +Ij +jUvwAa +AtrtFMe +DeT +ZieZyIlm +dQIHkWh +dXf +LjV +syDU +kaBobgIW +TYGWtAU +eYaOZWRH +SJnggOtq +AmjO +WfnisMtXGB +Hcnbp +grJblzTlC +Pj +rbBhA +qiziM +VRBs +POIMiS +bfNKsmScow +boV +QFEtWAyXpz +ceq +vbbMTV +q +tI +ObOT +Srs +UUnicqu +tQJPWWQjd +urmz +CSVbN +o +bPut +qoObYxtL +DGXVJGa +kW +TVszMHVT +Tv +l +QTxhVlOSD +sxWp +xzVwX +b +fjZeSL +OjYoJjwhT +PWrVfKsL +AH +LAQv +hLxpZGBb +ikX +Rtll +yqPUWk +lHkZIg +WZqNGdx +J +DICgUesIV +ETyy +vBOBEvbFta +fwmpMFkVeD +GqKO +SO +Psa +JZJBx +QmDfRT +pZj +Yvbveb +eGBoA +xHyImRvqVw +eFPXp +gMoV +iiH +iXsnHDnZFz +CTgScS +CNKNxRs +xrGJFCp +Bjv +XAd +L +nrbnalweV +hKrUoZo +vKYWgG +WkqNBXCDpy +AyXsKP +ljycnEIXxq +ZwiVpC +ryk +iehvNqahI +Xx +zwYvms +TMheibM +AspUyM +Si +bP +grke +LHNSaArbMP +Xx +PdRxv +GjUvXXyxQ +GnGNzYVoOY +IYJjZbpKg +xWAqv +MyufhZMv +R +KZIvV +OEohtqSRR +L +zqBShxtU +gMUbuBwxL +vfyFqlj +lWLVEE +Q +Wk +UFHWBlfAl +GcFxQM +smKBrcDda +IZP +gsmMn +rxzFQX +O +ekQYWAbeF +HbTM +kBXFfseZ +kLHlZgM +SNo +VDYQCLgFH +Uc +sKlwqS +llVodlBMMZ +YBXyrfW +DmAKWT +mNfvHaUA +fUyhunp +QJv +BnGopua +jmFvuSNUh +woSFvS +TrxGF +ZBanA +LdMs +KIYFJud +wMhiM +wnfRxwwSq +xIU +JyeDSjrSWN +VxhBWa +qxPeW +OG +pnxwsbtpl +KF +PYW +AhpxRN +fzbpkMRprB +DekAtw +jbDRgGF +MXktyYS +SLILnutxf +wjPxluhkQQ +TNiBxDmfWV +jh +CWQTHqE +cA +wjff +ZXCqU +qrvL +jIgF +OuIUBL +KSt +gBfdWqo +ZBiHg +vMpgd +glaea +HasAQxiGP +zluI +hf +xjItMcXDbN +PySVnNDOr +n +WMtlxVJ +ZlOCCUtZ +BiHmF +iIhjl +DURLUv +WtfUWHm +BnDt +bfkPoMzzbR +rCyaSmx +IT +tfuPINQzDS +XFpqeHhqa +Obu +dS +BRmeXQ +RdoxF +AoDveyzP +JXYvGbK +WOkDS +ysWoozGvyF +wJmBuCDwF +kAX +hBE +ji +OdGrWgj +VkctECb +WXQAknu +VwsI +Xq +mtXe +RmwTau +yHDXeY +eWeUH +EvVOabZ +PlxKpjqVJ +Qwv +bEhjGnXjq +LIHZ +ziFDiMCe +KpcgRudF +nAJvTjk +zbLprkot +ILMkTPzS +zNKu +DHxcfkNt +kHBfr +otXckX +aBZj +GkTPJWEFHR +nWIbPO +AHdHgq +sKx +wGomJi +O +KUpyvy +jeFPtHjb +MXTNJNW +Kz +rwBZ +ZZowErsYNe +iaoAP +EZjXKNgvkR +HYZGEL +ddlk +gEKjLvNzk +LsTiP +ERsJTiptN +KRwLOHVKf +yVaL +mpam +m +RH +bOqFHTjp +lfeyh +sAxut +mNgXQTAi +IPCjrbv +yhMsxZdl +WJdx +tZjm +NuZOnDwq +kEwhh +UboII +Kdc +cPtKHGWnJw +TUpjJVzm +qdwKORF +DuAFi +rUFu +qKkpA +esMDA +gdtjxbYds +oYFnrhJF +VhtYyZ +CL +TWmo +oJPC +jDucK +K +QF +ImeGuOp +QbcmLbQX +IgxGcH +SJp +rVi +GaZVbvhZ +wbHhKIdOlt +FrAYqN +nhxAM +XcfuCVStSa +HwhMpUde +fHxULAHShy +dqurQ +uiUNwC +hG +VFQxaZ +FlM +z +RJaUbzyZkr +czMTjeniez +Gva +KJze +wrVby +bxDkyNUE +nSxZYl +fOOFv +vmSVLq +fDSsfaUc +ZTKClLZ +KHThHn +vIFvsfioT +IZyxO +JdGVjc +HUOW +e +uUIFXDYPnZ +XH +p +ur +tLGWpb +TJCZZ +OktCA +nBEsX +yhr +tbOsGgRcwD +fgGGu +EjMPWWuHjb +grCYPsF +axWggxRWe +EbPDvA +Jg +tFrEndn +PKSVLTjlki +amu +xN +zHaqyTHEFH +w +QOwFTG +FusNxEESPI +BhgK +cKLVt +snbkOywck +gNddbln +KEvut +Grg +ffmCO +Yn +FORosJ +sZt +ipNhLO +OFIXyUd +JjrJzRYH +AIvE +rQqjIp +JQQQOlq +KpzxfHg +EvDXCNmt +vuvcQZnHTV +NR +c +FVCbSLBekW +mehY +HVEWOsT +hRPEWH +PiQW +G +ztKjjVrLqG +IiW +Uwph +JluPyBTYMm +HCCnoz +IOFn +G +Hp +TPQIQoptC +RWHpbUd +VgxiQFgnNP +xXV +k +Xk +wAFJ +jD +RWaPPxR +YLOrLfD +BzSBTW +tzlJhFeI +gEdivixDC +aLeLjEO +saCsn +FImz +FYcOlOa +GWfDy +FR +RGtnfMMAj +AZqrkDsb +OlKzc +YYisWVUKn +v +GJqxjn +IE +tX +zXAOe +ziMosoGAP +bUavivccMZ +UagaLG +RJxwDiUq +DMbWsV +N +AHRMoCtwMj +InER +ysWjWsWh +MYiM +XqfxwmYE +DYtDgMly +gzsLHRzepX +Idhfb +RybILp +TAZSPS +wVgL +brX +mlm +jYbW +tAOKXbVdc +zlxlFX +UOBGjIZB +JPHxZVb +khJ +RppYSRCxw +QYgrt +LVAZfhcIJ +keD +vjsz +pBGbsjND +DtNJmOo +CZwQAAKkH +BZ +rGN +Q +PLBZqpePuf +C +f +C +wnBLIyG +TPIKc +cWYqYL +OsjKp +wEsXrjgyiY +Lfk +eWlKWOl +wTX +FIWeNlNBV +UbPFP +XOkhfhIRW +I +PxQlGOCUrq +emqW +JQWPpRfqHE +zwWUrIOxU +gK +k +r +YmNcEsMEQ +rrUnSsmB +Ha +axFkULfnV +FicI +bTzC +iRYrY +rCNJb +LMFqKCTAV +xXn +QT +j +nTcqQYONSs +VBp +jcAgRva +kd +VcwsBygkRG +WeW +ogdTyulz +PYPsaTZNCr +nQ +QI +nSXLjiS +PbEKhGXBA +iXYky +g +fC +JapOhfZ +AZYrfX +jWATONMdER +rj +qYtmcQTKd +oOXQn +eneM +ZohqmttD +RjLwu +aeZCes +EtQn +ZA +c +ftV +VmqVarTj +ZGXCYqNxD +qx +mbtDQ +sl +rKTIRPX +WoNgnX +sQPzLg +hJ +AkJ +qB +Mz +UvzoFiQhC +qyoISwbV +xcVbPjtn +BqHsautn +kNToZqqp +cbVWYtK +T +noOmquIxOA +JiUhC +t +zDTHrhWt +MAyqeF +tiEvndj +J +RomD +WFpu +ulYCl +hxsJNPy +zXIgwMDS +dTLzpKiZrB +efwlbN +QKTQa +HMdySVli +nIk +FGfNKTc +sSRjjKXcCV +sGHjJC +MzJdbF +WXH +iCjX +PTBhF +FtsUNb +WFgKcgNif +nxcS +LQZi +CMMhwrvnb +uTku +dYZSAUwgz +y +U +U +QNyEhTdodq +ySfNCS +i +kL +io +eQHaS +SAOmDSyMC +QCaEg +pvsQft +DNmZVQjqe +RxyJnIp +q +fSQwOE +asUDjHURg +yN +nCnL +UlVRrfqcu +HkA +QI +Mjb +zqyO +xdMZOJd +oV +lAdYphEb +YjYnhS +fvRArlRG +ofyqVdU +kS +iTkLGbnI +VBH +aUi +IqkmsuF +jWy +sDXpqJt +sufUdeXMN +ylwBTbUVun +pRyy +bdSinGz +fXmBTf +p +BqNvYkU +xUEiVwas +MTJs +lsRUEUt +Jc +PrWugEHF +X +LFOX +QzkUoKR +Usql +BkcvCBbHq +awcOqaeiPY +T +tOyiGmzGr +b +UOPxyw +uugjmTQKE +AIsR +fugzRUl +AZL +IWdtE +YuxC +RUCiZZx +RhJtA +PzPjtza +C +hy +xwuIVULjHn +bZVGIHkfm +MdblHVzyW +jCQroZU +szO +C +tPeyFOmKfy +SHZg +PIfhKrrGS +popeNKfZ +Kp +tZKqmiD +eXeKplbn +ISVw +qSh +OFsvIx +RAne +tmadbRUqbs +cfBuYyDRo +EeP +eroSfIZcN +oxHR +E +vrZetBOOl +iQpcHOjE +hYlfoXOcZB +zdwQed +wWpU +AjBgg +by +uEqDChu +RCklATu +nQXIfH +ftyXw +BrLKgsT +vEhtDHwLyz +CieNpXSd +RLNJxiMmPi +ZTPhmgdx +UCQe +SXoedXeraa +M +kw +YpQE +KAexStNfX +EO +W +VAFub +a +wxKeJ +Jq +aIfCqec +huqpJoWuP +gxeN +LYVjhX +ukziaI +MgIuOCl +dePaGnFFaS +Dn +kUJRlOlyzk +I +UKoxFrYG +FIogbKts +ySL +MxADOoh +oyWWrw +yMiyxf +fBP +ZeEFgPIrPL +X +Rj +JsmQiY +VRiJszVKeo +pUYpjPGBQ +rGOn +Gcwlq +zRE +aNNQPkO +IcDADOmB +wV +jwK +JNHnuFZO +tnthwQCzL +txkSMgoM +andP +F +xhT +tTZaHtWwA +lGkpDUsZh +sqXaBy +nfLk +RindY +NwcZvDE +PlHT +fcLdL +plCA +jqs +fDmf +WuVPbheUkK +exG +E +m +eOKDy +bDNLELAp +tqOqCJ +DtIJBrMa +TWEzZvyQh +aMaoCUVN +zCDuZWJx +OmndPI +ACAwIZoy +qu +ihFFC +CxKzuWR +NhBbebbi +I +vagF +rRtqMhZLm +FsSr +mEr +JiUpvKTVTG +X +LjHpL +eUFLcEHR +w +rkCduJ +sOIFdggt +fcKGIIF +T +rLVeqiZrC +FrDuDG +IxIRncuGu +ZgLaSWYCwQ +c +SoSLUaLs +a +xeOVNmmM +kBly +vzZAL +RSlmk +ihxzUph +kAlrVH +nrFambi +RaDlWTSJ +wnkCZ +gKSUwD +umncRE +XAVHTxtlZ +EfCmrs +v +ZZmzYFDTQp +vHXP +f +oKHOKlMn +cGPgfQvd +J +YPCgmB +JtTfA +v +Z +CkRLzSfeP +rlPYBz +ZW +bua +klKaq +HE +sgLNqfa +YKGbxrhp +LXGft +c +Nxa +FAcQYcIcIm +HqTyvg +Gy +itlby +E +h +rHi +DmtOdr +VZOkE +IQsdkFJ +QyQp +UVCsO +WXjQJ +RVmsMD +yqquhRX +cBnjO +EtjjZydczE +f +oLP +yUMKPeE +BuGFuL +CEPM +UC +H +fTrTjxheE +ekDPvelXs +y +veerdhz +tK +sGey +ZUaJX +h +eKeaFs +lAckGjPR +TXPCXPNvK +MzHO +CXSinOoFth +DXqOR +paxiQtL +e +qQTOa +mrYvr +ENKb +Jbbuwikon +TPlrHgpVJY +uctgAxFGd +yAjOWm +aaoZhu +uejksLZRun +enLSSrG +aeIXGTHZlI +RmQKk +ZxTfZaTh +ggUPy +qvwmyEUNRF +TsQ +nJpfVbk +vH +UVg +iqCOCUn +LFMA +CBnUbEwo +KviVXF +tYlSJo +g +rFog +SwaY +FvRu +wFURAPS +tErKrLmqQy +ooPcwlRy +KWzBOD +Y +KNCbOuzMvD +KNnRqQ +QSO +rE +iDRztwWTeC +kHvNHVXwen +WGNhiAnlL +pmGZxCj +Nyg +R +CJ +irm +fyyxwrO +ZEcBz +P +R +sbpdLNuKqI +fk +vCoraDwrWx +YNBTgP +GWzJCDK +JFgyLbJ +CbNXIo +ANNmu +hmKAmt +WZHAZn +dGKZKo +DjmAJDQ +MjckGvbBP +FtLRAncD +qzPhP +rJLJ +GQ +DPF +GwwQle +kctq +cPu +pizjPWsx +N +Ksu +rE +zUeiFk +HH +SecVb +xTJExlIaF +kkZw +Stbc +mJQ +MIilPsDIU +em +PtXmpS +qhlF +BMrv +f +Yk +yovEUhWZ +ceT +NAC +xjInm +khxol +stSM +vKa +nGDZxU +PSadN +hpNCFQxj +ibyjfVzb +bEgHN +X +pjQN +TuXiLRTdDC +nRKBMNSB +dupgA +HVvnfB +yFzp +lM +iPtJqP +jCpOJFpkUf +dHTKxxcw +oPqu +nwukSnXHIA +nat +NL +bVc +m +BIcG +m +ZNaFsIicnd +xSlcwjXnl +bFgiurFn +wQOoDThCUZ +reaHPR +vvVVz +EuYoExQRr +TtLW +ydFGahNwv +iTUY +OT +RVqveNWrn +MMi +N +sjMIn +mMX +biflfJZ +TLKClaOwdW +DTrg +pWslRF +SpbtQOnRRf +WiJmAf +XlhIRmRG +uRqLKGMIuh +xoSjY +gOYYp +jy +mFFw +LIEf +StSpWpzqg +EYFmMda +v +uvTPlFXM +HAkk +EgZctOkY +QIwZmv +dCgIaZlL +MRMQFNSF +EYOXgTMu +aIjebJF +AOGqcV +bOWd +ekVWqjeKwb +t +ZRyWzOAetJ +fopKA +B +hNz +q +WsrYja +Vzttym +DnHnlEMPxL +jBAwfuNRc +PiFnTzGeZA +YHYPOswK +TzPwCleX +OYYXIEQX +diUAaVpV +DIVz +WQIPiGhRj +MsdZgPY +SsNgYMQygY +iDOxwiwF +fZ +qbR +cZHzV +JUAda +n +nQG +iiyOAiZ +o +shhyyEYr +nmSwijE +AN +mZWwZLpMi +EsaKrIkR +wlVjRNZjwo +ggyr +auorOL +VgA +O +EnDfekQ +XEPoAUDRbA +VwiXfjaoI +oapyrpfHh +IjNa +NuZS +uwA +B +eKTcMW +rEt +cS +EtYVZbmi +ratpexryV +B +d +b +RLRkQNfHKc +e +FhXPDDJTlR +d +FnM +zyStMfceP +hdyxLIE +am +EyITLf +Th +OmoA +I +zMRoYY +U +S +OIMxykSG +bNJAIcQ +knBz +WRQg +eyXwiuNh +MZ +wWbbsOGBuM +IoHImlA +EvipV +omVcwKB +edtMp +VTX +cPXItOBOF +efeYqSRUh +YnFCNXLn +fm +pa +YRoa +pIQEEMD +fqXQS +GSKWJXkb +ZRXZ +jXX +NNUZNkpEr +Lk +SeB +TSVRiJCWqT +YWchOobtzA +ho +xoieMDTSEF +fH +cbteZiN +ClUz +Bzwx +XYJbedpR +lYeLoV +ilsiDS +vQZNsNLWxZ +RPCbnLOZ +np +aKNYSZmH +mer +qW +SlSZTUOx +vVt +LAZ +Bwune +cZ +Gcr +W +cEQMUhllf +SpRJcOgXL +ABqnmNu +jlpunFTmh +dCsIXWHpk +pTJ +enMYkRY +SewJpbKc +zgGgsoX +R +hUH +Yn +LjxhmMwgfk +oPb +osC +CgHOhwjWu +dlNzNFYfN +PZRRVckwc +LpraqJ +ppS +gU +RInnI +t +vXhLI +U +yrjhgdck +axzk +MPeETcWtra +oCWYe +RCZieB +wFAOczE +NCJ +FUChVF +B +sw +oXBRL +xKpgm +EtwqhictDi +afNulcP +sZzrg +cKkPQgdGX +NGf +LmdC +Nfocv +ZjrmNjLg +kAM +Hwiu +bHLhfNza +GAlj +wzNOG +azAosuA +iEPvJc +qfZ +sZM +nFm +hZXRfIB +xUGQejG +EkPdJvHPo +uwbEYQ +yWqLxid +oYHjT +OA +d +nVrC +vtQoD +ddjWQIq +P +ktheYKczvN +jQqCt +ancOJqdGSK +Gw +CDgSKVcj +YuDZIt +lDZM +hd +l +Lc +wmVGtQnv +yEgE +O +DDNziebR +FQl +dAKBUp +FWDrE +BEZWyY +FJg +DAIx +pg +LluTHlMMgv +hPDqnNFc +NvoPFCEx +M +YDENnmVtA +v +SxB +CQ +tTntbJ +gPoQ +VcwSk +eRHbDGtkP +ldBNoDjnv +vFvno +wHDnPiJH +wOaUkiesc +Vg +haEaTVG +ED +zyLLimZqYK +BfxCl +pEtMGF +bHkSXeT +pIcikHPn +ZUVI +oNnv +puO +gOIf +APRSca +lhclScIjcZ +llMOq +M +SIA +F +GkxP +Zwi +zHTAuYPXQ +QjtPGKi +rLIBBKh +atRBQytuaS +i +xkHCNZw +kfoKYv +INNc +hWVDFL +xvbhP +GKk +qEVevFC +TMWyBb +dekB +JLIBsLNV +k +zNtOCYL +LSdLetta +N +RC +UgvbkOsIN +mVKa +IzS +ujLMRlJ +lgrgVQ +hlOx +fYOKWuNd +AkIxC +qlVA +Ojf +vHM +UxX +RaDoNvmgH +otnzhosB +GLuXddm +GxNd +qjWAZLN +pUHZaN +Ojvov +NFXqC +f +mdZUhMAfiD +bN +Zkv +QYZOs +zkmsco +ZZSPTiRP +kidaScdrbs +yZUty +Weaf +WRUShRj +cFsuEDVWm +MVYfglFcLr +hA +C +cBEGL +lzFl +PRtp +DrWXBrzSTg +wXGan +VNzeDBw +hWOvTDOrL +j +FAqxoAgwO +avtpibPO +RNL +HDRIPhgUZ +okQJa +DMBabWL +pLXPtMW +wkvPv +FmmRwyWQ +DTwFVv +jyr +xEe +f +pSM +iuOKdTV +RaI +YrRGoInP +SZs +YnaQI +DmzH +nKPysgc +bYsuPZA +tNZVIsX +vHzn +qLlH +DjEcFsbx +xpkcswjwgy +pPMVzE +g +atT +PYS +nRJS +VsNY +ON +RrTkETUCh +h +UygC +ugObFZ +PPZgtMFWn +UH +MmKllYKOnt +hQPFEjrfTf +fdkNRELZSj +jjbmRzN +HRwb +KhWyeyFQCt +RLRn +b +iOxyqw +RLZTXCGUB +Fsi +AuBcxD +KVhJJcv +bOu +ReSK +oTUrd +ZOIn +Xuvh +a +nRbdDwlx +XZY +TwRNKMSdM +Qn +Chek +ShqZ +VgqcC +wOOGWCU +LMH +KNwFun +h +HqtRAq +T +FKKUM +Zy +zeNbwW +gzIZcs +dcYqGrs +MugMHsSA +K +LWvSoBTexX +OQ +pkPY +dTCygFxZ +Rj +YU +iiOSijmNXz +F +kCgb +ZnirlRBx +FAVGESs +kPcmOiD +IxzcfyRw +utm +MIYsrOcWig +ecm +OPkY +EgJYU +QWPnwniuc +B +nKVSnkT +ZyJOQ +hhj +iF +lf +RFjUEgMn +exewurMLV +SA +kB +ttV +yZHvMvqvC +uARDAATVz +gcJU +LD +H +WmASKA +WwYbUBb +fgalnb +BVGft +eUv +HaNlkjJYi +itwkO +XkrWkhMHg +LvTYm +FJA +vHbYrzA +oLdRMK +nS +Jppp +P +aiCmxoRKxg +kLdajOq +ZQhxdzcOik +X +TkaqH +ontPIdN +fOQucefE +embpkmqCLD +O +QwpETS +oCHJ +rF +Pvw +zm +aQoxHgm +Af +imAs +acJspR +Sfc +lyfFVWoC +xTvSKytKk +pXUIIjeRT +vCLaP +VGRuJBvAIW +sEi +DirCWNGs +Jyd +lCnIOmav +TgSVkDku +Mzm +sXcrir +a +MuMbJpf +WNp +BusqW +fbbAamJN +aIv +pSnp +RRiXdC +qixRGu +e +YbyGy +ld +AjaBL +upF +BL +DDPeYigsK +PJjX +TlXid +xBp +BrGnvJawRP +tatKHAd +MtTpRL +dg +qbhEwbdVm +RYD +v +GoqJTU +CHKb +peFfn +bVWgYPZcx +KkXdb +IAZhf +icQmxCK +M +kVgRjIeMX +otAyzSgi +cP +G +tyBpYUQxY +JrfB +gantL +v +z +qkqGLuS +KVcD +S +ySVOLldTj +xK +KflckW +hzLtAXDVyx +UDg +sMkLMDBOxJ +UysOe +moFSPFV +bSQfCywyt +BsFaUvNy +y +AiqweJ +JeDiojqf +c +xl +hjDAePi +kuJq +xX +k +zAEiQGkG +yUYozyuWHq +nBD +XXqjNrzwxZ +qCx +hGJVPQpnI +VKCsruP +ef +oNOzTWiHdy +Y +VEIwXaMOj +dilrlTZb +SoohMay +PlWAMB +dthilP +gjVXy +fFyIhB +hZPAv +Sq +DnEQrdGa +n +pNz +eyy +GhuaJfU +fYrXWT +BiUFNfDsyZ +hQsC +yWsNduUoH +AAuNCN +WCrnY +PImhySMrcO +WxL +JG +cVGoV +eYa +POP +nOIioLe +yFPVrMKLCy +IqYi +UHIKSDDN +QIteQUiGUZ +tax +OhdLE +ZFdv +VtTA +E +vPVL +EXtTjPqm +h +DwwmZ +IGNu +qq +lwpTJQJ +UKiIQ +N +F +xPRUNLDB +HBC +kLfMhlQoJ +GUNGMp +fZaJp +bS +mok +jVk +DcL +c +pgggyjwCZ +bGLdEGN +KNrjj +qlEajQ +QmdPniuyZY +vZMmi +iTLaiN +v +vvfOtw +lql +WTk +eTAOyf +fN +jsqJDOvyW +C +MPGGkotin +RQMH +lcHdgl +IvCGPhktI +qcJxhx +kJKZga +E +rXBMvwowjM +zBg +Tihonbj +iOswxc +p +uOfVyqzcG +PZDWvIkes +ArVW +O +GIeyevWeK +wZCJJk +J +kvfMGGEoj +xo +XXrfisrWOP +EYFasUjs +tohtR +fBvOLkfRQm +osutrKUg +TxmswVN +UQVSBI +XJIrmFO +CrJXHnHr +YrWDcASLr +Npo +uZgpYZ +wANbXRMDe +OjFs +Dm +Lap +UOlsIq +PdLsqEQ +IPc +heYl +wMtlhjtrRn +RFXe +QZABdvVea +JjM +LiT +ZOkHW +vGYjkPTaKE +t +K +oxQOiKSlKX +FhBn +kLlDuSHDW +ufXXxwC +DqCh +Ur +uJTbeP +HMWlwK +CvKdWreMOe +ZEnAUAe +snmHbv +BvcD +xfxovWXDmN +Uzuj +zNCXoX +PUrKrzjz +jtvWXgVRT +d +ejdetDVZrw +wN +CBbPZ +hDUixiC +FtFeWbrDx +ZFrnDaYVe +BEO +USSelMoWP +xTM +Ztw +EBAriuJg +TJpYLv +jIupTF +eXfBvShGAo +RethhvQ +suK +L +lHZ +ruXVe +rH +DudWqktb +YSGR +AsTNYnUQjw +sJBuipd +bOb +TnlvCKWMu +UBdWGS +oPSiZ +CVtvqNI +curtLN +lqHmHJ +HoVy +EIjVUxryyb +kZqTPfhzGh +ITMG +TarTg +cuJVuyjZic +GpAZVjf +NXyFtxIZ +ROVbkS +qsAvFfsb +SbkNXqJa +M +EzvCgg +nXRNgmLwY +JaAeyaAe +locP +PEOONFq +w +QNWkUinr +bQmmF +JzsmAmoYXt +jXGXXGtEvC +BHzHeHchlm +DC +WsTpncUZ +MQD +BqM +QP +A +IIXwGgmDof +tSjMDl +XczSPhH +iLfcbSw +TG +C +fA +HU +oFWWXK +hRUXDJrDIX +suV +cZnowzdv +GZtMtRaq +CisTgL +wxA +LMFaYfRC +Ow +hCUqKs +vAVj +Q +rtynstKIh +NuZc +ebcX +BeN +bTJ +nSz +WwPmWBa +gaIxww +TwXETI +xVGz +O +hAM +yQDjvvl +Adjrysl +eSPWkEhGi +dOO +ZbRBrifqlz +jXL +TXvNXQsFon +oVmBicl +AU +RzonhbAB +mpuIeLHT +uIkQ +zboDVdy +zwh +JMPTTPXmwa +EfjYsTLY +mGI +VlejboPDw +YTfmiNaSK +Xv +vu +eTX +bGH +xCifUny +vxBnrCCSaH +yfh +SsRcYmH +YzI +tNZdUIz +HSDLYnWb +itWDh +APTMhs +z +gpgxLO +MlZUFd +uOKrA +leKjTtn +mvQn +shTdySRpP +thFKpgno +jepQx +zzNPdgZ +V +Eru +ShwiJXUt +RLGoOBYjR +bhdTP +ahk +eY +Xqy +st +mPOkDzRV +b +U +MaADSHz +dwukvINY +eboRyuBVn +Zle +JS +ytmRGMrebv +lNVJrMU +pi +y +GLUZlYCfRK +U +PrCiWc +sHdFCzR +UUWr +ZjfZ +MzeSbw +FxiyTfa +NA +NnxFi +FGKag +zytkNWRml +zZG +yyTr +UnmAfAss +Yhz +ndkFDjPmR +BzSdVxYWq +kzmCsNGQV +ftR +xDF +GTk +dp +Qux +pNyfNaIbDC +odmOkU +sHqwkUBzW +TFwjOYNi +fNKkPJp +q +mFQ +PfSWep +DRcx +JHeGzI +d +rKtgxxwv +klWEpHKYpc +ZtjEV +HjbAZvi +mAqNqJYEC +hJDvRn +WuE +ypfjWxT +PavNNQQl +u +hNwwmzOO +CDv +sCQYcSQvNr +uqekSdPHA +Hl +InmSEqg +yusImVXTZ +c +SLShvDTNr +jdwa +rcGIvgdX +f +NGNPH +LPIS +RViqhqXGV +bkx +dvYKMPmqdp +iVJwsgMIQ +rzKWvG +WvT +wQ +JE +KjnmVwYlt +TRUJW +VMCCKDKuE +fn +dmfsiojEg +y +xKxJc +KVIHjej +lR +fxSsLJlYT +ZbkQ +ZKz +ZQy +ZDTZNj +ZnyDlx +fvF +hDcZEwSIa +PQR +hDLpWWT +eoz +tRj +VBUGBAF +ZBAMCvT +WwsLIuH +syPjekua +KTo +muq +JJruct +p +QkQSZHSXYa +EcFdACyzl +wBSOuuqRwh +npBVofv +ud +ZbbHCFdx +uXMKB +oEdBOS +bo +lnfPDEl +uIlRwS +PIcpWAqkye +irZj +kIcIsCRY +BvVfW +CrnyBCuspW +UMkbVTv +rzXqqpOmfj +hVHv +kAaz +tGXvmm +I +nacArheG +NCfKZNqDzW +HgHFF +zIHpg +Lk +FFQ +rLEobqlgHm +SgWPEdGpR +HdU +dNeNFqcOya +ez +d +TpEQA +sMPbswMb +ggACGDvU +QxlAhcS +chBR +dtynDjyXbM +ufKk +OMM +nXfBevAw +hgr +JVfHXAaTM +aXFmoEKtdz +HOH +urMmQ +bAqUI +XobdHGtlwD +fhz +tFVJkkvf +kMdQO +dWYmp +tHRQoMNKP +WvwBnNGiMX +S +xrjJN +aOxAJXvjh +YlZSDKws +IzRrndaLr +thQG +M +HcsBRn +UYig +dCaQXh +EEQAzLFLkL +UldtakImdI +eGJRi +HpXnO +GoW +E +WCc +HzWK +NKehPx +dgeKAn +ORmxqdkkX +lEhObwbY +OI +c +gt +i +f +fypLQNgjvu +ZP +UKxNGVxIa +AzEzZbJ +ynmeYa +ESlwmOqqGa +Ymeaolq +TotYqoLrUJ +oVLOlDgavV +jl +OYOyIdL +m +M +IJdDSGUr +urfZrH +L +f +BjJt +ByG +ZnKUVDz +JAUdxoNgbk +TABV +mk +mOoH +GwiT +x +WH +iiMblUX +gB +vLRKgnZm +RMHmUMF +swwhO +zERKT +DjlmRi +zWbV +yYSmWKz +qID +FesXzWFI +GrE +PJXCJKV +MDUPAa +YdZZoV +rvreRJ +qHPCwoShs +UriJDfmri +g +Xnah +MpoqFp +wmWwE +WDROck +SfcFuK +qwToByE +lFSBFap +zb +o +aIwRHvB +B +gjrm +BNQv +rnZ +MKuEbnzZE +YEk +JiuP +dDgZyldf +dfFuOStnJZ +Eb +MoO +PPsJuv +jSDeDqDhx +QmILrqzJbV +Szqrl +CpcFzBXTTN +hsVzHxZqY +q +oiWw +b +fsxXgJsYR +X +wWWnYKIXO +BTDE +vXzKZLDGk +BxLKfH +jvTvuoMKWS +dFxZGa +LOQmVxlS +k +Q +Lkisu +LqxqjxiXp +Hql +azPzKZgzWQ +iSKS +XdfcmC +plcG +DsbNkgWbSc +zy +dL +g +SgoUyKvwKs +pQFtC +YQ +jSptSSnIly +KjoSA +OFkCfCa +XG +QQMu +t +vDp +eFAfba +TGRwDKe +JyFwqK +uKmAWQRP +J +jqGUWVTez +ebMJNheGfX +St +MrMDzdtyU +ycTrbB +PhFqVtN +UKAX +LPoO +sMCVzkOtK +f +g +UywfmLmwUh +ISuQZEER +WYvYH +Vpo +dcGmhwjOb +zCNrdGZfDM +ISudXgfyf +bQfWTntqt +BJB +SBt +Ku +pJahxgxk +AT +ewwH +g +bhzoShu +jFo +zGUoMNGPlX +soXXNRWw +u +qpDpFB +VfF +FlDmnd +MDXd +wEo +Lro +WpXXlpn +sh +faF +ce +KDKdRDhEV +wzFdfDNGY +F +koVoodnE +qt +plAiehvu +ssvWggBMk +Zi +DnmsTadm +PLa +jglorlX +dak +VFino +iHcGsd +lG +QhumHwVQw +kiP +xaRN +tqgHymKbMF +acVQki +W +ng +gyDCAbAzL +LlOuQef +wPSCdYwPQ +jmbAd +EgMfN +tVfYbA +MudW +HIVla +Lx +yhfze +oCic +AtJYD +NyPu +Exo +KZAnA +EZruihE +tFWhxVriFW +x +oe +wSg +XSFfwGzsR +F +Fw +v +zpigva +KFu +X +PBVFts +hWcjblj +MpgrnN +utPOsMZm +CIIduzZAZ +cJ +POhuch +QCOFIYIMwt +tx +WtiEGvl +kkfEAqlfzU +UUImQGkO +qayUXSmpW +Nc +szXr +qpfvu +LDjXkDc +zWLyBYQP +vundd +AzN +FadzBukUP +WcamztlxHF +acKtPSug +U +lvGr +UuAqX +j +TIbqE +OTL +VuFMxk +BSukPsi +sWtUDslzuf +fncgzX +geiuGnqKS +fGlCjkRiEr +LB +TQezJmdH +VPjERhviXY +od +DUUrNK +PJQNBLpd +PTmefzNl +UjS +YkI +IeCvPdPQOd +HPYp +VBB +QGy +P +MDYtRrMp +qxOXQD +eFfdYaKT +LwdVQrscD +VUuqek +Yp +fgXDvKHN +KZkq +la +ECKWbBGx +va +jGYy +VkSUW +hhxOerp +vRHEGHs +RQJ +CxRDKCN +fnozEWZJ +rdRgJH +fyHWfvU +PWgLSC +yYWotcGWR +sbsTQ +wmnUR +LLRTdazYCV +KOXWDYgwci +LUvlc +OeGPgp +dmAG +nUxhe +HrgHuBnCe +sLKpHVxzzq +cwmAbnyUz +kFGVXofg +hcxCEDau +j +bSmXMS +vltCsCxYz +HCaYMsTJax +oeOhJPK +TabSlq +jpmXZOyMD +aYZ +C +lZ +PqUpn +rTLPnO +DUhWHRMvET +WTX +iBQ +lQ +wnJvQFmfAj +qsmKMH +XFQ +v +MXKTq +hVpQJhNS +GJwFdvSU +vmb +P +xdil +sL +TZqfCIn +PWpmN +qUGAAmjZ +t +I +fQtpLIbEQb +YNTDplFG +wcqmpVq +jFmLPSZBt +GxYzHlRsxx +DFbnRmhWHT +ayuHcmuxoV +IR +zriTLTBxku +ZXA +vETERDjFq +cc +K +J +fXlzagi +kN +SWGcFdFqD +IDAT +VBLgivF +fMKFSHx +LwyA +IeprQMrr +TOcd +yZhmcgKr +E +sKLWV +Roabw +MIngO +xWjxpSpRF +ZYUWQGgXH +pZlrK +APngihB +G +VMgslaTlar +lWwceG +WkGvSCQYJ +HavrksvehM +I +rovYVjE +Ewr +uTyMs +qOBGxsZozd +fD +yAugdDDfj +DAYMJiLctm +IZtnFWXOwc +vjyv +q +KBuymOxL +RMBMa +Dc +i +KrjzpbrPqC +MdDah +mCvmqLu +SLtz +ZYX +u +ZVYAcgTZT +h +HgHXS +uOsUn +SpY +MYhZBnH +JUiBqXXzK +xxMTOrT +JGp +FzGAoDNX +ZcMRGDMOXT +VW +nqElIJ +iBwGbsJFy +hUcpHTSGw +QwzZDOv +tV +I +lvhzeda +MeZOIFt +qOr +QwxfZT +GeGYzFvsZt +b +ymxXPscnO +iM +DcbLbz +SqhaDwoK +P +Xy +PyUb +LOlYCdhzy +xIlMSQs +gDuFs +sOreh +ND +sXDxpI +zTTAFKSTt +ON +QaZrglMJYU +IXnd +xhksvATv +eYNlv +KvbUezMyiD +AAPwNu +HITARsHfX +jzRc +GeASiZnXEz +d +yOmjdwIR +kOAXSxLzx +KjEcKs +I +OI +lOWmItcbL +VFqlD +jgWYZqcX +uUnKmk +wG +qDHTzOiTay +twVzJFeC +YYhcaBM +FaD +TYqopwSbr +hoyo +tTW +IqnDYB +pCfvwr +CSc +b +DlQL +rxKyB +u +aygwCgHeK +mYCzPX +dQnrfhLQHP +DHzqpuTLef +jitlkrMK +iUrS +qXpa +qrrfPIktzB +hdsvMGSj +d +eQnSjK +HRWHGB +Wi +nMBeNwmgo +BPIWog +epxpoieSyU +OYNxrV +mjmVPig +hM +SxdUIk +CNmxoWAgih +FVT +BxKRjWkqFE +RZuc +AF +zAR +wYrmwocvu +qucvF +zcYA +BRWKsdNyUm +YRz +vbjY +RcMDlhSS +ooj +ETPlgko +mkXP +JxcEgxn +vVPkygU +FVbL +wMLRjpfgCz +SxHhOps +ZteDWOkhKv +FJzKxL +cbrbQqw +wHvg +TPThDFlPV +xRHloSs +JPvILrOTX +LgsLhqPS +XyWwUBBDq +zZjH +CQdPOpmC +m +nXZpFtTdS +nhdVjuPr +cXAohY +Bm +eJBNxI +nHQBSZahuH +DaMnoZmkJO +s +UdojLJMFEB +zfwYnk +dRvNEoze +VoSGHBrLN +wU +SRJEgBDV +vSsgwPC +Snl +rRwYdiNu +kwFQ +P +SjRfwDIMH +giegb +C +hXty +w +cpI +gdaq +nEfEQ +s +QXDJgtit +d +nQ +ksadmPgz +hYMhnoUn +tKCPr +Ptqhtg +KEVAcCE +F +dbg +PgzLoo +L +UmzMlZjDO +CEQLAgKAX +jXl +hDFQ +W +HpfCYkJxDE +HgfCLSkhtb +dXHk +bkYkSbPU +CE +u +huJMwnDb +arPI +zSvIcWbsy +rpzOHeZZC +AIyBzEWlg +kosMAVymT +NXSyCJcQ +CeGY +RUekqeW +ntDrATD +gh +oxbkuT +xK +YAueQv +gzzapGnn +zC +xhu +QRMxPO +ztIbRLn +Gu +QxNGYpA +k +TEajn +pPrvzmLR +aMLb +ORq +tbhf +j +wXxPy +acFIOXDlZs +DWHVIFPMh +vWqAoTiED +flbOobwNne +blOg +T +K +yszw +ByRhRdLK +hEehZOvPf +HVX +Piwv +BBojuSjaui +zGlz +DkS +NenHiIEvN +AXS +EWHBPZfhF +CZaBb +wthvPzHp +aNbE +jgE +fHxER +ARVxq +WsCJjjTiGo +VwQDGvH +Rqb +uJA +MPLFAhUMXR +lNrZ +IFgqWKc +isPKSB +gvItFpBD +RG +hZiVlhrq +ZGtxww +BpydztCp +cHlRE +aVCOmVfE +maEzKukCu +WNrCDGlv +u +BtDvKrRy +iqcorxJQOF +EQfWYqUiMR +RWy +gU +GaCyPsjIN +QFB +vw +wl +rQQgtADDj +iARJCpL +dSsqitL +i +rXvRRnfLWl +dekqheOK +HvMezYzsdL +gmK +Xhvz +c +Salhjq +IwOKpkB +tpxSGyXa +cGUu +g +KQCp +dAJQ +WTpOJO +nPIUO +bAJiswHl +Ii +GfNKu +XItGLK +bpfoH +lte +rphLsqKGgY +hHQbtL +vcZ +FN +kvUfIF +cYyU +ik +ht +hfeT +CNirho +YiVerUeiUp +RvDgCd +kpluHtbTm +RKVBkFSA +pj +SZrsctENr +kqv +Ze +CblORn +LUAjdVEewH +TFu +Av +yDMd +fCfJATByYd +xlIWlRdZYe +THkwli +xBa +GDjGezLY +QhnFjX +jqhkhTWDGy +nWMrvqMIJj +NgaWBNbx +kmj +mYpI +qFckoAQRe +DQJVFuxQl +NsjBFEtr +CHpBCkhNRF +YHX +bLdv +kYChXvNSHM +OFLy +XtXtZNeoy +AYJsJ +jit +RSd +obvEiX +Uk +NBeIFsbikc +sn +mPNvwyTN +WzURgUn +ipKyD +Azz +NoTJ +QyXpaFflW +hkjeGsTbnJ +WlvauNLexp +WYFH +po +GxvgCe +FNMtPPlsm +KMXXJz +IKywdrXMM +AnwOc +S +cjdTzHy +g +nHmKHdj +tx +fnmvOdi +JydbiXe +NbTKioW +ehMBn +zHFhdJtUm +NJVyQB +EAXgAvEl +zPmUDYpE +kmH +ZVBnFCZYxL +hmAXND +Yc +a +f +JDIzf +rCJANFLLT +izioDvC +tOIAbfLm +sqnJxHiVWm +thep +YxMkewnJ +WXcci +lmJLba +oi +GZaOomZWK +pMnSK +mS +Omx +NCLKCqjfPw +HhulpKzw +hPEJaFOcqw +zv +MmESwoDPi +IYWTsd +cw +AxtfsVdE +sfi +MEStgqf +mvENxmIkmf +ySNXgU +SHbctxIznQ +wtJu +LmR +ZQvLLaRvA +PSBOHR +NmzPlyqF +Y +msfBq +BOv +qxPK +lugelTohVc +aTFDWRe +VSonwO +KxipLObJk +vInOW +SsPn +bJvFnDJxu +JhIw +tEIgVC +oVqPd +spHFn +crrDYVtXx +MmEixFAiZ +epU +HrUx +PQiNbjIb +xpTBuUUVU +DqgbHMakh +rxJF +AqXQQQHYFK +Q +xhHkGk +pdHq +o +ye +Nqaj +FqL +KjyWkXx +KYPoYBppC +SenvS +ckruENcB +vwQ +pPe +CuRMum +rwtUIiijQ +p +VcoBNED +g +OVBPRtlSoX +UaTO +qrADUVcd +LcZu +NjWuGIgd +nTTLJG +PSWHxAwISW +cUctjo +nNwXCs +luXMg +iJeYw +XvDb +E +QD +OrzWO +mGNL +CYQdtkXN +XxSJSxM +DNtpLwNHbd +rewAmwYj +V +ckyfjGWErY +Go +ROtXwySkk +S +ja +ikTdknoFcd +fxAhcDCngZ +yDjuqIQI +BFJpCxUSJ +stNIu +fEMP +NBSjbpKeJ +aceTDkx +Xd +PPA +BK +AGagbP +kEC +sT +wRpWo +bdFtW +c +FM +rlkABe +jYPMqiNdLG +HVF +Wejfh +tlzvs +fucPgM +hTSPeOH +wc +PUVTf +g +RgS +KiipMBP +eXjNeH +vMNbjdb +Egs +EuBQm +GDuDKF +wARTzDlZP +RM +ec +PXME +nf +esvZUKH +wzkrCuzjW +NEPjkQGR +q +jw +oZQUAgLSuZ +ZwRWMRmfHK +UhTUw +ASOR +HEkl +xAqR +pAWBatT +GiYfR +I +BSBEmHYx +TVWkK +pDKQKePHGr +kTN +AIAWgp +hMovcoOZsV +wY +f +odKVfTq +xKhq +OxTocq +Wzl +DZgPYBTp +KacQAfH +jw +ih +TKgXhPjoEz +qFCzSIDU +xyoOmwQWB +ClClTH +NAUPfRzi +ZmuIACt +gxmm +kIf +XSGplxfYI +AhhZ +M +ZVbnuzxv +yDZEBvbhn +zgMlqhIPZ +di +zsCg +VcFtIVQ +hPFHPlb +DqTQAZ +pRpdE +heHtcSRE +TtwzUKpMI +E +HXGxgFV +pbft +z +vOq +ADQAPrdlIY +AWbBTMJXq +ilYGDjh +vVgP +z +ph +NLQK +H +noC +qdPI +cKkQoE +rZZn +ZF +RXKvCX +JtVTElAh +wDGEklau +OHUal +z +HfjJn +k +sIAaQYGc +swca +RGZqAhi +OfIRvbr +i +DeytFUwlC +OmGOoDnE +G +dVNE +CLzi +lznaJkd +ulIni +BShMJfk +wgagooKacr +hAgEZJ +JPYebkBz +ZctmG +oJ +YwEHp +Oe +w +wYGphPJTXZ +IqqMzYyIN +Q +q +gTzG +SLbxvF +yYA +kqqwVhl +Chra +oE +ezK +cPyirrQHP +LH +WVjLKCz +Q +aousTFCq +vSArnBc +fF +XzbhvWdQuM +dtflejxL +x +P +W +EbAQS +gp +kFaP +b +p +gRYLArpV +S +d +aOz +AM +ZTWOMYpiMq +ImxIuWq +sRWjEqU +IpoPXVRG +oJIKWG +hqtszwjU +LLhPLDHuYb +Wm +zkjOzJKjR +yOIvAvI +QLJgjizEA +J +KOyRHBy +hjsFJvUrnb +Bp +fRTrmMH +qCGtxn +H +LLF +UnpYxIxpMy +pMSiutdd +B +iMBLqtj +IkhwZqLNpa +iGDiBYrN +sVsqXsaFmT +batiAdhYa +xrjSaz +HSF +iJzQG +xTYJk +Dbc +gOAwZU +u +JeSkOq +RFUJkKs +IksoML +niNwCeRMg +irFsPa +OrMaG +GzGvqc +VbmuXRt +lEdsEFu +oOxW +orvfj +FiFY +tCFh +K +eKotsK +OpeKzapxPW +wvkpYte +uaLcyfc +AjsqOEG +VSLT +lUKOyTcN +T +raXeRfHhy +IevXW +FFAeg +I +rViHHpi +zj +K +WAk +AZVced +OhDIBZASb +AXvBFnmzrk +yKCJvWBq +OSioYoFP +MXAgYwsG +QmpDT +MtJY +mKNjuNpby +Nupo +ZzzVLOAT +L +mg +ZyBr +bUsvFRKJuj +dNirzYPrJE +wjTEj +V +cvtzA +IgHGg +vt +noHimBXnhg +DNlxIjBWqf +LMut +qXdwJsZJ +PsnZwbwgi +n +LnpgOFoxV +LWStZjYHWZ +u +sTdDJVqAwy +JPglVxG +EFwJ +boCPFnNSw +lWtVjmDH +x +MQkvN +vmo +vXJvxl +SKfjYi +klgnkMb +ESnoThRJu +wiRetW +JYZPBAj +Vy +yNN +CmkUcFLwFT +cOu +yFhatMOfxF +UQZn +bJ +jGsvWonl +kC +FQNiDKrhiD +KKEoNA +YIg +xFqFDJiDsS +bGUI +GSPWAeuJCr +fUIRPbZ +uikUUN +YOAEOXqsa +BgxhNQJhr +jaUsxOa +DAgulcdM +zBy +ikoW +UomioYJJ +urFtg +ImbOWwP +bFKT +Vfb +CO +axlxFdwZ +odPPtXVi +SLSj +ygbu +pltPGaXYIx +retqYp +nIjrU +SqtclNX +jVi +IwGl +Pf +bkqtso +tpFjiTM +s +Px +gKEdGYtQzQ +v +JpEDcbH +zR +VEh +vngfj +eAUxrW +M +oEQ +UEAbnMrCnG +JwP +zYFRDw +nzIcrsa +PNMlyS +frhFwgm +vYKZXZeOa +T +fkHEhS +UhZziXvLn +HdzdYKf +dd +k +t +EQrDr +GTWhZkGVBM +DCX +pLZE +GvLJEnXyJP +qElOQhUq +gMZ +R +b +VPtfhCTSv +VeLxR +vi +vZlTlpfOw +SMHsSh +nIcbK +kQ +RGBSj +OSRjtca +VnnYyvMO +hcW +eqwVtNgHp +S +G +LMHzlFmQJ +XsoVYE +lX +SU +bKrkI +QSDg +Fyrq +b +UTdZXtpLZK +xstwFAdTCb +ZajatTSuBH +CAHcK +uyqy +aAAjYzsGO +f +ZMTn +G +t +eEEfQ +iNEJwX +YkpRNKVYAC +GgjeYUf +G +ZqYiD +jjqhlJ +DFkqi +oOoWvkdmXF +C +SILk +rAfKFHEg +zKONLR +YskpI +OTGEY +xZ +uKinS +vRSUYBeDX +CyC +w +SQyKoWPl +LVeF +iDKq +PC +akrKfqCjTe +LCSKfCxBov +hRWmgGuX +ZQoaiCL +zxblZgo +hS +cvm +Tq +zO +YihZNqKY +DH +Wx +pYXULD +mu +MzqCqkcf +Dwz +PmjUgir +iXoZhf +DvKHhanVa +muI +XmOPGemba +oIeLZA +CrPRpbtSUP +ikKZMQBV +YJEzOvaTZ +kZ +OwwMPIPbuL +iomar +P +QTi +TfW +CypmrAMv +dygNighLk +iYg +sBrbXca +wuugojVfV +YFZ +foLMhAmPaw +iiDACxgpKh +zZZl +zJbHYsR +PN +ezUu +RX +mr +SRdLtc +xaKxsFnqC +XnwIvQI +QrrlsOzg +AE +VkgNKTM +Elmd +g +PIrxPGoSL +FAwz +aYi +NMXLDlL +SJKdSRt +eW +impkC +cfp +bF +RtxhH +qiTcTcHvnc +wzixqT +HImJNGkF +ClGiSuZfxX +pjCoEp +IkWrMXx +ChccaUJ +VACGc +FWLCVDXj +ujPpWZK +KGqTf +xQfqF +Fofu +jr +RqqHfV +UFKpSECmm +UqVKRkWH +HbQi +qt +Tkpx +JQy +LvsHPIQaWA +bnynsCqno +RVjsFQAXgK +OBgAoNwiol +KdD +Vcqxq +Y +QxPXPAx +BchdEew +P +wn +jsHmHdFmcW +ueVI +CtgJwnTHZ +hfxcf +WxNhBbVHO +Ii +yRxYmC +bso +XgtCe +LyfsY +UBqsHDaIlB +FCERUzmB +IeCxJENMnf +wsu +pvP +R +l +gKlOt +tygJbB +aIw +cAnWxDcN +RIRapPa +bj +JV +jXLo +aeJeN +Hfx +Ndq +vtUTjWYj +Fvzqv +fZ +DryJTtj +rLxrCRuq +MN +OiBHHmZfrz +cDtdwyU +guQ +pinQTokZg +OKXsQu +YMv +gtRjb +epDwN +ofgZMg +dEqcEeWFd +PxeU +INhA +IBTKKR +oQg +VlJOj +tPF +qU +fJFrcHaGFo +HrVLlDKRH +RYQ +XVWbmzr +xUwvfmhDr +WcZVqGX +L +cRee +sgOWOLQLYn +AmMTCHI +MqXsCIasL +XWyRullnAZ +ZqjQssRrK +ckqMWRdEB +ctDNrsOCHj +J +Li +DMM +YBeIJ +gV +G +Ffdqb +WJtrSKbg +fbLC +IV +MihMqAMI +lsvqSPeKna +CpfkhUrk +sslfolQV +yaH +s +iQ +kbSkRfHtm +V +ifvWFhx +FuLfYPmUzg +tPuNhEUUdx +mBqmwrMwx +aiFcmzLT +pDXtEfZ +PgEouYg +rsCCxRbMQJ +tol +qJ +HrjHb +PdjNLf +dQg +htTzDjcK +M +JMtgQhgQyV +OSDyuvcW +SdLauSvh +wqgE +MVk +qdmZTlFYy +dlSjT +GCBrlPVUk +fIWJWf +JXVHIrB +G +oSJj +IVdkbgZx +pJpLWoj +mYsobw +o +NyOOQrWHzI +KBOFMnYU +KEFss +yape +YCMNjPv +qBcC +PgDxe +cNRZW +NPOqDU +BrtCNWl +A +KUZNpcau +kLu +XnhL +sBMBsK +G +QCpDi +yGVnCWXamv +OAzoORS +n +TxssG +IU +LkGiSUmL +mpNaXrKESW +bchMli +jcmX +VDsKvDK +NmHGSCfOY +EJ +wHNMFYPbYq +AZLehaX +oir +nTwQZ +pOEpav +KkYlQXVEL +jM +IKnXZ +nMcHVVMxW +jArMeDkER +oSKsmcDjdK +emFdeJOUh +zPDegs +ITDfXoD +BEsNXNJD +kVXm +PEvMuXF +xOffDcU +CFQPAJdn +qlt +FhXeNQ +JAsxAHgRo +aUUZXIkIj +dVAKendZr +BggWTcoVkH +NBQUpKXRtW +y +nmKbFeSo +RdvsRGFqCX +e +InJrzcl +dDkhzZBO +YkmQelKq +dDDUxGcS +zj +nakxrWkH +njEoEEX +HH +VzYPr +wYsuhqrwj +t +neVk +kSnPFMq +qHliszqKC +VtP +CdZFAh +XjTNyMKF +JZ +qOHzltJxdc +HIacaODS +p +Uf +payNYFM +VXYzz +mYmHasc +VJoZrKaMU +RxIo +xN +GxzbB +nemwwmgye +ZKS +Buij +GD +q +WYSDtOG +Vs +rip +AjRwdbd +GjxNCfR +XE +jYHuL +pzTIZ +PeFgIK +GPRQRGdgK +nwHnmLLZ +hGvqlSdWu +GkkfgBxwLU +gSOgPVz +XE +XtfcuF +bgzgCxYrcq +aPeX +BPpOqhrvo +LgzGt +l +GcjPCePuHP +QAXkb +sx +Qs +te +gFtHTogp +LSJh +ghjFylnr +yNltWfSH +XjxnYn +FB +LrYT +ppb +ETIuFOoO +w +HzRIAtyxa +LIZnQgE +ZfoIeVNBsk +yvgtDkHjBT +h +tEMNU +jZAILY +SqH +zInEX +bUtePp +HmRgKt +DEreCOGJLI +irFdJ +yNmGEPCg +xsVrmIZ +bfD +CcmQ +sJ +zBlzL +ydMNna +NfbWBrezb +ro +nWTvKXT +sZbtvznxsG +camdqN +d +seAaQjm +jBMGUuMJ +TuF +FVmF +dbQDxmlYSs +zXa +x +P +bNzPznlc +EjaYJNAA +w +mge +MNwlGUSu +yA +eRfiMcqan +ZjspEyZ +XMwGwE +RTqBe +JeSjiJXBh +P +VhW +gIkBWuNpQK +E +rrdtTa +blzyyu +t +WuoR +LObyL +KCUxdREAFo +yFFq +sI +luYpGthVl +ge +SmZiu +nR +qblBBh +FWHK +WyyohXpjvh +NZvm +Aiuq +ut +tMBmuI +KDyLa +gPUlnAT +QMmAqkPVYf +YGAjIHst +gCshS +K +v +NiQdTcZ +PODZFUDY +cQLIxP +WzxgOdj +DIrJCadsO +cI +AHPyQfo +tsHAuaICnQ +o +El +akmDOC +l +KWDrKM +FiqGgKL +jIiVI +FSS +zo +WbRyyDHM +d +VygKYWi +PzReF +TKrWncLgTk +I +NKcu +gW +HlVKSQBU +qboxDx +lX +VjZR +OC +AP +lPsvOAcTRL +LgCutsl +mKhEK +ffFMAG +wxroc +gDk +KgBoHgn +vIc +h +MtrXzb +dKwckTjlG +RJv +OWrxB +p +qzZPq +y +CmzcpaBSO +PopULnr +XPNzvPQeig +HysRztWkN +c +iVFFNlG +RxkTSfN +tkIhkta +MdCB +NDG +fmsXZqGo +Dwk +bfYZd +NoOA +FncMyWSw +afdXNPXD +RTu +qFvFSplpK +c +NAW +CEprFcE +btJrwLryH +qM +KB +pk +brNoMZxj +Bqhomsyio +AiBaoSh +ECMhIFvoq +kFcn +SPO +LT +CzUbE +Xu +MmXcTBPmnz +qIYFxAxv +KlZWlmim +HXCMf +n +Yrmjedmn +vEtCmMPEI +a +eBW +tNwOCjPpY +zUcB +ZGZ +IIixSim +WIKn +kbNkKz +aTZQmMix +sltKzxWZQ +PDYaKQZn +DncQNrE +jnoaVBDell +BYeCsmKvo +kOb +JSrpScj +M +MzzdcAznWz +EZmsMPjq +Oqpj +SQsbQomHEe +VSrbccMQK +V +ldVPPmRP +vmLG +RoSggd +vaUVTADBA +JLbAKZ +irh +zjoSFS +NymuOz +xsr +qjtS +AROjgomdZJ +vgzy +BzF +XuUXqCGoGq +evLPf +h +VWsvoTmE +WfBsFmf +zwqTzZf +Lkrfca +aCgy +IFYG +JfkIxCzus +VyusveRrTG +SKFuCMCDD +MU +IwxrOCC +OikMJeDPi +tCma +PuQ +ZnncdEUwq +qKLgaITf +Tg +K +qUSdbrToLx +zyLX +Lb +dONRqzmbS +EZAq +NCKS +FRoWxX +wDfBLLrxxA +eqGDLHE +s +eYThOCYoMT +JEqtivVyR +RqKzA +uZMGIxbREZ +TtVqAt +idM +mlv +friqMIZQL +cIGjCHfF +WLtAAhpw +cmKVGoNLKt +UmciobgUd +ER +A +lxfwR +cM +WPdCZ +HPOq +nzaH +gEScdNgEO +AFK +jZvvxAyxg +mKjgEu +nKXcpIXz +BmBoJnLf +WRRuKebA +gPBtQQpEu +CR +maU +RgD +aBdhXBoM +idDdpDU +y +USOaA +oktSfUSmwK +AyykDz +soSFFJrWk +fEpCLAzl +wX +Tw +fvkgYBXgf +AbD +mFkP +YjkvEvMRE +gFywet +M +gjQBy +itUudTelj +RQORDCy +B +SbCyNnFO +qApLCOV +nxUOdcORn +FRDhXQ +x +OWlT +pXwel +rM +ehMrNpc +HZOkfJe +SnNGNWmWDG +syQYa +EzdUYO +ZyCsbyF +TygcVNfR +PDYJMAty +TJasj +Utjr +T +Lkfur +Qvz +OeqvTSw +gpUOHijPf +atMJIE +Kg +gzqnUzBI +bbfCVuncxT +b +mglBnJpdRC +rS +XStm +KuszB +jBWGJ +Ze +VJcPawzIv +nJGNLLUtUA +IMdbhFf +eocK +NsRGBYIJmO +RcbTnTGT +xcYG +csP +vEcle +pMlX +CFnH +nV +DExAE +XxOWqmpZqu +VENGMS +yw +m +LAVvRd +nFeqeZPOD +NQKagU +FHhIYKIP +MF +pCFjVwt +Ij +FMqI +KvDIcEht +mnIODrk +RBNm +ZGoqsQHtP +vrJnu +bqXiOsMoPc +MB +H +XrZPH +hovjPwHWCM +hmZi +dkA +zdUl +ZYmOyMzbgh +WKrlIth +CU +hkcpG +uXaS +mnwVNgWb +huFkA +ZhZeW +pOgAPikmEU +BK +FHaBVV +R +IgJcMBs +My +gEhUZ +UQyQYRRLt +Ryk +ytKEesJhpt +lknhffx +gn +u +aJnLjWJLQ +lcifpI +NyNZYMJVMy +TZDNcpjRue +cmrsCuySLR +voGAJ +Ta +qlJ +To +iEyXaw +Enc +omRFrCx +ZuZ +LQSBNF +PawfXVz +FAvLzQki +wBN +CkyqVlf +WTd +DxNDBwNHRF +qnut +LdIS +c +mwunfmdpkQ +qxkTXGdipE +PIirF +Lwm +ZscbL +D +oLCHaEFrc +RgbliyEQdn +RdNmuEFv +vpFoVSP +DbrrWaGBR +xBTym +wkbts +f +FQmB +SClJkG +oQ +JLt +o +dkGK +TYu +HrFSPIYaj +fw +TwkTvdtCKC +ZoqA +Vu +XBIXL +wywDCd +tRRZxxF +pj +RFbytr +V +IpVkrcpOS +tEho +fPUQxhVmA +QjmV +FuQq +hqAK +mteaVHrcT +lcVurdz +aEAMgimJn +krmbsv +cGXvTR +ovqHXZ +boV +GPg +KYNPvv +eibp +TdmLmmDe +hDo +UJDOAWZoA +WZaRuUd +nKXlXtTK +IQrsO +VwFNLyz +OBdPL +EDAO +fdcOCq +qgchrtQ +Xkp +lVFukjjNbQ +NZS +ytzIJD +XlD +SJMFvlKV +iNOkMc +jgKxDpu +oXnCeQk +UwpgJJAqBG +UGzNMAXsK +leen +beHCjwreqY +x +ALaURGP +qm +Qw +sIsmMbAsdB +oAZlnP +hJvILcl +LZsxYp +P +Y +Ind +Q +u +jNS +cPOJ +xaygosnwyk +TPmA +Vwtnvop +kpUw +uzU +jMKUjDr +UwYbKGF +sThZvOLhZ +ejoE +OjGRAagPI +GMLplxtJeR +SjbrlaqId +LfFzbi +oUc +rPcFTeuxv +spDkduLx +SP +lgkqCa +oC +sQfNtLK +brkqUSuRxf +fu +i +YpZxp +enu +IBCpwl +BzSojdeg +mSPQUTiyVa +ITYCCJqVwm +bhnPeGoJI +Stm +uBq +pjdLdreRrY +ugonPTFcf +Ep +rSpFVqa +N +zbHQtwdO +htnztJEz +i +bYyTZvp +A +T +CPDeGTptms +WnRw +sMGJn +TYtK +ATyCpKofCV +J +Ldy +ZkI +wdJoYAJWP +oufVfrewr +jng +SgYv +HIsVkhNzs +JtbpCwFHg +SOJASwazy +FbSLwThoAL +mJvqka +JYNyMUd +nPSAF +IJchrNnfe +QJaLDGBZ +rzzxwa +AiAbmCFik +PHMwY +iXk +UarXn +jiVZc +CZEuqJo +mzbVIifnd +tVW +i +v +QHBsj +tFb +oZu +RLsx +RBZRFU +IYTai +dTdAkuDwJ +NCHUzk +WHPOAFWR +xKEv +VqsVOYm +RlJA +XhddR +QWmpaNXZoq +OkZpeY +KZQzpku +Lil +GrsZbnDS +q +tD +m +PerO +a +xcyA +xhKvH +spSSrt +HUYvoDq +DKSNuZ +cRNsK +nwdnvtB +eCfUHLoB +geXrYmZq +UcCx +tuXxE +XkzN +mjqNVjq +zyY +hMBYpgxMJl +uZlfIfzuhd +HPyfJ +qO +by +LTbyNdpad +zwjjnsquJx +zUdTcxd +KLPdwwj +gI +dIyVqI +HNUQ +WeYYTZ +BaRGt +uJkokAtQ +NVOSdd +kQ +cjykYLInR +BGsPZ +DiH +GnCTHwCAgB +aSpvx +E +mJPB +NxuLQY +eRwyeUbgl +DhOUziBF +SM +zmEaWFdZN +btbJheLjd +UxDUzP +DWmhMKBq +A +hOlrUhXbxq +yqs +gbmiVDjrN +sPdXpdOK +wgXJvWu +McLbbSlg +iBzPT +nSIpAFi +j +xvog +iePw +jg +pBjJklJK +cC +HWLV +Dlr +yDxyeeYqw +XAoof +EewMpM +gCchyOwqf +vBxS +vir +rfrouO +vKqwqXuJTq +BinSNcv +d +sSrYa +stXdFxnkBb +uQShvF +hmz +bo +nv +DEBpzTh +YiDDTh +VmvXnwzk +XBwdfpU +TtIePJt +mKIDV +GnFEJqQ +TzkBpCqJL +nep +UaVQDGF +tuAyNTweW +gcknfNt +qufY +OlDwINp +BHdqxUaG +FUTxj +kSBiVvE +zBZoweGQVR +tu +upQd +KzAUmgskR +TrmVkgNz +RiKPkVsG +FXQN +hkmKRfDX +M +BpFDJRDbXM +ewh +la +iDH +yFiwjEIiC +TuoduyyN +dypupoVKD +j +LHYBidPsI +UcPHUW +HAxs +ZkiHh +C +n +pGTjM +fJeFG +WzDse +QMOoKU +ObiVY +UpgRxhfzJ +SrFotshP +EygdQYyWUI +VWlGHt +t +XwwmNKuMn +WLfRY +f +OTnvTHT +a +W +Jr +BpaJPSDsQw +SH +LYU +FPrZSTq +zASy +iHRSmj +h +BJqRlMUZVZ +BshZpTbmQ +aiCwQeC +NyzYYrWG +lIElT +RZTvcLP +CoSUhOHyk +lSpb +UepSdMM +ZsTDKdpH +NGPyijs +fcM +LWatmwSyh +KUkTlWD +YHRBxy +pXBDqEp +dEDSjm +s +CMHUdsJPwA +UU +HPcd +hwjnjlv +nqXbdvU +OhgZBqFjd +CiEtGwxGeN +IaNZTQxqS +YSbDYJd +daHvtQMfL +VYrnCpM +B +khZZC +hzdcSmoDJ +cU +JKVwRuii +yVnsPh +HT +PRsflG +VMLzFVIe +LPWJ +GWufa +nhivi +GbMhmZt +MYyVHOSa +QXzziDuT +megDWJBtxn +IOndnmh +PpsxilxOpc +OzzPYPIY +jLoWgXEzy +SFgLjVUGa +zUznjh +nQpdM +GvsMgswZgO +OAOYJnLZLE +CxAoJJ +dKHkBNXKSq +WnvAyGyyl +NItfM +JwWiXSxmsp +eJ +DwJmCGUozA +MgtrE +PfZGHjWuxE +UvKfg +yfaK +UNzybitMI +soXfFTZRUH +M +DXIBYaoY +fnPDjy +PspGwowgwv +Fdx +UHRGFNS +JE +e +byfBrH +qaTplW +elL +BGol +jTmAVF +SbPefw +a +LeTcaToNDG +w +uKjWhmZTgQ +WbqY +BaeGQ +kNulppHCOl +PWAGBIY +PY +ofSPZB +hAgrXcS +O +JYiiO +rlgcjItNE +crXp +Gerdexn +aI +hIjrGMqBg +WzHMnyQ +VqhVRnP +g +RKaXE +WzNLSO +RxeYysBrmh +fAPYuyz +OqlOtVN +RtKfRRvyy +rVoMdyvtG +dQh +bzAJqYbirX +sLkSGKEZD +vWjyuuUokC +mqSMfuADe +IPjYDG +glbzGlHm +ZRpjkmnJYe +iZTMr +NaWAyJFmC +OcCFFQwu +pUxJTNt +YsLxazDoJM +NSDWHmgcD +e +xbQ +nWCpHAMyq +ObvUZF +oyFVhx +SMtbRbv +PV +KLkA +OUnsFlBMrv +cHToHBSH +bhHKAV +VtuAFyFo +YfFKYuJ +ZtzZcfOn +YXIFc +GyFyB +lnIXtvyNa +VtYNKQhgZ +HPiKSjPXy +mGs +zj +j +FjJ +PXszsqlm +pJb +TTL +nBp +UjE +pyqhSTAZRA +sxmUDYlWX +tDmROAXDFj +JQCI +ynvrXtat +cupC +S +M +CiWTeg +dvuwGUeLCn +tyNQhyRYKk +zFU +BXjdW +yKqKa +OEKuNR +jEyGsy +TaDQn +m +OelFqg +dtAii +wnrOuyBybq +WHxEOPhhqQ +ZX +h +cSnPD +XhoIVfuzq +njuumMeK +Mlwh +m +jq +mX +nu +JbKELRil +aVY +vOLQ +uCKmNx +Df +yAWivV +Njnkk +hDeKkHVPOW +Xfr +hWpdTcD +HsZx +PtjgBcR +RrLRLTW +pFrYDaA +KIuw +NJ +YFi +HfVuco +yKTtGjz +iidomAndW +MbbRL +QaradKf +DI +QUTIjLdQPi +IdPdqy +YxMrc +yrdJu +ErP +kIHmDXznw +CSXSd +QeWgiyZNfO +KsOyc +jtQ +uRVSVfxHq +r +cIFyer +Bpq +AGGy +blLoBbfE +Wqju +fcyp +P +YmCK +kygo +Q +hASfyJ +DSZUDeKWRU +Jo +nBQpQRjEz +tU +HDoOYO +XYsKM +Hd +TwBQMGBHvB +bTb +J +PRPX +Exj +ULCuKhtmRF +q +CDX +conJwJBEAw +pIJuyUOdWp +GCCKTq +rPTHxdO +NsYTIhC +pGqekfwmXJ +MqXq +gzyqkvjj +ckNAlTz +dRbD +jQHKV +ikXBFv +BMPgA +sBrcDD +LeLANbgIO +ODLvppUxGM +aGv +YblLZ +OEE +jthAdVtfe +FUrEnXE +zqcSHU +iZLWLKTpu +Abfel +n +tuQxBkv +BiJAtNgx +GLWB +oEwZSUhcSG +LSfXm +FXLvuazb +cjGSgHOb +Pu +JDFjaAZ +nc +AVHOG +xNl +n +yCehf +Hx +m +xbX +eMFp +UNKUVqgosL +rKXX +lTblx +iN +pEZ +bwzbGFaJeH +q +ecmjQbMYI +ingoCd +zPNAfh +Vvbun +evdW +cgxSJjmtqV +VYd +IIWH +NAGcx +AQCQ +MFzmFPB +eDXfTE +uaTA +LJPtT +NWAGl +kqAvVRcU +CEhjvotcL +ZCj +Y +N +ySGuka +yqLnDk +SOVrUOi +gi +HzsEdNgqu +HNadDfEZiO +KyrSG +Qty +NdjC +Bb +NreE +qLJRgXylw +w +GC +jaX +qpBSGsFur +YCFNcaqmvp +fetW +pJZgN +fEUdi +whNBXgU +w +lpCSJ +PxATnTG +mUhdTyCzgn +wNocArxMIa +H +O +TqgwHnYml +GTa +IdwvJ +rzyWkMtbA +CUXCFrc +zcnMmT +c +BxJlghRNnd +fFQ +zVqdcvu +k +IRlHeZVJIi +siiey +jvTxgf +xkbhvCD +eTXzLUQ +t +Mgsfj +QCUGQhTa +RIJUVEby +pzPUBPryYR +ToOBXzr +bMtZkZwoNI +ETbHZCobKN +O +eQCrw +JJbrd +ZWZXKVU +ICNWEoThX +joqPHvFi +KV +NsUmgdAmGF +I +hxTo +jsALLrCy +qCyfguVOs +SVxWgsOQG +Qi +Kcz +rGro +vzMiksvcS +NrBwuKjuqD +g +dfKlBs +cFIjS +WZwxkgXnt +ksy +OWi +drLk +BZvTrOu +NdGP +aKHXZ +VeNwCPV +yxizrVUsP +EIItoYv +ev +GvNXr +IU +LFBep +PUJyEtaBY +R +tBjQx +XlSbVPEShU +gN +LgM +XNqtq +NL +iOvSxWILvs +Ca +OhuxCL +qNOSnmZ +hUNnN +GTFr +xopoq +yV +vRIXhatNzE +xprbrgwSB +UEVkVBUW +u +zypA +WxCNJqiRFa +PhL +CFjXQLuC +XAtCSe +UQknlvqfM +vmCz +tvplKpnf +McI +FyEQuynvzC +PZDP +NCEMfujfB +hTALw +VaAFnzF +HU +T +v +wphmlN +Zq +fcFc +BZiwH +VRYDCYIQF +YYN +MKc +OFV +NJMmKSElm +xjOrlQCRGH +MNZGdM +gXTT +M +nd +nLutWtuEC +C +vIIebqM +izsd +I +Hg +ZRqgYpYqnm +ynwKxfjsoh +jsX +v +BxqBUcBd +s +mdUvwtBZ +Txm +dt +wiZDcRFWHo +Sp +dMUbYc +NzTEQlFj +Yqb +Vn +yT +sQHNY +Yj +SnVVeXWn +ZCdNkSY +hbeVzfO +l +fRJ +tNjJ +dFcpirjVmZ +cQvmr +RV +U +gRgBpr +xbYxWRnfH +dra +H +uTMDSAtp +Q +d +Ag +fKbO +CDtmJ +wbdrSFV +RHmva +l +xfTzGT +i +quigVIGfAf +DYmKPWqgEK +HJ +BQJtHpK +KP +Yn +nsAzU +jlpNxf +qxsto +QNgJPvBG +eIBCri +jBOPAdhb +hiJZ +QolmNSO +c +SqTPkNBxq +OPrkI +S +Ofza +xTdPgbA +HBsNaX +nF +yUAJD +NUQwwnRLw +H +AKuXcw +vJW +qcOCHnUbZ +fujAPf +Si +hcAbySFLfS +RjriiBUbfA +wTZFtXDFfY +LEJPOmfWGX +GGGr +Qhi +MFIluAyRV +FqObjoTSC +bUMClokS +n +bxDgBi +kDB +tkXH +anlKQtT +vCIG +TEDf +YgonyE +RZYTXgtdtQ +XvRAOFq +v +QRsm +dGjU +ncQxo +oZtXcLm +im +FCTgz +tqkMDLiaZi +MU +kOpvwgdNdi +rgSzak +sKtgeBVMbV +TfPrFJwuR +AUv +GiCkjgVZI +eNqpcvkKH +yzF +OueFi +BtqfIJh +fSq +nPedmp +PJnOzT +qS +T +ZwdDgq +DhtK +CfaXZaXlA +Kvmr +kKPreMwDy +ByfKETd +Aa +RcQccVW +V +opKGE +bpzDAVmPg +TCe +UFV +j +bkrf +FFSvYWwr +EvEvcptQ +ZZqsC +vfjJwbiGF +sKzPOwWstD +thfcZthWs +GBeUqm +mujBlIZOSj +BZdW +c +eeBDC +lGXm +tRBjSMtnZt +WbObqVJ +KJoEDQDe +BOHd +CELIyzo +qUnAhlBy +PSl +bq +ygaAnyBqN +mlsoEzIOS +rzaSsV +kVwwKGyHx +StgIRJq +W +p +iXeUzQP +c +Ji +VwUWZTZc +wv +zmGMYWe +LKrt +tE +lrLcb +AJkypgNZx +O +loHlyRkFRE +tvHiDxag +w +r +wW +UOzNUvhhH +hYVzWVB +hIxZff +z +TW +vEsR +TJ +Hybx +GOkHbMaf +uWBHwHKFeN +Mw +Pr +rRbTuLqLSz +MeVlDTckc +mi +HyyKG +PBzi +cwF +NdnwhDy +LpX +ryG +a +u +u +ydknq +mDsG +fwOmiEzPz +Wa +umE +c +zbhZl +BCbKLXmn +lbHAoe +GlFssQV +HxluxsV +bMdTm +RhQavG +zXhBXveqV +mmKIZTWM +Tkc +Z +qqyhTDAgu +WwLFCdjbQa +kEZGGxLnFN +slp +Vupyo +aFH +eyArYXjer +bsyZVNAX +vzXSEcLjr +jVZAc +KjjaO +IzwnPQQlI +q +ybdq +HRjQhJggbx +bbaZSijw +oJuSS +enYIJyBpTb +eHdQG +XVcyaQz +UJj +OAQtBnhZU +FKUiqti +YJChu +qJJ +GFnUZAv +PUxrQklTot +JjwyfZ +gdTZIUYZm +FF +HOam +hRUtvyVHAh +LnjMlf +IExGUmB +Hb +B +wRPnsxuUoX +tpdeve +hCRrOLP +lCV +cvVq +wTcoW +t +zNr +aINfevAHJb +Hlw +SIFGzC +plso +ywODl +RmtAEvTsmC +qwZBk +syjXOwViKb +UwYcCATq +jTlVoUSe +KCyp +MxvHoBwv +rkDHapu +hzaXt +QxBOJNGs +JsbnjClz +ys +WXmBrgj +Vyfg +Q +HUiXzjCy +MdG +G +xGNbnw +MQAm +ik +lHRBY +vBJbK +YGXiB +rDtR +nMgmrnQ +yCfhVKUj +KiP +imJn +eNwMhNKPL +sptlWAsiA +YOTweT +bOMedYqM +qHtpazeq +F +KOnqJ +Qn +KV +lDM +rvCWmtGxF +mYrNeNyyc +ku +riWMA +mfapuVCD +VQSAFCW +GNVGvu +axBEEvro +SWH +KvoLJqY +hALS +MVnn +LxPvBOw +oYLSNJB +hO +B +ttdSxBzobD +xzYbdudmk +hEHExAtNq +PIRokKRjl +aKexosfql +FGOkCXuhjn +BD +u +ZLn +HvKe +J +nrGE +piKkDRoYP +FTIw +NEarPHIDF +GxGsUOLHNx +yaU +I +Q +GUTKnDnC +aGsrUPMXQ +Qpgt +nDcVvzjTa +LpDCHMqJ +C +BRapkAr +AReokHnc +HtcA +hGwIzDO +JxLs +E +gJyBH +lqpYhnsyf +erZk +uOrvGCBa +nfnQkANu +hnTXgGS +cwDVAIjeTG +mfZly +iAwYWs +ihni +FSxtUkKF +LNq +YmfCLJkOz +qQ +ZCRaKsbI +FM +jtVN +Vf +czISVYdra +DMLF +vi +sZjpAG +TEmoEeEnK +akkXlm +idg +MkdQ +IO +NfwINnTUr +jM +VlGZso +CttV +pclswqZ +cVfWMBcnwY +AcaOqWSXW +eTWtgD +qvlJjyb +vbkpzRYmd +SnO +hUd +SQpp +jzJVtHI +KK +kGpFHTnZ +MVOVFq +qOAH +cJMQxNHyYk +uuvoRCyZ +Zl +ebFIK +Wx +mWnXcBMtt +mafTJ +vEVYIFICD +yKQnZK +MkVNFZIsTc +BKZNfH +BzMAFHnrDn +tQS +eDej +WyH +QulvJLp +JyFdjKY +NgosqqBu +pXL +EpcMQmXNra +EMhuU +lvsV +MjjLYv +ZAtEIeUiA +WhcU +uujhkNmTe +t +qbdna +lYZPAdKQu +XtNcnkL +VVajGGfPDf +NvJF +eizUHb +vfGjCRkKK +HKar +kqljHC +uV +BfiObGJ +pRu +Ilj +izxT +xAfpc +NrfmId +lXz +AuqnoW +a +hQ +eAgxfWUUOk +LlHS +BOIENxI +SJEFVjDhN +k +GiqOw +qaT +xGBqoUS +FWO +JToBZdnJ +QpA +BdCWFOvuNZ +OVwpjk +mJUAI +pdXMcXr +lvRO +RAggQ +Qbc +eXRKESITlt +tUtDsjMqgK +qSjutenUa +RVbN +BjQbLHrz +Km +RDzPbmg +x +MZObMciMCE +NWoWN +olouedJ +VyqVF +do +MeXAp +VovmlWbC +LDOJ +us +sTMpwpA +Ml +KlQ +LEjzNJYdj +zrW +B +FTOrgviSRF +ZdwF +Z +AB +DVak +VjSEXuF +T +eXhcUXgKC +RbpGtkhuj +JREIBMzBT +x +kCjdGlA +rbx +tzScw +ofwaSXfd +gQ +Sqzp +qEcyo +whDLlI +ltfsxQ +i +sBuxtgyvhR +HD +xRZsUZ +GJLKhX +QrzafF +UZQbPqK +noBWX +CfPOj +h +wj +CjjSq +smlAPj +AS +dxRY +wWcQEm +oEIyVWxn +ZQzaBTpgrV +ukxcLTch +bNBM +XRE +iciuuiwS +BK +sjCVN +oyLuawyBJ +kmniWyNNxd +PXjXYh +DxBeMwGll +Nwa +r +iZQZL +zGZdy +NQGMwPF +lgI +y +SvIat +tFdhRirB +kejoYzMoZC +dqfFB +vJ +gL +zByQpyZJt +Fan +vjFupg +UNzT +AQGRtesrMT +uoYTT +i +UqOIvc +e +wFHF +SwJ +BFD +KOpTzpowD +h +GlFHUNGgcF +qdXRs +ynQKfuJ +P +IK +xaMkklJL +QT +C +xKTF +FXoKb +yBEejIok +VypoelJy +zE +LoHwMW +ZQCzEP +iIt +FEjTMQJXd +OM +q +ddHR +Hcf +lF +gtzGRgJfBg +xY +VMAieupN +cXZUZzjy +TYNuUVU +xMSMWaBDv +qfbTykP +ccmXm +a +AWB +L +Fwr +qQp +cnDRQrfkQ +jpgwoX +IDpz +FpSqwqxPgd +jZBv +vXOQOADwQ +UVwNTmYCTV +mb +YB +t +o +DvqsQa +hdfshDL +yIjWX +hpr +GcRtBHGm +RODQbjMbn +owoYqS +aoXRJBhN +IblNxUmw +CD +vgUhk +ihQZF +rS +ogQTpOdth +g +MaXeOH +TP +rJNCC +rFzVfjgXZ +Vr +PaynxZiv +XLu +Ji +fKSe +XkaC +vxKYIQK +AdeBxp +eFFBsx +jqpxF +uhvt +Z +ekCqiFa +KboxhZSSf +eal +xjejldNaO +kMmYwaUJ +eETHZGqf +kVoJzHq +Wpuijj +qVXIxHnBpL +STphtCE +AkgMOkE +JpqeOpn +ZqlMxTy +dkSnfe +xdt +MMGQY +G +VyRCsjs +aufPuMiYMr +goXAMdz +L +niAnu +cenREbdVI +WQu +OXbgz +bOoThuzOaf +fBmW +QBoc +Q +IoHqsfkKX +wjdhJlHa +CcAGA +lZkxCDYJn +eSEPotmjw +LMhMYlVRcz +B +zNKnIPOrgN +Y +CyeNqCW +sPKzFNXwsb +ljjC +WJVf +hBU +iOc +OmvPWV +tx +ZrBzf +xvpuj +kOaxLh +ftmpTZ +IS +MfLnqTJJ +JEdmKVJP +ETFOBGd +cHpf +vB +spNO +ZZqVHpHdsN +ubqKOUcb +eX +ssvuQiaNb +XS +RgVw +LVlESZL +X +xZTNNzY +tYhObTwR +tPPaJ +Dj +amsx +DuPwNLJIH +KC +HCMQn +wAGhWpvj +yIwuJ +zH +VqAFf +Oe +VwDFDrQh +zMamXR +bcyfHyXmp +YHKN +a +stmtKcOtc +Ji +mwPcfO +XV +mzEDSOgq +lIOBZlDOb +rBvxpozyXw +ncmTMaIT +EwodsV +GV +GlihHPbk +DdmbA +ViLMNIdr +BllHBR +SLXqvK +ILVbDdV +GahU +GuaPcQ +tfBCvFFowN +SLO +b +i +AGNSQXjf +MHN +OAywfZl +ik +SDLEmM +gAxbp +zGfvYVOj +BahV +kDULvOYcbC +SvcBXzo +wqt +PxhfPJlw +ie +QCoXOucu +uycWN +SCKGgZ +pdgKvHcHKP +i +EMjOG +tvxP +AbIWGiQ +ebxdcRao +KLDGxVg +nrJ +hIs +gjusAfR +nUh +fXBoWK +kmmbtHpE +uRxCLaUPdY +LF +PXuwdbzc +ynSM +IrkngXj +RUZsk +SckZPUbBsO +RiTGBcw +m +cFhq +odlJp +qwLmK +UgDBiObT +kFn +AT +L +iDtp +evvI +LaSUyn +tFYidcfKrC +i +TYhTmlyCr +REtUj +KaBvGC +ErvVJX +sQGzxRmj +vQi +qnokgWXUF +mokYyOqVg +R +cOYJMbStu +hCcuSVjMn +g +G +RJQLP +aU +YelKXbDYCK +YRlwxi +l +L +ZWjYIvj +IEkISCVA +aPmnpD +zKKixpSBBv +T +EwOoT +ALP +iyf +Mn +mEwGXPdaOt +f +USzrI +G +lXMnlPEU +fHgeXEESD +obxwNooCCy +bz +yNUoFyhx +hQ +rHjwPBAPYV +vbfUQ +RgtapNFMM +vTlk +Fern +grBkeSy +hFCsGgV +sk +AALYZdqIf +GjZOssEeF +nn +Zt +ZqaUCZ +izuhb +iLu +NYPOzjkC +krRxcn +nhPJxvFatf +zHWQTq +ScqUlO +dB +lVkEc +b +UE +XTFBWpTx +ZVfsZdrdy +ixMjGlWS +rSdSf +NEXZqxc +EW +kugEKow +E +IkWwMkUHrY +r +kOOywPGHtu +vV +UDhSHpTnSD +roYQoUVgE +qPipS +PJeTN +CYXu +LJVQw +gtT +QZiRHeb +NAwdQDBvl +jQ +OGTHANlwFv +VUqYGlHEIo +MQexaafO +NK +A +bRwuUP +qrL +gBiYQaGdNY +dZhhBKt +rgEJujlM +PCJQSVffU +gWKGVyrKG +NOASsXoZi +tYI +edofF +aU +exkaqEMv +pBVOjx +Kr +VN +CDqpIYg +tqgJHX +rDGHGnKqF +HlITxDBkf +y +nY +O +DQNfUnG +iHJYrHOxBD +MtUW +ohyKrEbRvN +fhHmfit +bvMdFaRZFu +FfXpJmu +ClZYuH +nSBaZf +QSIqOue +eK +OqQOt +hKZKIeRnja +RAnLGnUTui +VwmAfl +ZBC +cBh +MQ +KbKLBHX +wS +DnLc +muQCLa +cVYZzNHOf +aqtMnHyE +aVvyzNyq +KlVCCdzfw +qdxvRNUVeg +qmLsm +x +xKrD +HIgxmE +MKDrF +fkkp +ulgKmRQUwW +GlDBV +EE +swcrSAKHe +vnWKSPbKW +lFAdSlBeN +UOOtSU +Yb +OnJJpbk +K +Gjkkt +FfOygOGqa +lcNgSVjg +ryK +FRc +EwXhyKejeq +jMUBgYswyB +kLPPgP +MHGJ +KpCQOpt +sA +umW +HNpIjlAA +Q +gNh +ZJjnIZ +IGnRFpjLd +R +E +Qox +DkBOomfj +zlzOr +KpDvVbi +AjYPCyWe +rfrNApNZnL +buA +wMWZEwSTK +eXv +MyJQAxZFZ +aqZQU +HSwwpRpmnO +xlXgh +cqFg +sbpQp +BPUQRC +dq +PJ +Q +Le +WqgQcl +zCuuI +PbGLUnw +wzj +yITgDspg +IKyndzU +EcoHDAZ +OIR +L +baX +MgxG +q +g +fFXTVsufdc +EC +TZRfTQo +w +OQxbdO +RirxDX +kWeHCLj +Dna +CSPKkVQ +NktgbTno +YzVznDXSZ +MTgZlohT +MS +GRiqutxH +xMaUAEiDi +r +PELKw +NOnYpIe +uTuclL +lJXfyhkIvz +vyCOpDJrN +tDEIcKtg +tqRJhuv +Vj +RyEQe +GX +GUffOxd +cafpwZEnV +ioQfNeSQL +iNiom +JyIrlxjfI +YdH +USKJF +tgrZeESLeH +DUnzjMf +WkUXXhGz +jgnqfkRf +HdPOKxbfLq +b +KHSKMD +zKCIsabKQ +vAdgpMawN +lnrY +WhwP +jx +F +XnQwxr +CgCNHewiqx +ZAJncXik +QHywBKc +VvyFgKbPp +TZJL +iYxAaQyrb +dBujwDNOZn +dczk +z +jjz +TY +vAg +Q +uCCFaIWD +kXTP +I +qD +reUNq +Drcnrn +KgHNo +kh +LJf +NI +kGzmKy +fuSImUCXwc +oQM +jzjJoPPo +VqpuG +Qtck +xayX +CLUk +yHM +PyYu +OQcsepg +DdC +XXIXoLE +RwbsrUO +zsl +gbHl +kWTElJ +oSbRor +zcTbAk +ZYmYnaRrQ +ZRcp +Szobd +DVowIUIBQf +hbhvB +IlFmGOCEEn +dlUPde +ZQ +qZxWyFwvEq +CDPrej +fqEMsIKlEp +CUSZJ +FR +rjKeOckLhl +dOmTYS +jthrH +vHhpLxVeh +Eq +eCo +IRKmDKxQm +oSYEKUnb +Sq +qIErlL +QesWF +yFtUy +QL +jpecU +UvufvOQA +uDrkCH +sa +eK +d +kleRKEcU +yBLocTwXy +eOlvSGr +fZZT +FYTuj +wJemojRav +xgJ +XLWOp +CLpoxkE +dDxN +UdgzEbfAD +cFnfnsLqQc +cY +k +ICWpcTjbug +aqLsotS +u +TBgmXWKM +Nk +BS +oxwBhSbzsL +DAWsiWrZ +dybpFcvT +C +y +zNSGQH +aEIgFYDnK +VnUe +vpEFQA +P +RNPbjI +ZWDZQTz +BvhjKXl +EpNf +pDzL +DMkREr +zkTc +g +MiQ +qafVhGIYLQ +VuBodzFFN +SnCbpUj +FZWJQ +mdDagJqa +qKtWPosyrV +IF +AXTvzcHMfo +e +yglMpyFUv +QW +IWzjOLf +BVy +WYBx +DPr +XpsluBozL +lU +Dwnjdnr +Wrk +CPDM +siNuynOWfA +PPItAue +hQEKLQasB +BVulY +Ywfd +TzTggWf +pl +N +kuAsgSexu +vQYPvWtiyH +VlgvEPbm +CGWqFadj +SOMtTbIDDP +IjexV +e +RnkvLdf +WERla +oQTeymG +qAkXLkDWRi +HIqtYrkksp +Y +lAfbZG +NTUNy +GjW +mYd +UaOxWC +dq +q +IhX +dLMvO +wmaQFLE +akaEICQv +hEyUrpA +FTE +sdpzSU +KjUKtNtF +frnULrs +Undtu +WjFMAriPOr +g +qE +Ldz +uIqcPVl +Gf +tusnbSi +tWjj +kWEXInxLcU +afGw +z +slOkGzw +BXs +IK +i +AaskxE +nE +yhVa +WszX +wDsR +sHgQUp +Ui +ygr +YGw +B +UsxcjpSfDy +iNYid +pkyBB +IHnFG +Jhnr +k +Ddxaz +EJMbtDtMI +IDFJjqERr +oAeOLEgi +rPnNB +e +vnng +Pt +kq +lQwn +brLEWMGNls +Qk +q +Ylfyrt +djOLdbPhD +dv +UEFieYmAN +zzF +qbWwtHRF +oydBK +mr +CWpP +mkQzli +MXTK +NoQPBf +LuoNaoqOM +vUSifwgNHG +O +yJSKkn +jQtwyv +tyj +obFItkt +ANivUYETfA +teOXEAaBzE +ChgLrSiTW +zfV +QgPwbwljs +WwJVMVOdsE +uv +QiIntmdzK +qZy +FYOdDA +lqYfXfvLD +Yjgb +TWT +iOZuVQ +feAR +DszlqMp +N +DMhX +DHDQQO +RXycA +FCa +yWAAXePOZ +l +rYU +DYZrhyYWh +AUEVQTVlG +q +m +dcB diff --git a/java-basic/learn-source-jdk7/pom.xml b/java-basic/learn-source-jdk7/pom.xml new file mode 100644 index 00000000..39251272 --- /dev/null +++ b/java-basic/learn-source-jdk7/pom.xml @@ -0,0 +1,18 @@ + + + + 4.0.0 + cn.lastwhisper + learn-source-jdk7 + 1.0-SNAPSHOT + + + + junit + junit + 4.13 + + + \ No newline at end of file diff --git a/java-basic/learn-source-jdk7/src/main/java/cn/lastwhisper/learn7/util/collection/HashMap7MultiThread.java b/java-basic/learn-source-jdk7/src/main/java/cn/lastwhisper/learn7/util/collection/HashMap7MultiThread.java new file mode 100644 index 00000000..6c2ac43a --- /dev/null +++ b/java-basic/learn-source-jdk7/src/main/java/cn/lastwhisper/learn7/util/collection/HashMap7MultiThread.java @@ -0,0 +1,53 @@ +package cn.lastwhisper.learn7.util.collection; + +import java.util.HashMap; +import java.util.concurrent.CountDownLatch; + +/** + * HashMap 在多线程环境成环 + * @author lastwhisper + * @date 2020/4/14 + */ +public class HashMap7MultiThread { + + // 多线程共享的HashMap + static HashMap shareMap = new HashMap<>(); + + static class AddTask implements Runnable { + int start = 0; + CountDownLatch latch; + + public AddTask(int start, CountDownLatch latch) { + this.start = start; + this.latch = latch; + } + + @Override + public void run() { + try { + for (int i = start; i < 100000; i += 2) { + shareMap.put(Integer.toString(i), Integer.toBinaryString(i)); + } + } finally { + latch.countDown(); + } + } + } + + public static void main(String[] args) throws InterruptedException { + CountDownLatch latch = new CountDownLatch(2); + + Thread t1 = new Thread(new AddTask(0, latch)); + Thread t2 = new Thread(new AddTask(1, latch)); + t1.start(); + t2.start(); + + try { + latch.await(); + System.out.println(shareMap.size()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + +} diff --git a/java-basic/learn-source-jdk7/src/main/java/cn/lastwhisper/learn7/util/collection/HashMap7Test.java b/java-basic/learn-source-jdk7/src/main/java/cn/lastwhisper/learn7/util/collection/HashMap7Test.java new file mode 100644 index 00000000..d90308e7 --- /dev/null +++ b/java-basic/learn-source-jdk7/src/main/java/cn/lastwhisper/learn7/util/collection/HashMap7Test.java @@ -0,0 +1,118 @@ +package cn.lastwhisper.learn7.util.collection; + +import org.junit.Test; + +import java.util.HashMap; + +/** + * + * @author lastwhisper + * @date 2020/3/26 + */ +public class HashMap7Test { + + /* + * 一、重要参数 + * 1.DEFAULT_INITIAL_CAPACITY = 16 默认哈希表的容量 + * 2.DEFAULT_LOAD_FACTOR = 0.75f 默认负载因子 + * 3.loadFactor 自定义负载因子(一般不会指定,默认0.75f,用来算threshold) + * 4.size k-v对的数量 + * 5.threshold 阈值,addEntry方法中size>=threshold&&null != table[K的Hash索引]时,哈希表将会扩容。 + * + * 二、Hash索引:int index = hash(K) % Array.length ===> HashMap的策略HashCode(K) & (Array.length-1) + * 三、Hash冲突:开放寻址法、拉链法===> HashMap的策略 拉链法 + * 四、为什么数组的大小是2^n? + * (1)加快哈希计算 + * (2)减少哈希冲突 + * n 为 2 的整数次幂,这样 n-1 后之前为 1 的位后面全是 1,这样就能保证 (n-1) & hash 后相应的位数既可能是 0 又可能是 1, + * 这取决于 hash 的值,这样能保证散列的均匀,同时与运算效率高如果 n 不是 2 的整数次幂,会造成更多的 hash 冲突 + * 五、hash(K)扰动函数的原理? + * JDK 源码中 HashMap 的 hash 方法原理是什么? - 胖君的回答 - 知乎 + * https://www.zhihu.com/question/20733617/answer/111577937 + * 六、inflateTable()函数计算threshold的值,inflateTable()会被Map参数构造函数和put()函数调用,计算规则: + * (1)threshold初始化,有三种情况: + * (a)HashMap 无参构造函数,threshold=DEFAULT_INITIAL_CAPACITY + * (b)HashMap initialCapacity参数构造函数,threshold=initialCapacity + * (c)HashMap Map参数构造函数,threshold=Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, + * DEFAULT_INITIAL_CAPACITY) + * (2)int capacity = roundUpToPowerOf2(threshold),找大于或等于threshold的2的幂次,capacity将作为HashMap内数组的容量 + * (3)threshold = capacity * loadFactor,threshold值确定 + * + * 七、初始化容量:initialCapacity=expectSize / 0.75f + 1.0f + * 比如,需要在HashMap中存储27个K-V。 + * (1)错误:设置initialCapacity=27,capacity=32,threshold=24=32*0.75=capacity*loadFactor + * 当你连续存储到满了24个以后,再存入第25个K-V的时候,size=24>=threshold=24,有可能触发扩容。 + * (2)正确:设置initialCapacity=37=27 / 0.75f + 1.0f,capacity=64,threshold=48=64*0.75=capacity*loadFactor + * 当你连续存储到满了24个以后,再存入第25个K-V的时候,size=24=threshold=12,有可能触发扩容。 + * 八、put(): + * (1)K=null单独处理,存入数组下标0的位置 + * (2)hash(K)存在&&K存在(内存地址相同||equals),覆盖值 + * 前两种情况不会触发扩容 + * (3)K不为前两种情况,满足(size >= threshold) && (null != table[K的Hash索引]) + * 触发扩容 + * 九、resize()与transfer():put(addEntry)和putAll时会调用 + * resize()会创建原数组容量两倍的新数组,transfer()负责将老数组的链表转移到新数组 + * transfer()步骤: + * 遍历该链表中的结点e,重复1、2、3、4步骤 + * (1)暂存Entry next = e.next + * (2)rehash(数组长度变了,需要重新计算hash,找到在新数组的位置)找到e在新数组的位置newTable[i],将e.next指向newTable[i] + * (3)将新数组位置替换成e, newTable[i] = e,完成头插法 + * (4)e = next; + * 十、并发读写成环或丢数据 + * + * https://blog.csdn.net/Lammonpeter/article/details/104271481 + * http://www.imooc.com/article/292265 + * https://zhuanlan.zhihu.com/p/96426441 + * + * + */ + + // 一个可能要扩容的HashMap + HashMap possibleResizeMap = new HashMap() {{ + this.put("1", "1"); + this.put("2", "2"); + this.put("3", "3"); + this.put("4", "4"); + this.put("5", "5"); + this.put("6", "6"); + this.put("7", "7"); + this.put("8", "8"); + this.put("9", "9"); + this.put("10", "10"); + this.put("11", "11"); + this.put("12", "12"); + /*--------------不扩容------------*/ + // size=12 >= threshold=12满足,但是null != table[bucketIndex]不满足 + this.put("13", "13"); + this.put("14", "14"); + + }}; + + @Test + public void testHashCode() { + + } + + @Test + public void testRepetitionK() { + possibleResizeMap.put("1", "1"); + } + + @Test + public void testResize() { + /*--------------扩容------------*/ + // size=14 >= threshold=12满足,同时null != table[bucketIndex]满足 + possibleResizeMap.put("15", "15"); + } + + @Test + public void testGet() { + possibleResizeMap.get(null); + possibleResizeMap.get("14"); + possibleResizeMap.get("15"); + } + + +} diff --git a/java-basic/learn-source-jdk8/READMD.md b/java-basic/learn-source-jdk8/READMD.md new file mode 100644 index 00000000..c1cfc4ca --- /dev/null +++ b/java-basic/learn-source-jdk8/READMD.md @@ -0,0 +1,3 @@ +# jdk1.8.0_241环境下 + + diff --git a/java-basic/learn-source-jdk8/pom.xml b/java-basic/learn-source-jdk8/pom.xml new file mode 100644 index 00000000..3de1810f --- /dev/null +++ b/java-basic/learn-source-jdk8/pom.xml @@ -0,0 +1,121 @@ + + + + 4.0.0 + cn.lastwhisper + learn-source-jdk8 + 1.0-SNAPSHOT + + + 1.8 + 4.3.5.RELEASE + + + + + + org.projectlombok + lombok + 1.18.24 + + + + org.apache.commons + commons-lang3 + 3.4 + + + + com.alibaba + fastjson + 1.2.47 + + + + + org.slf4j + slf4j-api + 1.7.9 + + + ch.qos.logback + logback-core + 1.2.3 + + + ch.qos.logback + logback-classic + 1.2.3 + + + + + junit + junit + 4.12 + + + + com.google.guava + guava + 23.0 + + + + commons-collections + commons-collections + 3.2.2 + + + + + org.springframework + spring-core + ${spring-version} + + + org.springframework + spring-beans + ${spring-version} + + + org.springframework + spring-aop + ${spring-version} + + + org.springframework + spring-context + ${spring-version} + + + org.springframework + spring-context-support + ${spring-version} + + + + org.springframework + spring-tx + 4.3.17.RELEASE + + + + + + org.springframework.boot + spring-boot-starter-web + 1.5.8.RELEASE + + + org.codehaus.groovy + groovy-all + 2.4.15 + compile + + + + + \ No newline at end of file diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/common/ReflectUtils.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/common/ReflectUtils.java new file mode 100644 index 00000000..53fdca24 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/common/ReflectUtils.java @@ -0,0 +1,54 @@ +package cn.lastwhisper.learn8.common; + +import java.lang.reflect.Field; + +public class ReflectUtils { + + public static Field getField(Object target, String fieldName) { + if (target == null) { + return null; + } + if ("".equals(fieldName)) { + return null; + } + Field field = null; + Class clazz = target.getClass(); + for (; clazz != Object.class; clazz = clazz.getSuperclass()) { + try { + field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + return field; + } catch (Exception e) { + + } + } + return null; + } + + /** + * 通过字段名从对象或对象的父类中得到字段的值 + * @param target 对象实例 + * @param fieldName 字段名 + * @return 字段对应的值 + */ + public static Object getValue(Object target, String fieldName) { + Object obj = null; + try { + obj = getField(target, fieldName).get(target); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return obj; + + } + + public static void setValue(Object target, String fieldName, Object value) { + try { + Field field = getField(target, fieldName); + field.set(target,value); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + + } +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/lang/LongTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/lang/LongTest.java new file mode 100644 index 00000000..bb94cd38 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/lang/LongTest.java @@ -0,0 +1,56 @@ +package cn.lastwhisper.learn8.lang; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +/** + * Long + * @author lastwhisper + * @date 2020/4/12 + */ +@Slf4j +public class LongTest { + + /** + * Long常量池 + */ + @Test + public void testLongCache() { + Long.valueOf(128); + Long.valueOf(129); + + Long.parseLong("128"); + Long.valueOf("128"); + } + + + @Test + public void testParse() throws InterruptedException { + log.info("----"); + Thread.sleep(1000L); + String s = "100"; + int valueOf = 0; + int parseLong = 0; + for (int j = 0; j < 100; j++) { + long beginTime = System.currentTimeMillis(); + for (int i = 0; i < 1000; i++) { + Long.valueOf(s); + } + long valueOfTime = System.currentTimeMillis() - beginTime; + long beginTime1 = System.currentTimeMillis(); + for (int i = 0; i < 1000; i++) { + Long.parseLong(s); + } + long parseLongTime = System.currentTimeMillis() - beginTime1; + + if (valueOfTime > parseLongTime) { + valueOf++; + } else { + parseLong++; + } + } + System.out.println("valueOf 累计" + valueOf); + System.out.println("parseLong 累计" + parseLong); + + } +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/lang/StringTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/lang/StringTest.java new file mode 100644 index 00000000..3c361f9f --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/lang/StringTest.java @@ -0,0 +1,130 @@ +package cn.lastwhisper.learn8.lang; + +import cn.lastwhisper.learn8.common.ReflectUtils; +import com.alibaba.fastjson.JSON; +import com.google.common.base.Joiner; +import com.google.common.base.Splitter; +import com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +import java.io.UnsupportedEncodingException; +import java.util.List; + +/** + * 学习String + * @author lastwhisper + * @date 2020/3/30 + */ +@Slf4j +public class StringTest { + + @Test + public void testValue(){ + String str = "hello world"; + // 拿到 string 里面的数组 + char[] value = (char[]) ReflectUtils.getValue(str,"value"); + log.info("修改之前{}", value); + ReflectUtils.setValue(str,"value","hello java".toCharArray()); + log.info("修改之后{}", str); + } + + /** + * String 不变性 + */ + @Test + public void testFinal() { + String s = "hello"; + s = "world"; + + String str = "hello world !!"; + // 这种写法是替换不掉的,必须接受 replace 方法返回的参数才行,这样才行:str = str.replace("l","dd"); + str.replace("l", "dd"); + } + + /** + * String decode + */ + @Test + public void testGibberish() throws UnsupportedEncodingException { + String str = "nihao 你好 喬亂"; + byte[] bytes = str.getBytes("ISO-8859-1"); + String s2 = new String(bytes, "ISO-8859-1"); + log.info(s2); + } + + /** + * String 相等判断 + */ + @Test + public void testEquals() { + String s1 = "A"; + String s2 = new String("A"); + String s3 = new String("a"); + Assert.assertTrue(s1.equals(s2)); + Assert.assertTrue(s1.equalsIgnoreCase(s3)); + } + + /** + * String 替换、删除 + * replace 并不只是替换一个,是替换所有匹配到的字符或字符串 + * replaceAll 替换所有,并支持正则 + */ + @Test + public void testReplace() { + String str = "hello word !!"; + log.info("替换之前 :{}", str); + str = str.replace('l', 'd'); + log.info("替换所有字符 :{}", str); + str = str.replaceAll("d", "l"); + log.info("替换全部 :{}", str); + str = str.replaceFirst("l", ""); + log.info("替换第一个 l :{}", str); + } + + /** + * String 拆分和合并 + */ + @Test + public void testSplit() { + String s = "boo:and:foo"; + log.info("s.split(\":\") 结果:{}", JSON.toJSONString(s.split(":"))); + log.info("s.split(\":\",2) 结果:{}", JSON.toJSONString(s.split(":", 2))); + log.info("s.split(\":\",5) 结果:{}", JSON.toJSONString(s.split(":", 5))); + log.info("s.split(\":\",-2) 结果:{}", JSON.toJSONString(s.split(":", -2))); + log.info("s.split(\"o\") 结果:{}", JSON.toJSONString(s.split("o"))); + log.info("s.split(\"o\",2) 结果:{}", JSON.toJSONString(s.split("o", 2))); + + String a1 = ",a, , b c ,"; + log.info("a.split(\",\") 结果:{}", JSON.toJSONString(a1.split(","))); + + List list = Splitter.on(',') + .trimResults()// 去掉空格 + .omitEmptyStrings()// 去掉空值 + .splitToList(a1); + log.info("Guava 去掉空格的分割方法:{}", JSON.toJSONString(list)); + } + + /** + * String 拆分和合并 + */ + @Test + public void testJoin() { + String s = "hello"; + String s1 = "china"; + log.info("String join api 一个字符串:{}", String.join(",", s1)); + log.info("String join api 不能join多个字符串:{}", String.join(",", s1).join(",", "null")); + + // 依次 join 多个字符串 + Joiner joiner = Joiner.on(",").skipNulls(); + String result = joiner.join("hello", null, "china"); + log.info("Guava join api 多个字符串:{}", result); + + List list = Lists.newArrayList("hello", "china", null); + log.info("Guava join api 自动删除 list 中空值:{}", joiner.join(list)); + + log.info("String join api 不删除 list 中空值:{}", String.join(",", list)); + } + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/lang/thread/ThreadTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/lang/thread/ThreadTest.java new file mode 100644 index 00000000..4248e924 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/lang/thread/ThreadTest.java @@ -0,0 +1,11 @@ +package cn.lastwhisper.learn8.lang.thread; + +/** + * Thread + * @author lastwhisper + * @date 2020/4/18 + */ +public class ThreadTest { + + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/ArraysTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/ArraysTest.java new file mode 100644 index 00000000..030a6792 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/ArraysTest.java @@ -0,0 +1,87 @@ +package cn.lastwhisper.learn8.util; + +import com.alibaba.fastjson.JSON; +import com.google.common.collect.ImmutableList; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +/** + * Arrays + * @author lastwhisper + * @date 2020/4/12 + */ +@Slf4j +public class ArraysTest { + + @Data + static class SortDTO { + private String sortTarget; + + public SortDTO(String sortTarget) { + this.sortTarget = sortTarget; + } + } + + /** + * Arrays 排序 + */ + @Test + public void testSort() { + List list = ImmutableList.of( + new SortDTO("300"), + new SortDTO("50"), + new SortDTO("200"), + new SortDTO("220") + ); + // 我们先把数组的大小初始化成 list 的大小,保证能够正确执行 toArray + SortDTO[] array = new SortDTO[list.size()]; + list.toArray(array); + + log.info("排序之前:{}", JSON.toJSONString(array)); + Arrays.sort(array, Comparator.comparing(SortDTO::getSortTarget)); + log.info("排序之后:{}", JSON.toJSONString(array)); + } + + /** + * Arrays 二分查找 + */ + @Test + public void testBinarySearch() { + List list = ImmutableList.of( + new SortDTO("300"), + new SortDTO("50"), + new SortDTO("200"), + new SortDTO("220") + ); + + SortDTO[] array = new SortDTO[list.size()]; + list.toArray(array); + + log.info("搜索之前:{}", JSON.toJSONString(array)); + Arrays.sort(array, Comparator.comparing(SortDTO::getSortTarget)); + log.info("先排序,结果为:{}", JSON.toJSONString(array)); + int index = Arrays.binarySearch(array, new SortDTO("200"), + Comparator.comparing(SortDTO::getSortTarget)); + if (index < 0) { + throw new RuntimeException("没有找到 200"); + } + log.info("搜索结果:{}", JSON.toJSONString(array[index])); + } + + /** + * Arrays copy + */ + @Test + public void testCopyOf() { + char[] original = new char[]{'1', '2', '3', '4', '5', '6', '7'}; + char[] chars = Arrays.copyOfRange(original, 2, 4); + log.info("copyOfRange:{}", Arrays.toString(chars)); + } + + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/CollectionsTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/CollectionsTest.java new file mode 100644 index 00000000..b8b77c25 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/CollectionsTest.java @@ -0,0 +1,28 @@ +package cn.lastwhisper.learn8.util; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.list.UnmodifiableList; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Collections + * @author lastwhisper + * @date 2020/4/12 + */ +@Slf4j +public class CollectionsTest { + + @Test + public void unmodifiable(){ + List list = new ArrayList<>(); + List unmodifiableList = UnmodifiableList.decorate(list); + +// Collections.synchronizedList() + + } + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/ObjectsTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/ObjectsTest.java new file mode 100644 index 00000000..62420e05 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/ObjectsTest.java @@ -0,0 +1,15 @@ +package cn.lastwhisper.learn8.util; + +import lombok.extern.slf4j.Slf4j; + +/** + * Objects + * @author lastwhisper + * @date 2020/4/12 + */ +@Slf4j +public class ObjectsTest { + + + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/ArrayListTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/ArrayListTest.java new file mode 100644 index 00000000..284cf810 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/ArrayListTest.java @@ -0,0 +1,127 @@ +package cn.lastwhisper.learn8.util.collection; + +import cn.lastwhisper.learn8.common.ReflectUtils; +import com.alibaba.fastjson.JSON; +import com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +/** + * ArrayList + * @author lastwhisper + * @date 2020/4/12 + */ +@Slf4j +public class ArrayListTest { + + /** + * ArrayList初始化 + */ + @Test + public void testInitBug() { + // Arrays.asList 返回的是具体的类型 + List list = Arrays.asList("hello,world"); + Object[] objArray = list.toArray(); + log.info(objArray.getClass().getSimpleName());//Object[] + // objArray 元素的类型是 String,储存 Object 就会报错, + // 因为 jvm 不清楚你存储的 Object 真实类型是不是 String + objArray[0] = new Object(); + } + + /** + * ArrayList扩容机制 + * + * 创建ArrayList不指定初始容量,第一次add时直接扩容到DEFAULT_CAPACITY=10 + * 所以如果能确定ArrayList的大小一定要指定初始容量 + * + * add逻辑: + * ensureCapacityInternal——确保内部需要的容量够用minCapacity=size + 1 + * calculateCapacity——判断ArrayList是否是第一次创建且未指定初始容量,如果是minCapacity=DEFAULT_CAPACITY + * ensureExplicitCapacity——minCapacity>elementData.length,扩容1.5*elementData.length + */ + @Test + public void testGrow() { + List arrayList = new ArrayList<>(); + + Object[] elementData = (Object[]) ReflectUtils.getValue(arrayList, "elementData"); + Assert.assertEquals(0, elementData.length); + + // 此处应该扩容 0->10 + arrayList.add(1); + elementData = (Object[]) ReflectUtils.getValue(arrayList, "elementData"); + Assert.assertEquals(10, elementData.length); + arrayList.add(2); + arrayList.add(3); + arrayList.add(4); + arrayList.add(5); + arrayList.add(6); + arrayList.add(7); + arrayList.add(8); + arrayList.add(9); + arrayList.add(10); + // 此处应该扩容 10->15 + arrayList.add(11); + + elementData = (Object[]) ReflectUtils.getValue(arrayList, "elementData"); + Assert.assertEquals(15, elementData.length); + } + + + /** + * 测试ArrayList在创建迭代器后,使用iterator.remove()单线程修改 + * + * fail-fast + * + * 一般都是用增强for循环遍历集合,增强for只是个语法糖,本质上还是迭代器遍历。 + * modCount和expectedModCount其实就是个版本号,通过modCount和expectedModCount能感知到ArrayList是否被并发读写, + * ArrayList是非线程安全的,并发读写极有可能出错,于是JDK直接提供了快速失败机制,省的你出现奇怪的错误。 + * + * 通过这个快速失败机制也能看出来,JDK就是要告诉你ArrayList不能并发读写,就算你能容忍并发读写带来的错误也不行, + * 人家的设计理念就不允许你这么做。 + */ + @Test + public void testFailFast() { + List arrayList = new ArrayList(){{ + add("a"); + add("b"); + add("c"); + add("d"); + }}; + + // java.util.ConcurrentModificationException + //for (String data : arrayList) { + // if (data.equals("a")) { + // arrayList.remove("a"); + // } + // System.out.println(data); + //} + + // java.util.ConcurrentModificationException + //Iterator iterator = arrayList.iterator(); + //while (iterator.hasNext()) { + // String data = iterator.next(); + // if (data.equals("a")) { + // arrayList.remove("a"); + // } + // System.out.println(data); + //} + + Iterator iterator = arrayList.iterator(); + while (iterator.hasNext()) { + String data = iterator.next(); + if (data.equals("a")) { + iterator.remove(); + } + System.out.println(data); + } + System.out.println("size=" + arrayList.size()); + } + + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/HashMap8MultiThread.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/HashMap8MultiThread.java new file mode 100644 index 00000000..06a36801 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/HashMap8MultiThread.java @@ -0,0 +1,54 @@ +package cn.lastwhisper.learn8.util.collection; + +import java.util.HashMap; +import java.util.concurrent.CountDownLatch; + +/** + * HashMap 在多线程环境成环 + * @author lastwhisper + * @date 2020/4/14 + */ +public class HashMap8MultiThread { + + // 多线程共享的HashMap + static HashMap shareMap = new HashMap<>(); + + static class AddTask implements Runnable { + int start = 0; + CountDownLatch latch; + + public AddTask(int start, CountDownLatch latch) { + this.start = start; + this.latch = latch; + } + + @Override + public void run() { + try { + for (int i = start; i < 100000; i += 2) { + shareMap.put(Integer.toString(i), Integer.toBinaryString(i)); + } + } finally { + latch.countDown(); + } + } + } + + public static void main(String[] args) throws InterruptedException { + CountDownLatch latch = new CountDownLatch(2); + + Thread t1 = new Thread(new AddTask(0, latch)); + Thread t2 = new Thread(new AddTask(1, latch)); + t1.start(); + t2.start(); + + try { + latch.await(); + System.out.println(shareMap.size()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + } + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/HashMap8Test.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/HashMap8Test.java new file mode 100644 index 00000000..758685e7 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/HashMap8Test.java @@ -0,0 +1,118 @@ +package cn.lastwhisper.learn8.util.collection; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author lastwhisper + * @date 2020/3/26 + */ +public class HashMap8Test { + + /* + * 一、重要参数 + * 1.DEFAULT_INITIAL_CAPACITY = 16 默认哈希表的容量 + * 2.DEFAULT_LOAD_FACTOR = 0.75f 默认负载因子 + * 3.loadFactor 自定义负载因子(一般不会指定,默认0.75f,用来算threshold) + * 4.size k-v对的数量 + * 5.threshold 阈值,addEntry方法中size>=threshold&&null != table[K的Hash索引]时,哈希表将会扩容。 + * + * 6.TREEIFY_THRESHOLD = 8 链表可能转换为红黑树的基本阈值(链表长度>=8) + * 7.UNTREEIFY_THRESHOLD = 6 哈希表扩容后,如果发现红黑树节点数小于6,则退化为链表 + * 8.MIN_TREEIFY_CAPACITY = 64 链表转换为红黑树的另一个条件,哈希表长度必须大于等于64才会转换,否则会扩容 + * + * 二、Hash索引:int index = hash(K) % Array.length ===> HashMap的策略HashCode(K) & (Array.length-1) + * 三、Hash冲突:开放寻址法、拉链法===> HashMap的策略 拉链法 + * 四、为什么数组的大小是2^n? + * (1)加快哈希计算 + * (2)减少哈希冲突 + * n 为 2 的整数次幂,这样 n-1 后之前为 1 的位后面全是 1,这样就能保证 (n-1) & hash 后相应的位数既可能是 0 又可能是 1, + * 这取决于 hash 的值,这样能保证散列的均匀,同时与运算效率高如果 n 不是 2 的整数次幂,会造成更多的 hash 冲突 + * 五、hash(K)扰动函数的原理? + * https://www.zhihu.com/question/20733617/answer/111577937 + * + * 六、threshold计算规则: + * (1)threshold初始化,有三种情况: + * (a)HashMap 无参构造函数,threshold=0 + * (b)HashMap initialCapacity参数构造函数,threshold=initialCapacity + * (c)HashMap Map参数构造函数,threshold=((float)s / loadFactor) + 1.0F + * (2)tableSizeFor()会在HashMap四个构造函数初始化时调用 + * int threshold = tableSizeFor(threshold),找大于或等于threshold的2的幂次,该值作为数组大小 + * (3)resize()时,执行threshold = capacity * loadFactor,threshold值确定 + * + * 七、初始化容量:initialCapacity=expectSize / 0.75f + 1.0f + * 比如,需要在HashMap中存储27个K-V。 + * (1)错误:设置initialCapacity=27,capacity=32,threshold=24=32*0.75=capacity*loadFactor + * 当你连续存储到满了24个以后,再存入第25个K-V的时候,size=24>=threshold=24,有可能触发扩容。 + * (2)正确:设置initialCapacity=37=27 / 0.75f + 1.0f,capacity=64,threshold=48=64*0.75=capacity*loadFactor + * 当你连续存储到满了24个以后,再存入第25个K-V的时候,size=24=threshold=12,有可能触发扩容。 + * 八、put(): + * + * 九、resize(): + * + * + */ + + // 一个可能要扩容的HashMap + HashMap possibleResizeMap = new HashMap() {{ + this.put("1", "1"); + this.put("2", "2"); + this.put("3", "3"); + this.put("4", "4"); + this.put("5", "5"); + this.put("6", "6"); + this.put("7", "7"); + this.put("8", "8"); + this.put("9", "9"); + this.put("10", "10"); + this.put("11", "11"); + this.put("12", "12"); + /*--------------不扩容------------*/ + // size=12 >= threshold=12满足,但是null != table[bucketIndex]不满足 + this.put("13", "13"); + this.put("14", "14"); + + }}; + + @Test + public void testConstruct() { + new HashMap<>(possibleResizeMap); + } + + @Test + public void testPut() { + //HashMap hashMap = new HashMap<>(); + //hashMap.put("1", "1"); + Integer[] integers = new Integer[10]; + for (Integer integer : integers) { + System.out.println(integer); + } + } + + @Test + public void testResize() { + /*--------------扩容------------*/ + // size=14 >= threshold=12满足,同时null != table[bucketIndex]满足 + possibleResizeMap.put("15", "15"); + } + + @Test + public void testResize2() { + HashMap data = new HashMap<>(2); + data.put("rows", "rows"); + data.put("total", "total"); + } + + @Test + public void testGet() { + possibleResizeMap.get(null); + possibleResizeMap.get("14"); + possibleResizeMap.get("15"); + } + + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/LinkedHashMapTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/LinkedHashMapTest.java new file mode 100644 index 00000000..977059f1 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/LinkedHashMapTest.java @@ -0,0 +1,105 @@ +package cn.lastwhisper.learn8.util.collection; + +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * LinkedHashMap + * @author lastwhisper + * @date 2020/4/13 + */ +@Slf4j +public class LinkedHashMapTest { + + /** + * 最近最少使用到的(least recently used) + * LinkedHashMap继承HashMap,LinkedHashMap实现LRU核心方法: + * + * LinkedHashMap队头是最近最少使用的结点,队尾是最近最常使用的 + * + * void afterNodeAccess(Node p) { } + * HashMap putVal的元素已经存在时回调,当前该节点移动到队尾 + * + * void afterNodeInsertion(boolean evict) { } + * HashMap putVal时回调 + * + * boolean removeEldestEntry(Map.Entry eldest) + * 留着用户重写,默认返回false。返回true时,删除最近最少使用的元素,也就是队头。 + * + * void afterNodeRemoval(Node p) { } + * HashMap remove时回调,删除HashMap remove的元素 + * + * + */ + + /** + * 稳定性 + */ + @Test + public void testInsertOrder() { + LinkedHashMap map = new LinkedHashMap() {{ + put(10, 10); + put(9, 9); + put(20, 20); + put(1, 1); + }}; + Assert.assertNotNull(map.get(9)); + Assert.assertNotNull(map.get(20)); + Assert.assertNotNull(map.get(9)); + log.info(JSON.toJSONString(map)); + + } + + /** + * lru + */ + @Test + public void testAccessOrder() { + LinkedHashMap map = new LinkedHashMap(4,0.75f,true) { + { + put(10, 10); + put(9, 9); + put(20, 20); + put(1, 1); + } + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > 3; + } + }; + + log.info("初始化:{}",JSON.toJSONString(map)); + Assert.assertNotNull(map.get(9)); + log.info("map.get(9):{}",JSON.toJSONString(map)); + Assert.assertNotNull(map.get(20)); + log.info("map.get(20):{}",JSON.toJSONString(map)); + + } + + @Test + public void testIterator(){ + LinkedHashMap map = new LinkedHashMap(4,0.75f,true) { + { + put(10, 10); + put(9, 9); + put(20, 20); + put(1, 1); + } + }; + + log.info("迭代访问 start"); + Iterator> iterator = map.entrySet().iterator(); + while (iterator.hasNext()){ + Map.Entry entry = iterator.next(); + log.info(JSON.toJSONString(entry)); + } + log.info("迭代访问 end"); + } + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/LinkedListTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/LinkedListTest.java new file mode 100644 index 00000000..598e7e04 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/LinkedListTest.java @@ -0,0 +1,65 @@ +package cn.lastwhisper.learn8.util.collection; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + +/** + * LinkedList + * + * @author lastwhisper + * @date 2020/4/13 + */ +@Slf4j +public class LinkedListTest { + + @Test + public void testFastFail() { + List linkedList = new LinkedList(){{ + add("a"); + add("b"); + add("c"); + add("d"); + }}; + + // java.util.ConcurrentModificationException + Iterator iterator = linkedList.iterator(); + while (iterator.hasNext()) { + String data = iterator.next(); + if (data.equals("a")) { + linkedList.remove("a"); + } + System.out.println(data); + } + System.out.println("size=" + linkedList.size()); + } + + @Test + public void testItertor() { + List list = new LinkedList<>(); + list.add("s1"); + list.add("s3"); + list.add("s3"); + list.add(null); + list.add("s4"); + + ListIterator listIterator = list.listIterator(); + while (listIterator.hasNext()) { + String s = listIterator.next(); + log.info("从头到尾迭代顺序:" + s); + } + + while (listIterator.hasPrevious()) { + String s = listIterator.previous(); + if (s.equals("s5")) { + listIterator.remove(); + } + log.info("从尾到头迭代顺序:" + s); + } + } + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/TreeMapTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/TreeMapTest.java new file mode 100644 index 00000000..0dbb91ce --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/collection/TreeMapTest.java @@ -0,0 +1,81 @@ +package cn.lastwhisper.learn8.util.collection; + +import com.alibaba.fastjson.JSON; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +import java.util.*; + +/** + * TreeMap + * @author lastwhisper + * @date 2020/4/13 + */ +@Slf4j +public class TreeMapTest { + + @Data + class DTO implements Comparable { + + private Integer id; + + public DTO(Integer id) { + this.id = id; + } + + @Override + public int compareTo(DTO o) { + //默认从小到大排序 + return id - o.getId(); + } + } + + + @Test + public void testIterator() { + TreeMap m = new TreeMap<>(); + m.put("asdf", "nihao"); + m.put("sdf", "nihao"); + m.put("df", "nihao"); + m.keySet().iterator(); + } + + @Test + public void testRegionSearch() { + TreeMap rankingMap = new TreeMap<>(); + rankingMap.put(1,1); //ranking 1 ->1 + rankingMap.put(2,2); //ranking 2 ->2 + rankingMap.put(3,3); //ranking 3 -> 3 + rankingMap.put(4,4); //ranking 4-10 ->4 + rankingMap.put(11,5); //ranking 11-20 ->5 + rankingMap.put(21,6); //ranking 21-30 ->6 + rankingMap.put(31,7); //ranking >= 31 ->7 + + Assert.assertEquals(6, (int) rankingMap.floorEntry(30).getValue()); + Assert.assertEquals(7, (int) rankingMap.floorEntry(71).getValue()); + } + + @Test + public void testTwoComparable() { + // 第一种排序,从小到大排序,实现 Comparable 的 compareTo 方法进行排序 + List list = new ArrayList<>(); + for (int i = 5; i > 0; i--) { + list.add(new DTO(i)); + } + Collections.sort(list); + log.info(JSON.toJSONString(list)); + + // 第二种排序,从大到小排序,利用外部排序器 Comparator 进行排序 + Comparator comparator = (Comparator) (o1, o2) -> o2.getId() - o1.getId(); + List list2 = new ArrayList<>(); + for (int i = 5; i > 0; i--) { + list2.add(new DTO(i)); + } + Collections.sort(list, comparator); + log.info(JSON.toJSONString(list2)); + } + + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/collection/ConcurrentHashMapTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/collection/ConcurrentHashMapTest.java new file mode 100644 index 00000000..540e5587 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/collection/ConcurrentHashMapTest.java @@ -0,0 +1,26 @@ +package cn.lastwhisper.learn8.util.concurrent.collection; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; + +/** + * ConcurrentHashMap + * @author lastwhisper + * @date 2020/4/16 + */ +@Slf4j +public class ConcurrentHashMapTest { + + @Test + public void testRegionSearch() { + ConcurrentHashMap map = new ConcurrentHashMap<>(); + map.put("1","1"); + + } + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/collection/CopyOnWriteArrayListTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/collection/CopyOnWriteArrayListTest.java new file mode 100644 index 00000000..6f1b2603 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/collection/CopyOnWriteArrayListTest.java @@ -0,0 +1,30 @@ +package cn.lastwhisper.learn8.util.concurrent.collection; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +import java.util.Iterator; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * CopyOnWriteArrayList + * @author lastwhisper + * @date 2020/4/16 + */ +@Slf4j +public class CopyOnWriteArrayListTest { + + @Test + public void testIterator() { + CopyOnWriteArrayList list = new CopyOnWriteArrayList(); + list.add("10"); + list.add("20"); + list.add("30"); + Iterator iterator = list.iterator(); + list.add("50"); + iterator.next(); + list.add("50"); + } + + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/executor/FutureTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/executor/FutureTest.java new file mode 100644 index 00000000..1b8b1e3f --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/executor/FutureTest.java @@ -0,0 +1,84 @@ +package cn.lastwhisper.learn8.util.concurrent.executor; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +import java.util.concurrent.*; + +/** + * Future + * @author lastwhisper + * @date 2020/4/18 + */ +@Slf4j +public class FutureTest { + + /** + * Callable 有返回值 + */ + @Test + public void testCallable() throws ExecutionException, InterruptedException { + FutureTask futureTask = new FutureTask<>(new Callable() { + @Override + public String call() throws Exception { + TimeUnit.SECONDS.sleep(5); + return "return val"; + } + }); + log.info("do some thing..."); + futureTask.run(); + String result = futureTask.get(); + log.info("拿到值了,为 {}", result); + } + + /** + * Runnable 无返回值 + * 适配器 + * + */ + @Test + public void testRunnable() throws ExecutionException, InterruptedException { + FutureTask futureTask = new FutureTask(new Runnable() { + @Override + public void run() { + log.info("{} is run", Thread.currentThread().getName()); + } + }, null); + futureTask.run(); + String result = futureTask.get(); + log.info("run end,result is {}", result); + } + + @Test + public void testGet() throws ExecutionException, InterruptedException { + ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 3, 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue<>()); + FutureTask futureTask = new FutureTask(new Callable() { + @Override + public String call() throws Exception { + Thread.sleep(3000); + return "我是子线程" + Thread.currentThread().getName(); + } + }); + executor.submit(futureTask); + String result = (String) futureTask.get(); + log.info("result is {}", result); + executor.shutdown(); + } + + @Test + public void testThreadByCallable() throws ExecutionException, InterruptedException { + FutureTask futureTask = new FutureTask(new Callable() { + @Override + public String call() throws Exception { + Thread.sleep(3000); + String result = "我是子线程" + Thread.currentThread().getName(); + log.info("子线程正在运行:{}", Thread.currentThread().getName()); + return result; + } + }); + new Thread(futureTask).start(); + log.info("返回的结果是 {}", futureTask.get()); + } + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/ArrayBlockingQueueDemo.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/ArrayBlockingQueueDemo.java new file mode 100644 index 00000000..c4978bf9 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/ArrayBlockingQueueDemo.java @@ -0,0 +1,90 @@ +package cn.lastwhisper.learn8.util.concurrent.queue; + +import org.junit.Test; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.TimeUnit; + +/** + * 阻塞队列 + * @author lastwhisper + */ +public class ArrayBlockingQueueDemo { + ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3); + + // 抛异常 + @Test + public void testThrowException() { + System.out.println(blockingQueue.add("a")); + System.out.println(blockingQueue.add("b")); + System.out.println(blockingQueue.add("c")); + + try { + System.out.println(blockingQueue.add("x")); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println(blockingQueue.element()); + System.out.println(blockingQueue.remove()); + System.out.println(blockingQueue.remove()); + System.out.println(blockingQueue.remove()); + try { + //当阻塞队列空时,再往队列Remove元素时候回抛出NoSuchElementException + System.out.println(blockingQueue.remove()); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + // 特殊值 + @Test + public void testReturnBool() { + System.out.println(blockingQueue.offer("a")); + System.out.println(blockingQueue.offer("b")); + System.out.println(blockingQueue.offer("c")); + // 插入方法,成功返回true 失败返回false + System.out.println(blockingQueue.offer("x")); + + System.out.println(blockingQueue.poll()); + System.out.println(blockingQueue.poll()); + System.out.println(blockingQueue.poll()); + //移除方法,成功返回元素,队列里面没有就返回null + System.out.println(blockingQueue.poll()); + } + + // 一直阻塞 + @Test + public void testBlock() throws InterruptedException { + blockingQueue.put("a"); + blockingQueue.put("b"); + blockingQueue.put("c"); + // 当阻塞队列满时,生产者继续往队列里面put元素,队列会一直阻塞直到put数据or响应中断退出 + blockingQueue.offer("x"); + + System.out.println(blockingQueue.take()); + System.out.println(blockingQueue.take()); + System.out.println(blockingQueue.take()); + //当阻塞队列空时,消费者试图从队列take元素,队列会一直阻塞消费者线程直到队列可用. + System.out.println(blockingQueue.take()); + } + + // 超时退出 + @Test + public void testIncorruptible() throws InterruptedException { + blockingQueue.offer("a"); + blockingQueue.offer("b"); + blockingQueue.offer("c"); + System.out.println(blockingQueue.size()); + // 当阻塞队列满时,队列会阻塞生产者线程一定时间,超过后限时后生产者线程就会退出 + blockingQueue.offer("x", 2L, TimeUnit.SECONDS); + + System.out.println(blockingQueue.poll()); + System.out.println(blockingQueue.poll()); + System.out.println(blockingQueue.poll()); + System.out.println(blockingQueue.size()); + System.out.println(blockingQueue.poll(2L, TimeUnit.SECONDS)); + } + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/DelayQueueTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/DelayQueueTest.java new file mode 100644 index 00000000..d2f1f834 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/DelayQueueTest.java @@ -0,0 +1,98 @@ +package cn.lastwhisper.learn8.util.concurrent.queue; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.DelayQueue; +import java.util.concurrent.Delayed; +import java.util.concurrent.TimeUnit; + +/** + * DelayQueue + * @author lastwhisper + * @date 2020/4/17 + */ +@Slf4j +public class DelayQueueTest { + + static class Product implements Runnable { + + private final BlockingQueue queue; + + public Product(BlockingQueue queue) { + this.queue = queue; + } + + @Override + public void run() { + try { + log.info("begin put"); + long beginTime = System.currentTimeMillis(); + queue.put(new DelayedDTO(System.currentTimeMillis() + 2000L, beginTime));//延迟 2 秒执行 + queue.put(new DelayedDTO(System.currentTimeMillis() + 5000L, beginTime));//延迟 5 秒执行 + queue.put(new DelayedDTO(System.currentTimeMillis() + 1000L * 10, beginTime));//延迟 10 秒执行 + log.info("end put"); + } catch (InterruptedException e) { + log.error("" + e); + } + } + } + + static class Consumer implements Runnable { + + private final BlockingQueue queue; + + public Consumer(BlockingQueue queue) { + this.queue = queue; + } + + @Override + public void run() { + try { + log.info("Consumer begin"); + queue.take().run(); + queue.take().run(); + queue.take().run(); + log.info("Consumer end"); + } catch (InterruptedException e) { + log.error("" + e); + } + } + } + + @Data + static class DelayedDTO implements Delayed { + Long s; + Long beginTime; + + public DelayedDTO(Long s, Long beginTime) { + this.s = s; + this.beginTime = beginTime; + } + + @Override + public long getDelay(TimeUnit unit) { + return unit.convert(s - System.currentTimeMillis(), TimeUnit.MILLISECONDS); + } + + @Override + public int compareTo(Delayed o) { + return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS)); + } + + public void run() { + log.info("延迟了{}秒钟才执行", (System.currentTimeMillis() - beginTime) / 1000); + } + } + + public static void main(String[] args) throws InterruptedException { + BlockingQueue q = new DelayQueue<>(); + DelayQueueTest.Product p = new DelayQueueTest.Product(q); + DelayQueueTest.Consumer c = new DelayQueueTest.Consumer(q); + new Thread(c).start(); + new Thread(p).start(); + + } + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/LinkedBlockingQueueTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/LinkedBlockingQueueTest.java new file mode 100644 index 00000000..9fd01c55 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/LinkedBlockingQueueTest.java @@ -0,0 +1,94 @@ +package cn.lastwhisper.learn8.util.concurrent.queue; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +/** + * LinkedBlockingQueue + * @author lastwhisper + * @date 2020/4/17 + */ +@Slf4j +public class LinkedBlockingQueueTest { + + LinkedBlockingQueue blockingQueue = new LinkedBlockingQueue<>(3); + + // 抛异常 + @Test + public void testThrowException() { + System.out.println(blockingQueue.add("a")); + System.out.println(blockingQueue.add("b")); + System.out.println(blockingQueue.add("c")); + + try { + System.out.println(blockingQueue.add("x")); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println(blockingQueue.element()); + System.out.println(blockingQueue.remove()); + System.out.println(blockingQueue.remove()); + System.out.println(blockingQueue.remove()); + try { + //当阻塞队列空时,再往队列Remove元素时候回抛出NoSuchElementException + System.out.println(blockingQueue.remove()); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + // 特殊值 + @Test + public void testReturnBool() { + System.out.println(blockingQueue.offer("a")); + System.out.println(blockingQueue.offer("b")); + System.out.println(blockingQueue.offer("c")); + // 插入方法,成功返回true 失败返回false + System.out.println(blockingQueue.offer("x")); + + System.out.println(blockingQueue.poll()); + System.out.println(blockingQueue.poll()); + System.out.println(blockingQueue.poll()); + //移除方法,成功返回元素,队列里面没有就返回null + System.out.println(blockingQueue.poll()); + } + + // 一直阻塞 + @Test + public void testBlock() throws InterruptedException { + blockingQueue.put("a"); + blockingQueue.put("b"); + blockingQueue.put("c"); + // 当阻塞队列满时,生产者继续往队列里面put元素,队列会一直阻塞直到put数据or响应中断退出 + blockingQueue.offer("x"); + System.out.println(blockingQueue.take()); + System.out.println(blockingQueue.take()); + System.out.println(blockingQueue.take()); + //当阻塞队列空时,消费者试图从队列take元素,队列会一直阻塞消费者线程直到队列可用. + System.out.println(blockingQueue.take()); + } + + // 超时退出 + @Test + public void testIncorruptible() throws InterruptedException { + blockingQueue.offer("a"); + blockingQueue.offer("b"); + blockingQueue.offer("c"); + System.out.println(blockingQueue.size()); + // 当阻塞队列满时,队列会阻塞生产者线程一定时间,超过后限时后生产者线程就会退出 + blockingQueue.offer("x", 2L, TimeUnit.SECONDS); + + System.out.println(blockingQueue.poll()); + System.out.println(blockingQueue.poll()); + System.out.println(blockingQueue.poll()); + System.out.println(blockingQueue.size()); + System.out.println(blockingQueue.poll(2L, TimeUnit.SECONDS)); + } + + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/SynchronousQueueTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/SynchronousQueueTest.java new file mode 100644 index 00000000..55981e6f --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/SynchronousQueueTest.java @@ -0,0 +1,68 @@ +package cn.lastwhisper.learn8.util.concurrent.queue; + +import lombok.extern.slf4j.Slf4j; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.SynchronousQueue; + +/** + * SynchronousQueue + * @author lastwhisper + * @date 2020/4/17 + */ +@Slf4j +public class SynchronousQueueTest { + + static class Product implements Runnable { + + private final BlockingQueue queue; + + public Product(BlockingQueue queue) { + this.queue = queue; + } + + @Override + public void run() { + try { + log.info("begin put"); + queue.put("nihao"); + log.info("end put"); + } catch (InterruptedException e) { + } + } + + } + + static class Consumer implements Runnable { + + private final BlockingQueue queue; + + public Consumer(BlockingQueue queue) { + this.queue = queue; + } + + @Override + public void run() { + try { + log.info("Consumer begin"); + String name = (String) queue.take(); + log.info("Consumer end :{}", name); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public static void main(String[] args) throws InterruptedException { + BlockingQueue q = new SynchronousQueue(true); + Product p = new Product(q); + Consumer c = new Consumer(q); + new Thread(c).start(); + log.info("sleeping"); + Thread.sleep(5000L); + log.info("sleepEnd"); + new Thread(p).start(); + } + + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/my/LinkedBlockingQueue.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/my/LinkedBlockingQueue.java new file mode 100644 index 00000000..fb9e6a81 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/my/LinkedBlockingQueue.java @@ -0,0 +1,196 @@ +package cn.lastwhisper.learn8.util.concurrent.queue.my; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +/** + * 链表实现的阻塞队列 + * @author lastwhisper + * @date 2020/4/17 + */ +public class LinkedBlockingQueue implements Queue { + + /** + * 容量 + */ + private final Integer capacity; + /** + * 队列的大小,使用 AtomicInteger 来保证其线程安全 + */ + private final AtomicInteger count = new AtomicInteger(); + /** Lock held by take, poll, etc */ + private final ReentrantLock takeLock = new ReentrantLock(); + /** Wait queue for waiting takes */ + private final Condition notEmpty = takeLock.newCondition(); + /** Lock held by put, offer, etc */ + private final ReentrantLock putLock = new ReentrantLock(); + /** Wait queue for waiting puts */ + private final Condition notFull = putLock.newCondition(); + /** + * 链表头 + */ + private transient Node head; + /** + * 链表尾 + */ + private transient Node tail; + + public LinkedBlockingQueue() { + this(Integer.MAX_VALUE); + } + + /** + * 初始化 + * + * @param capacity 队列容量 + */ + public LinkedBlockingQueue(Integer capacity) { + // 边界检查 + if (capacity == null || capacity < 0) { + throw new IllegalArgumentException("capacity is null or less zero"); + } + this.capacity = capacity; + head = tail = new Node<>(null); + } + + /** + * 实现思路: + * 1、put元素不为空 + * 2、上put锁 + * 3、队满,put操作阻塞 + * 4、队不满,元素入队 + * 5、校验队列长度是否小于容量,小于则唤醒其他put操作 + * 6、释放put锁 + * 7、校验队列长度是否等于1,等于则唤醒take操作(这个1是刚put的,可能有take在阻塞中) + * @param item 元素 + * @return boolean + */ + @Override + public void put(E item) throws InterruptedException { + // 1、put元素不为空 + if (item == null) { + throw new NullPointerException(); + } + + int c = -1; + + final ReentrantLock putLock = this.putLock; + final Condition notFull = this.notFull; + final AtomicInteger count = this.count; + // 2、上put锁 + putLock.lockInterruptibly(); + try { + // 3、队满,put操作阻塞 + while (count.get() == capacity) {//为什么是while,不是if?防止虚假唤醒 + notFull.await(); + } + // 4、队不满,元素入队 + enqueue(new Node<>(item)); + // 5、校验队列长度是否小于容量,小于则唤醒其他put操作 + c = count.getAndIncrement();// 旧值 + if (c + 1 < capacity) { + notFull.signal(); + } + } finally { + // 6、释放put锁 + putLock.unlock(); + } + // 7、校验队列长度是否等于1,等于则唤醒take操作(这个1是刚put的,可能有take在阻塞中) + if (c == 0) { + signalNotEmpty(); + } + } + + /** + * 实现思路: + * 1、上take锁 + * 2、队空,take操作阻塞 + * 3、队不空,从对头拿一个元素 + * 4、校验队列长度是否大于0,大于则唤醒其他take操作 + * 5、释放take锁 + * 6、校验队列长度是否等于capacity-1,等于则唤醒put操作(这个-1是刚take的,可能有put在阻塞中) + * @return 元素 + */ + @Override + public E take() throws InterruptedException { + E e; + int c; + + final ReentrantLock takeLock = this.takeLock; + final AtomicInteger count = this.count; + final Condition notEmpty = this.notEmpty; + // 1、上take锁 + takeLock.lockInterruptibly(); + try { + // 2、队空,take操作阻塞 + while (count.get() == 0) {//为什么是while,不是if?防止虚假唤醒 + notEmpty.await(); + } + // 3、队不空,从对头拿一个元素 + e = dequeue(); + c = count.getAndDecrement(); // 次处为旧值,旧值=新值 + 1。为啥是拿旧值? + // 4、校验队列长度是否大于0,大于则唤醒其他take操作 + if (c > 1) { + notEmpty.signal(); + } + } finally { + // 5、释放take锁 + takeLock.unlock(); + } + // 6、校验队列长度是否等于capacity-1,等于则唤醒put操作(这个-1是刚take的,可能有put在阻塞中) + if (c == capacity) + signalNotFull(); + return e; + } + + private void signalNotEmpty() { + final ReentrantLock takeLock = this.takeLock; + takeLock.lock(); + try { + notEmpty.signal(); + } finally { + takeLock.unlock(); + } + } + + private void signalNotFull() { + final ReentrantLock putLock = this.putLock; + putLock.lock(); + try { + notFull.signal(); + } finally { + putLock.unlock(); + } + } + + /** + * 结点出队(队头) + * + */ + private E dequeue() { + // 取出头节点 + Node h = head; + // 头节点的下一个节点为 first + Node first = h.next; + // 使 h 的下一个节点指向自己 + h.next = h; // help GC + // 给链表头赋值 + head = first; + // 取出链表头值 + E x = first.item; + // 旧头节点指向 null,帮助 GC + first.item = null; + // 返回旧头节点值 + return x; + } + + /** + * 结点入队(队尾) + * + * @param node 结点 + */ + private void enqueue(Node node) { + tail = tail.next = node; + } +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/my/Queue.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/my/Queue.java new file mode 100644 index 00000000..385f94c5 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/my/Queue.java @@ -0,0 +1,35 @@ +package cn.lastwhisper.learn8.util.concurrent.queue.my; + +/** + * 队列接口 + * @author lastwhisper + * @date 2020/4/17 + */ +public interface Queue { + + // 队列中元素的基本结构 + class Node { + // 数据本身 + E item; + // 下一个元素 + Node next; + + // 构造器 + public Node(E item) { + this.item = item; + } + } + + /** + * 放数据 + * @param item 入参 + */ + void put(E item) throws InterruptedException; + + /** + * 拿数据,返回一个泛型值 + * @return 数据 + */ + E take() throws InterruptedException; + +} diff --git a/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/my/QueueTest.java b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/my/QueueTest.java new file mode 100644 index 00000000..6807dc40 --- /dev/null +++ b/java-basic/learn-source-jdk8/src/main/java/cn/lastwhisper/learn8/util/concurrent/queue/my/QueueTest.java @@ -0,0 +1,73 @@ +package cn.lastwhisper.learn8.util.concurrent.queue.my; + +import java.util.concurrent.TimeUnit; + +/** + * + * @author lastwhisper + * @date 2020/4/18 + */ +public class QueueTest { + + public static void main(String[] args) throws InterruptedException { + Queue blockingQueue = new LinkedBlockingQueue<>(3); + System.out.println("/*----------------capacity=3---------------*/"); + blockingQueue.put("a"); + blockingQueue.put("b"); + blockingQueue.put("c"); + System.out.println("thread name:" + Thread.currentThread().getName() + + ",put a、b、c三个元素"); + + new Thread(new Runnable() { + @Override + public void run() { + try { + System.out.println("thread name:" + Thread.currentThread().getName() + + ",5秒后执行take操作"); + TimeUnit.SECONDS.sleep(5); + blockingQueue.take(); + System.out.println("thread name:" + Thread.currentThread().getName() + + ",take操作执行,take a,并唤醒put操作"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }).start(); + + System.out.println("thread name:" + Thread.currentThread().getName() + + ",开始执行put操作,队满一直阻塞"); + blockingQueue.put("d"); + System.out.println("thread name:" + Thread.currentThread().getName() + + ",put操作被唤醒,put d"); + blockingQueue.take(); + blockingQueue.take(); + blockingQueue.take(); + System.out.println("thread name:" + Thread.currentThread().getName() + + ",take操作执行,take b c d"); + + new Thread(new Runnable() { + @Override + public void run() { + try { + System.out.println("thread name:" + Thread.currentThread().getName() + + ",5秒后执行put操作"); + TimeUnit.SECONDS.sleep(5); + blockingQueue.put("d"); + System.out.println("thread name:" + Thread.currentThread().getName() + + ",put操作执行,put d,并唤醒take操作"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }).start(); + + System.out.println("thread name:" + Thread.currentThread().getName() + + ",开始执行take操作,队空一直阻塞"); + blockingQueue.take(); + System.out.println("thread name:" + Thread.currentThread().getName() + + ",take操作被唤醒,take d"); + + } + + +} diff --git a/java-basic/pom.xml b/java-basic/pom.xml deleted file mode 100644 index a961deff..00000000 --- a/java-basic/pom.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - 4.0.0 - - cn.lastwhisper - java-basic - pom - 1.0-SNAPSHOT - - concurrent - jvm - jdk5 - design-pattern - interview - jdk8 - jdk9 - jdk11 - jdk12 - jdk13 - - - - - - org.projectlombok - lombok - 1.18.10 - - - - junit - junit - 4.12 - - - - mysql - mysql-connector-java - 5.1.38 - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.8 - 1.8 - - - - - - - \ No newline at end of file diff --git a/lesson-code/design/fsm/README.md b/lesson-code/design/fsm/README.md new file mode 100644 index 00000000..c16d0458 --- /dev/null +++ b/lesson-code/design/fsm/README.md @@ -0,0 +1,4 @@ +有限状态机 +- switch-case +- driver-table +- state-pattern \ No newline at end of file diff --git a/lesson-code/design/fsm/pom.xml b/lesson-code/design/fsm/pom.xml new file mode 100644 index 00000000..169ad03f --- /dev/null +++ b/lesson-code/design/fsm/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + + cn.cunchang + fsm + 1.0-SNAPSHOT + + + 8 + 8 + + + \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/ApplicationDemo.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/ApplicationDemo.java new file mode 100644 index 00000000..28a885ae --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/ApplicationDemo.java @@ -0,0 +1,11 @@ +package cn.cunchang; + +public class ApplicationDemo { + public static void main(String[] args) { + MarioStateMachine mario = new MarioStateMachine(); + mario.obtainMushRoom(); + int score = mario.getScore(); + State state = mario.getCurrentState(); + System.out.println("mario score: " + score + "; state: " + state); + } +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/MarioStateMachine.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/MarioStateMachine.java new file mode 100644 index 00000000..3014a29d --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/MarioStateMachine.java @@ -0,0 +1,42 @@ +package cn.cunchang; + +public class MarioStateMachine { + private int score; + private State currentState; + + public MarioStateMachine() { + this.score = 0; + this.currentState = State.SMALL; + } + + public void obtainMushRoom() { + //TODO + } + + public void obtainCape() { + //TODO + } + + public void obtainFireFlower() { + //TODO + } + + public void meetMonster() { + //TODO + } + + public int getScore() { + return this.score; + } + + public State getCurrentState() { + return this.currentState; + } + + public void print() { + int score = this.score; + State state = this.currentState; + System.out.println("mario score: " + score + "; state: " + state); + } + +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/State.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/State.java new file mode 100644 index 00000000..9aad3f87 --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/State.java @@ -0,0 +1,17 @@ +package cn.cunchang; + +public enum State { + SMALL(0), + SUPER(1), + FIRE(2), + CAPE(3); + private int value; + + private State(int value) { + this.value = value; + } + + public int getValue() { + return this.value; + } +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/ApplicationDemo.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/ApplicationDemo.java new file mode 100644 index 00000000..493c5eaf --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/ApplicationDemo.java @@ -0,0 +1,20 @@ +package cn.cunchang.state.v1; + +public class ApplicationDemo { + public static void main(String[] args) { + MarioStateMachine mario = new MarioStateMachine(); + // 吃了蘑菇 + mario.obtainMushRoom(); + mario.print(); + // 获得斗篷 + mario.obtainCape(); + mario.print(); + // 遇到怪物 + mario.meetMonster(); + mario.print(); + // 获得火焰 + mario.obtainFireFlower(); + mario.print(); + } + +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/CapeMario.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/CapeMario.java new file mode 100644 index 00000000..5deb00b8 --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/CapeMario.java @@ -0,0 +1,36 @@ +package cn.cunchang.state.v1; + +public class CapeMario implements IMario { + + private MarioStateMachine stateMachine; + + public CapeMario(MarioStateMachine stateMachine) { + this.stateMachine = stateMachine; + } + + @Override + public State getName() { + return State.CAPE; + } + + @Override + public void obtainMushRoom() { + + } + + @Override + public void obtainCape() { + + } + + @Override + public void obtainFireFlower() { + + } + + @Override + public void meetMonster() { + stateMachine.setCurrentState(new SmallMario(stateMachine)); + stateMachine.setScore(stateMachine.getScore()-200); + } +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/FireMario.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/FireMario.java new file mode 100644 index 00000000..0223438f --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/FireMario.java @@ -0,0 +1,36 @@ +package cn.cunchang.state.v1; + +public class FireMario implements IMario { + + private MarioStateMachine stateMachine; + + public FireMario(MarioStateMachine stateMachine) { + this.stateMachine = stateMachine; + } + + @Override + public State getName() { + return State.FIRE; + } + + @Override + public void obtainMushRoom() { + + } + + @Override + public void obtainCape() { + + } + + @Override + public void obtainFireFlower() { + + } + + @Override + public void meetMonster() { + stateMachine.setCurrentState(new SmallMario(stateMachine)); + stateMachine.setScore(stateMachine.getScore()-300); + } +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/IMario.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/IMario.java new file mode 100644 index 00000000..60624030 --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/IMario.java @@ -0,0 +1,14 @@ +package cn.cunchang.state.v1; + +public interface IMario { //所有状态类的接口 + State getName(); + + //以下是定义的事件 + void obtainMushRoom(); + + void obtainCape(); + + void obtainFireFlower(); + + void meetMonster(); +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/MarioStateMachine.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/MarioStateMachine.java new file mode 100644 index 00000000..c982ae1a --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/MarioStateMachine.java @@ -0,0 +1,50 @@ +package cn.cunchang.state.v1; + +public class MarioStateMachine { + private int score; + private IMario currentState; // 不再使用枚举来表示状态 + + public MarioStateMachine() { + this.score = 0; + this.currentState = new SmallMario(this); + } + + public void obtainMushRoom() { + this.currentState.obtainMushRoom(); + } + + public void obtainCape() { + this.currentState.obtainCape(); + } + + public void obtainFireFlower() { + this.currentState.obtainFireFlower(); + } + + public void meetMonster() { + this.currentState.meetMonster(); + } + + public int getScore() { + return this.score; + } + + public State getCurrentState() { + return this.currentState.getName(); + } + + public void setScore(int score) { + this.score = score; + } + + public void setCurrentState(IMario currentState) { + this.currentState = currentState; + } + + public void print(){ + int score = this.score; + State state = this.currentState.getName(); + System.out.println("mario score: " + score + "; state: " + state); + } + +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/SmallMario.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/SmallMario.java new file mode 100644 index 00000000..48a92fb5 --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/SmallMario.java @@ -0,0 +1,38 @@ +package cn.cunchang.state.v1; + +public class SmallMario implements IMario { + + private MarioStateMachine stateMachine; + + public SmallMario(MarioStateMachine stateMachine) { + this.stateMachine = stateMachine; + } + + @Override + public State getName() { + return State.SMALL; + } + + @Override + public void obtainMushRoom() { + stateMachine.setCurrentState(new SuperMario(stateMachine)); + stateMachine.setScore(stateMachine.getScore()+100); + } + + @Override + public void obtainCape() { + stateMachine.setCurrentState(new CapeMario(stateMachine)); + stateMachine.setScore(stateMachine.getScore()+200); + } + + @Override + public void obtainFireFlower() { + stateMachine.setCurrentState(new FireMario(stateMachine)); + stateMachine.setScore(stateMachine.getScore()+300); + } + + @Override + public void meetMonster() { + + } +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/State.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/State.java new file mode 100644 index 00000000..ad6436bf --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/State.java @@ -0,0 +1,18 @@ +package cn.cunchang.state.v1; + +public enum State { + SMALL(0), + SUPER(1), + CAPE(2), + FIRE(3), + ; + private int value; + + private State(int value) { + this.value = value; + } + + public int getValue() { + return this.value; + } +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/SuperMario.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/SuperMario.java new file mode 100644 index 00000000..08bd431d --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v1/SuperMario.java @@ -0,0 +1,38 @@ +package cn.cunchang.state.v1; + +public class SuperMario implements IMario { + + private MarioStateMachine stateMachine; + + public SuperMario(MarioStateMachine stateMachine) { + this.stateMachine = stateMachine; + } + + @Override + public State getName() { + return State.SUPER; + } + + @Override + public void obtainMushRoom() { + + } + + @Override + public void obtainCape() { + stateMachine.setCurrentState(new CapeMario(stateMachine)); + stateMachine.setScore(stateMachine.getScore()+200); + } + + @Override + public void obtainFireFlower() { + stateMachine.setCurrentState(new FireMario(stateMachine)); + stateMachine.setScore(stateMachine.getScore()+300); + } + + @Override + public void meetMonster() { + stateMachine.setCurrentState(new SmallMario(stateMachine)); + stateMachine.setScore(stateMachine.getScore()-100); + } +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/ApplicationDemo.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/ApplicationDemo.java new file mode 100644 index 00000000..0a525009 --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/ApplicationDemo.java @@ -0,0 +1,21 @@ +package cn.cunchang.state.v2; + +public class ApplicationDemo { + public static void main(String[] args) { + MarioStateMachine mario = new MarioStateMachine(); + mario.print(); + // 吃了蘑菇 + mario.obtainMushRoom(); + mario.print(); + // 获得斗篷 + mario.obtainCape(); + mario.print(); + // 遇到怪物 + mario.meetMonster(); + mario.print(); + // 获得火焰 + mario.obtainFireFlower(); + mario.print(); + } + +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/CapeMario.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/CapeMario.java new file mode 100644 index 00000000..8eb2d47a --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/CapeMario.java @@ -0,0 +1,38 @@ +package cn.cunchang.state.v2; + +public class CapeMario implements IMario { + private static final CapeMario instance = new CapeMario(); + + private CapeMario() { + } + + public static CapeMario getInstance() { + return instance; + } + + @Override + public State getName() { + return State.CAPE; + } + + @Override + public void obtainMushRoom(MarioStateMachine stateMachine) { + + } + + @Override + public void obtainCape(MarioStateMachine stateMachine) { + + } + + @Override + public void obtainFireFlower(MarioStateMachine stateMachine) { + + } + + @Override + public void meetMonster(MarioStateMachine stateMachine) { + stateMachine.setCurrentState(SmallMario.getInstance()); + stateMachine.setScore(stateMachine.getScore()-200); + } +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/FireMario.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/FireMario.java new file mode 100644 index 00000000..6bb65309 --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/FireMario.java @@ -0,0 +1,39 @@ +package cn.cunchang.state.v2; + +public class FireMario implements IMario { + + private static final FireMario instance = new FireMario(); + + private FireMario() { + } + + public static FireMario getInstance() { + return instance; + } + + @Override + public State getName() { + return State.FIRE; + } + + @Override + public void obtainMushRoom(MarioStateMachine stateMachine) { + + } + + @Override + public void obtainCape(MarioStateMachine stateMachine) { + + } + + @Override + public void obtainFireFlower(MarioStateMachine stateMachine) { + + } + + @Override + public void meetMonster(MarioStateMachine stateMachine) { + stateMachine.setCurrentState(SmallMario.getInstance()); + stateMachine.setScore(stateMachine.getScore()-300); + } +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/IMario.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/IMario.java new file mode 100644 index 00000000..c680d09e --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/IMario.java @@ -0,0 +1,14 @@ +package cn.cunchang.state.v2; + +public interface IMario { //所有状态类的接口 + State getName(); + + //以下是定义的事件 + void obtainMushRoom(MarioStateMachine stateMachine); + + void obtainCape(MarioStateMachine stateMachine); + + void obtainFireFlower(MarioStateMachine stateMachine); + + void meetMonster(MarioStateMachine stateMachine); +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/MarioStateMachine.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/MarioStateMachine.java new file mode 100644 index 00000000..777e9f19 --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/MarioStateMachine.java @@ -0,0 +1,50 @@ +package cn.cunchang.state.v2; + +public class MarioStateMachine { + private int score; + private IMario currentState; // 不再使用枚举来表示状态 + + public MarioStateMachine() { + this.score = 0; + this.currentState = SmallMario.getInstance(); + } + + public void obtainMushRoom() { + this.currentState.obtainMushRoom(this); + } + + public void obtainCape() { + this.currentState.obtainCape(this); + } + + public void obtainFireFlower() { + this.currentState.obtainFireFlower(this); + } + + public void meetMonster() { + this.currentState.meetMonster(this); + } + + public int getScore() { + return this.score; + } + + public State getCurrentState() { + return this.currentState.getName(); + } + + public void setScore(int score) { + this.score = score; + } + + public void setCurrentState(IMario currentState) { + this.currentState = currentState; + } + + public void print(){ + int score = this.score; + State state = this.getCurrentState(); + System.out.println("mario score: " + score + "; state: " + state); + } + +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/SmallMario.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/SmallMario.java new file mode 100644 index 00000000..9e36e300 --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/SmallMario.java @@ -0,0 +1,42 @@ +package cn.cunchang.state.v2; + +public class SmallMario implements IMario { + + private static final SmallMario instance = new SmallMario(); + + private SmallMario() { + } + + public static SmallMario getInstance() { + return instance; + } + + + @Override + public State getName() { + return State.SMALL; + } + + @Override + public void obtainMushRoom(MarioStateMachine stateMachine) { + stateMachine.setCurrentState(SuperMario.getInstance()); + stateMachine.setScore(stateMachine.getScore() + 100); + } + + @Override + public void obtainCape(MarioStateMachine stateMachine) { + stateMachine.setCurrentState(CapeMario.getInstance()); + stateMachine.setScore(stateMachine.getScore() + 200); + } + + @Override + public void obtainFireFlower(MarioStateMachine stateMachine) { + stateMachine.setCurrentState(FireMario.getInstance()); + stateMachine.setScore(stateMachine.getScore() + 300); + } + + @Override + public void meetMonster(MarioStateMachine stateMachine) { + + } +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/State.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/State.java new file mode 100644 index 00000000..4f50886d --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/State.java @@ -0,0 +1,18 @@ +package cn.cunchang.state.v2; + +public enum State { + SMALL(0), + SUPER(1), + CAPE(2), + FIRE(3), + ; + private int value; + + private State(int value) { + this.value = value; + } + + public int getValue() { + return this.value; + } +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/SuperMario.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/SuperMario.java new file mode 100644 index 00000000..3bb18d68 --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/state/v2/SuperMario.java @@ -0,0 +1,41 @@ +package cn.cunchang.state.v2; + +public class SuperMario implements IMario { + + private static final SuperMario instance = new SuperMario(); + + private SuperMario() { + } + + public static SuperMario getInstance() { + return instance; + } + + @Override + public State getName() { + return State.SUPER; + } + + @Override + public void obtainMushRoom(MarioStateMachine stateMachine) { + + } + + @Override + public void obtainCape(MarioStateMachine stateMachine) { + stateMachine.setCurrentState(CapeMario.getInstance()); + stateMachine.setScore(stateMachine.getScore()+200); + } + + @Override + public void obtainFireFlower(MarioStateMachine stateMachine) { + stateMachine.setCurrentState(FireMario.getInstance()); + stateMachine.setScore(stateMachine.getScore()+300); + } + + @Override + public void meetMonster(MarioStateMachine stateMachine) { + stateMachine.setCurrentState(SmallMario.getInstance()); + stateMachine.setScore(stateMachine.getScore()-100); + } +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/switchcase/ApplicationDemo.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/switchcase/ApplicationDemo.java new file mode 100644 index 00000000..bc2ad543 --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/switchcase/ApplicationDemo.java @@ -0,0 +1,21 @@ +package cn.cunchang.switchcase; + +public class ApplicationDemo { + public static void main(String[] args) { + MarioStateMachine mario = new MarioStateMachine(); + mario.print(); + // 吃了蘑菇 + mario.obtainMushRoom(); + mario.print(); + // 获得斗篷 + mario.obtainCape(); + mario.print(); + // 遇到怪物 + mario.meetMonster(); + mario.print(); + // 获得火焰 + mario.obtainFireFlower(); + mario.print(); + } + +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/switchcase/MarioStateMachine.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/switchcase/MarioStateMachine.java new file mode 100644 index 00000000..b4ba58f5 --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/switchcase/MarioStateMachine.java @@ -0,0 +1,66 @@ +package cn.cunchang.switchcase; + +import java.util.Objects; + +public class MarioStateMachine { + private int score; + private State currentState; + + public MarioStateMachine() { + this.score = 0; + this.currentState = State.SMALL; + } + + public void obtainMushRoom() { + if (Objects.equals(this.currentState, State.SMALL)) { + this.score += 100; + this.currentState = State.SUPER; + } + } + + public void obtainCape() { + if (Objects.equals(this.currentState, State.SMALL) || + Objects.equals(this.currentState, State.SUPER)) { + this.score += 200; + this.currentState = State.CAPE; + } + } + + public void obtainFireFlower() { + if (Objects.equals(this.currentState, State.SMALL) || + Objects.equals(this.currentState, State.SUPER)) { + this.score += 300; + this.currentState = State.FIRE; + } + } + + public void meetMonster() { + if (Objects.equals(this.currentState, State.SUPER)) { + this.score -= 100; + this.currentState = State.SMALL; + } + if (Objects.equals(this.currentState, State.CAPE)) { + this.score -= 200; + this.currentState = State.SMALL; + } + if (Objects.equals(this.currentState, State.FIRE)) { + this.score -= 300; + this.currentState = State.SMALL; + } + } + + public int getScore() { + return this.score; + } + + public State getCurrentState() { + return this.currentState; + } + + public void print(){ + int score = this.score; + State state = this.currentState; + System.out.println("mario score: " + score + "; state: " + state); + } + +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/switchcase/State.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/switchcase/State.java new file mode 100644 index 00000000..e73af6b9 --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/switchcase/State.java @@ -0,0 +1,18 @@ +package cn.cunchang.switchcase; + +public enum State { + SMALL(0), + SUPER(1), + CAPE(2), + FIRE(3), + ; + private int value; + + private State(int value) { + this.value = value; + } + + public int getValue() { + return this.value; + } +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/table/ApplicationDemo.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/table/ApplicationDemo.java new file mode 100644 index 00000000..89934837 --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/table/ApplicationDemo.java @@ -0,0 +1,21 @@ +package cn.cunchang.table; + +public class ApplicationDemo { + public static void main(String[] args) { + MarioStateMachine mario = new MarioStateMachine(); + mario.print(); + // 吃了蘑菇 + mario.obtainMushRoom(); + mario.print(); + // 获得斗篷 + mario.obtainCape(); + mario.print(); + // 遇到怪物 + mario.meetMonster(); + mario.print(); + // 获得火焰 + mario.obtainFireFlower(); + mario.print(); + } + +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/table/Event.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/table/Event.java new file mode 100644 index 00000000..3f3103ee --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/table/Event.java @@ -0,0 +1,17 @@ +package cn.cunchang.table; + +public enum Event { + GOT_MUSHROOM(0), + GOT_CAPE(1), + GOT_FIRE(2), + MET_MONSTER(3); + private int value; + + private Event(int value) { + this.value = value; + } + + public int getValue() { + return this.value; + } +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/table/MarioStateMachine.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/table/MarioStateMachine.java new file mode 100644 index 00000000..a80a0a78 --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/table/MarioStateMachine.java @@ -0,0 +1,63 @@ +package cn.cunchang.table; + +import static cn.cunchang.table.State.*; + +public class MarioStateMachine { + private int score; + private State currentState; + private static final State[][] transitionTable = { + {SUPER, CAPE, FIRE, SMALL}, + {SUPER, CAPE, FIRE, SMALL}, + {CAPE, CAPE, CAPE, SMALL}, + {FIRE, FIRE, FIRE, SMALL} + }; + private static final int[][] actionTable = { + {+100, +200, +300, +0}, + {+0, +200, +300, -100}, + {+0, +0, +0, -200}, + {+0, +0, +0, -300} + }; + + public MarioStateMachine() { + this.score = 0; + this.currentState = State.SMALL; + } + + public void obtainMushRoom() { + executeEvent(Event.GOT_MUSHROOM); + } + + public void obtainCape() { + executeEvent(Event.GOT_CAPE); + } + + public void obtainFireFlower() { + executeEvent(Event.GOT_FIRE); + } + + public void meetMonster() { + executeEvent(Event.MET_MONSTER); + } + + private void executeEvent(Event event) { + int stateValue = currentState.getValue(); + int eventValue = event.getValue(); + this.currentState = transitionTable[stateValue][eventValue]; + this.score += actionTable[stateValue][eventValue]; + } + + public int getScore() { + return this.score; + } + + public State getCurrentState() { + return this.currentState; + } + + public void print(){ + int score = this.score; + State state = this.currentState; + System.out.println("mario score: " + score + "; state: " + state); + } + +} \ No newline at end of file diff --git a/lesson-code/design/fsm/src/main/java/cn/cunchang/table/State.java b/lesson-code/design/fsm/src/main/java/cn/cunchang/table/State.java new file mode 100644 index 00000000..4c5d346f --- /dev/null +++ b/lesson-code/design/fsm/src/main/java/cn/cunchang/table/State.java @@ -0,0 +1,19 @@ +package cn.cunchang.table; + +public enum State { + SMALL(0), + SUPER(1), + CAPE(2), + FIRE(3), + + ; + private int value; + + private State(int value) { + this.value = value; + } + + public int getValue() { + return this.value; + } +} \ No newline at end of file diff --git a/lesson-code/java-common-mistakes/pom.xml b/lesson-code/java-common-mistakes/pom.xml new file mode 100644 index 00000000..45a476a1 --- /dev/null +++ b/lesson-code/java-common-mistakes/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + cn.cunchang + java-common-mistakes + 1.0-SNAPSHOT + + + 8 + 8 + + + + + + org.slf4j + slf4j-api + 1.7.26 + + + + ch.qos.logback + logback-classic + 1.2.3 + + + + org.projectlombok + lombok + 1.18.20 + + + + junit + junit + 4.13.1 + + + + org.jodd + jodd-core + 5.1.6 + + + + + \ No newline at end of file diff --git a/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/TestSomething.java b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/TestSomething.java new file mode 100644 index 00000000..760789ab --- /dev/null +++ b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/TestSomething.java @@ -0,0 +1,45 @@ +package cn.cunchang; + +import org.junit.Test; + +import java.time.LocalDate; +import java.time.Period; +import java.time.format.DateTimeFormatter; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * @author cunchang + * @date 2021/7/13 9:55 上午 + */ +public class TestSomething { + + @Test + public void test1() { + String payload = IntStream.rangeClosed(1, 1000000) + .mapToObj((item) -> "a") + .collect(Collectors.joining("")); + System.out.println(payload.length()); + } + + @Test + public void test2() { +// LocalDate startDate = LocalDate.now().plusDays(-17L); + LocalDate startDate = LocalDate.parse("20210701", DateTimeFormatter.ofPattern("yyyyMMdd")); + LocalDate endDate = LocalDate.parse("20210713", DateTimeFormatter.ofPattern("yyyyMMdd")); + + endDate = endDate.plusDays(1L); + + Period between = Period.between(startDate, endDate); + System.out.println(between.getDays()); + + int i=0; + while (startDate.isBefore(endDate)) { + i++; + System.out.println(startDate); + startDate = startDate.plusDays(1L); + } + System.out.println("i:"+i); + } + +} diff --git a/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/Cart.java b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/Cart.java new file mode 100644 index 00000000..fee2e880 --- /dev/null +++ b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/Cart.java @@ -0,0 +1,22 @@ +package cn.cunchang.repeatcode; + +import lombok.Data; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +//购物车 +@Data +public class Cart { + //商品清单 + private List items = new ArrayList<>(); + //总优惠 + private BigDecimal totalDiscount; + //商品总价 + private BigDecimal totalItemPrice; + //总运费 + private BigDecimal totalDeliveryPrice; + //应付总价 + private BigDecimal payPrice; +} \ No newline at end of file diff --git a/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/Db.java b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/Db.java new file mode 100644 index 00000000..af3c6249 --- /dev/null +++ b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/Db.java @@ -0,0 +1,31 @@ +package cn.cunchang.repeatcode; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; + +public class Db { + + private static Map items = new HashMap<>(); + + static { + items.put(1L, new BigDecimal("10")); + items.put(2L, new BigDecimal("20")); + } + + public static BigDecimal getItemPrice(long id) { + return items.get(id); + } + + public static String getUserCategory(long userId) { + + if (userId == 1L) return "Normal"; + if (userId == 2L) return "Vip"; + if (userId == 3L) return "Internal"; + return "Normal"; + } + + public static int getUserCouponPercent(long userId) { + return 90; + } +} \ No newline at end of file diff --git a/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/Item.java b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/Item.java new file mode 100644 index 00000000..bfcb1b3c --- /dev/null +++ b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/Item.java @@ -0,0 +1,20 @@ +package cn.cunchang.repeatcode; + +import lombok.Data; + +import java.math.BigDecimal; + +//购物车中的商品 +@Data +public class Item { + //商品ID + private long id; + //商品数量 + private int quantity; + //商品单价 + private BigDecimal price; + //商品优惠 + private BigDecimal couponPrice; + //商品运费 + private BigDecimal deliveryPrice; +} \ No newline at end of file diff --git a/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/NormalUserCart.java b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/NormalUserCart.java new file mode 100644 index 00000000..d9d7968c --- /dev/null +++ b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/NormalUserCart.java @@ -0,0 +1,42 @@ +package cn.cunchang.repeatcode; + + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class NormalUserCart { + public Cart process(long userId, Map items) { + Cart cart = new Cart(); + + //把Map的购物车转换为Item列表 + List itemList = new ArrayList<>(); + items.entrySet().stream().forEach(entry -> { + Item item = new Item(); + item.setId(entry.getKey()); + item.setPrice(Db.getItemPrice(entry.getKey())); + item.setQuantity(entry.getValue()); + itemList.add(item); + }); + cart.setItems(itemList); + + //处理运费和商品优惠 + itemList.stream().forEach(item -> { + //运费为商品总价的10% + item.setDeliveryPrice(item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity())).multiply(new BigDecimal("0.1"))); + //无优惠 + item.setCouponPrice(BigDecimal.ZERO); + }); + + //计算纯商品总价 + cart.setTotalItemPrice(cart.getItems().stream().map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity()))).reduce(BigDecimal.ZERO, BigDecimal::add)); + //计算运费总价 + cart.setTotalDeliveryPrice(cart.getItems().stream().map(Item::getDeliveryPrice).reduce(BigDecimal.ZERO, BigDecimal::add)); + //计算总优惠 + cart.setTotalDiscount(cart.getItems().stream().map(Item::getCouponPrice).reduce(BigDecimal.ZERO, BigDecimal::add)); + //应付总价=商品总价+运费总价-总优惠 + cart.setPayPrice(cart.getTotalItemPrice().add(cart.getTotalDeliveryPrice()).subtract(cart.getTotalDiscount())); + return cart; + } +} \ No newline at end of file diff --git a/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/wrong/InternalUserCart.java b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/wrong/InternalUserCart.java new file mode 100644 index 00000000..1f6857a2 --- /dev/null +++ b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/wrong/InternalUserCart.java @@ -0,0 +1,40 @@ +package cn.cunchang.repeatcode.wrong; + +import cn.cunchang.repeatcode.Cart; +import cn.cunchang.repeatcode.Db; +import cn.cunchang.repeatcode.Item; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class InternalUserCart { + + public Cart process(long userId, Map items) { + Cart cart = new Cart(); + + List itemList = new ArrayList<>(); + items.entrySet().stream().forEach(entry -> { + Item item = new Item(); + item.setId(entry.getKey()); + item.setPrice(Db.getItemPrice(entry.getKey())); + item.setQuantity(entry.getValue()); + itemList.add(item); + }); + cart.setItems(itemList); + + itemList.stream().forEach(item -> { + //免运费 + item.setDeliveryPrice(BigDecimal.ZERO); + //无优惠 + item.setCouponPrice(BigDecimal.ZERO); + }); + + cart.setTotalItemPrice(cart.getItems().stream().map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity()))).reduce(BigDecimal.ZERO, BigDecimal::add)); + cart.setTotalDeliveryPrice(cart.getItems().stream().map(Item::getDeliveryPrice).reduce(BigDecimal.ZERO, BigDecimal::add)); + cart.setTotalDiscount(cart.getItems().stream().map(Item::getCouponPrice).reduce(BigDecimal.ZERO, BigDecimal::add)); + cart.setPayPrice(cart.getTotalItemPrice().add(cart.getTotalDeliveryPrice()).subtract(cart.getTotalDiscount())); + return cart; + } +} \ No newline at end of file diff --git a/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/wrong/NormalUserCart.java b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/wrong/NormalUserCart.java new file mode 100644 index 00000000..8f238dba --- /dev/null +++ b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/wrong/NormalUserCart.java @@ -0,0 +1,45 @@ +package cn.cunchang.repeatcode.wrong; + +import cn.cunchang.repeatcode.Cart; +import cn.cunchang.repeatcode.Db; +import cn.cunchang.repeatcode.Item; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class NormalUserCart { + public Cart process(long userId, Map items) { + Cart cart = new Cart(); + + //把Map的购物车转换为Item列表 + List itemList = new ArrayList<>(); + items.entrySet().stream().forEach(entry -> { + Item item = new Item(); + item.setId(entry.getKey()); + item.setPrice(Db.getItemPrice(entry.getKey())); + item.setQuantity(entry.getValue()); + itemList.add(item); + }); + cart.setItems(itemList); + + //处理运费和商品优惠 + itemList.stream().forEach(item -> { + //运费为商品总价的10% + item.setDeliveryPrice(item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity())).multiply(new BigDecimal("0.1"))); + //无优惠 + item.setCouponPrice(BigDecimal.ZERO); + }); + + //计算纯商品总价 + cart.setTotalItemPrice(cart.getItems().stream().map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity()))).reduce(BigDecimal.ZERO, BigDecimal::add)); + //计算运费总价 + cart.setTotalDeliveryPrice(cart.getItems().stream().map(Item::getDeliveryPrice).reduce(BigDecimal.ZERO, BigDecimal::add)); + //计算总优惠 + cart.setTotalDiscount(cart.getItems().stream().map(Item::getCouponPrice).reduce(BigDecimal.ZERO, BigDecimal::add)); + //应付总价=商品总价+运费总价-总优惠 + cart.setPayPrice(cart.getTotalItemPrice().add(cart.getTotalDeliveryPrice()).subtract(cart.getTotalDiscount())); + return cart; + } +} diff --git a/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/wrong/VipUserCart.java b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/wrong/VipUserCart.java new file mode 100644 index 00000000..bc99fa4b --- /dev/null +++ b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/repeatcode/wrong/VipUserCart.java @@ -0,0 +1,46 @@ +package cn.cunchang.repeatcode.wrong; + +import cn.cunchang.repeatcode.Cart; +import cn.cunchang.repeatcode.Db; +import cn.cunchang.repeatcode.Item; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class VipUserCart { + + public Cart process(long userId, Map items) { + Cart cart = new Cart(); + + List itemList = new ArrayList<>(); + items.entrySet().stream().forEach(entry -> { + Item item = new Item(); + item.setId(entry.getKey()); + item.setPrice(Db.getItemPrice(entry.getKey())); + item.setQuantity(entry.getValue()); + itemList.add(item); + }); + cart.setItems(itemList); + + itemList.stream().forEach(item -> { + //运费为商品总价的10% + item.setDeliveryPrice(item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity())).multiply(new BigDecimal("0.1"))); + //购买两件以上相同商品,第三件开始享受一定折扣 + if (item.getQuantity() > 2) { + item.setCouponPrice(item.getPrice() + .multiply(BigDecimal.valueOf(100 - Db.getUserCouponPercent(userId)).divide(new BigDecimal("100"))) + .multiply(BigDecimal.valueOf(item.getQuantity() - 2))); + } else { + item.setCouponPrice(BigDecimal.ZERO); + } + }); + + cart.setTotalItemPrice(cart.getItems().stream().map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity()))).reduce(BigDecimal.ZERO, BigDecimal::add)); + cart.setTotalDeliveryPrice(cart.getItems().stream().map(Item::getDeliveryPrice).reduce(BigDecimal.ZERO, BigDecimal::add)); + cart.setTotalDiscount(cart.getItems().stream().map(Item::getCouponPrice).reduce(BigDecimal.ZERO, BigDecimal::add)); + cart.setPayPrice(cart.getTotalItemPrice().add(cart.getTotalDeliveryPrice()).subtract(cart.getTotalDiscount())); + return cart; + } +} \ No newline at end of file diff --git a/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/threadpool/ExtremeThreadPoolExecutor.java b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/threadpool/ExtremeThreadPoolExecutor.java new file mode 100644 index 00000000..caff249b --- /dev/null +++ b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/threadpool/ExtremeThreadPoolExecutor.java @@ -0,0 +1,72 @@ +package cn.cunchang.threadpool; + +import java.util.concurrent.*; + +/** + * @description 自定义激进线程池,在核心线程数满了后,新的任务来了,直接创建线程,直到达到最大线程数,此时再新来任务,此时再加入阻塞队列 + * @author: darren + * @data: 2020-03-12 10:19 + */ +public class ExtremeThreadPoolExecutor extends ThreadPoolExecutor { + + /** + * 构造方法 + * @param corePoolSize 核心线程数 + * @param maximumPoolSize 最大线程数 + * @param keepAliveTime 非核心线程数保留时长 + * @param unit 非核心线程数保留时长单位 + * @param blockQueueSize 阻塞队列长度 + */ + public ExtremeThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, int blockQueueSize) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, new ExtremeBlockQueue(blockQueueSize), Executors.defaultThreadFactory(), new ExtremePolicy()); + + } + + /** + * 自定义阻塞队列 + * @param + */ + static class ExtremeBlockQueue extends LinkedBlockingQueue { + public ExtremeBlockQueue(int capacity) { + super(capacity); + } + + /** + * 覆盖默认的offer方法,触发拒绝策略执行 + * @param runnable + * @return + */ + @Override + public boolean offer(Runnable runnable) { + return false; + } + + /** + * 拒绝策略触发后,真正的保存进阻塞队列 + * @param runnable + * @return + */ + public boolean extremeOffer(Runnable runnable) { + return super.offer(runnable); + } + } + + /** + * 自定义拒绝策略 + */ + static class ExtremePolicy implements RejectedExecutionHandler { + @Override + public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { + //线程池非关闭 + if (!e.isShutdown()) { + //真正入阻塞队列,若阻塞队列已满,则抛出RejectedExecutionException + if (!((ExtremeBlockQueue)e.getQueue()).extremeOffer(r)) { + //可以真正进行触发策略的执行(不管是默认的,还是自定义的) + throw new RejectedExecutionException("Task " + r.toString() + + " rejected from " + + e.toString()); + } + } + } + } +} \ No newline at end of file diff --git a/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/threadpool/README.md b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/threadpool/README.md new file mode 100644 index 00000000..77b8f832 --- /dev/null +++ b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/threadpool/README.md @@ -0,0 +1,20 @@ + +```properties + +-Xms100m -Xmx100m -XX:+HeapDumpOnOutOfMemoryError + +java.lang.OutOfMemoryError: GC overhead limit exceeded +Dumping heap to java_pid7565.hprof ... +Heap dump file created [163563855 bytes in 0.990 secs] +Exception in thread "main" *** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message can't create name string at JPLISAgent.c line: 807 +[INFO ] 2021-07-13 14:54:06.416 cn.cunchang.threadpool.ThreadPoolOOMTest lambda$printStats$4 81 [pool-2-thread-1] Pool Size: 1 +java.lang.OutOfMemoryError: GC overhead limit exceeded +at java.util.concurrent.LinkedBlockingQueue.offer(LinkedBlockingQueue.java:416) +at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1371) +at cn.cunchang.threadpool.ThreadPoolOOMTest.newFixedThreadPool_oom(ThreadPoolOOMTest.java:37) +at cn.cunchang.threadpool.ThreadPoolOOMTest.main(ThreadPoolOOMTest.java:21) + +``` + + + diff --git a/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/threadpool/ThreadPoolExpansiveTest.java b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/threadpool/ThreadPoolExpansiveTest.java new file mode 100644 index 00000000..e516c5fb --- /dev/null +++ b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/threadpool/ThreadPoolExpansiveTest.java @@ -0,0 +1,74 @@ +package cn.cunchang.threadpool; + +import jodd.util.concurrent.ThreadFactoryBuilder; +import lombok.extern.slf4j.Slf4j; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.IntStream; + +/** + * + * @author cunchang + * @date 2021/7/14 6:34 下午 + */ +@Slf4j +public class ThreadPoolExpansiveTest { + + public static void main(String[] args) throws InterruptedException { + System.out.println("总条数:20,成功条数:"+right());; + } + + /** + * 线程池最大线程扩容太晚,导致任务丢弃 + * + * @return + * @throws InterruptedException + */ + public static int right() throws InterruptedException { + //使用一个计数器跟踪完成的任务数 + AtomicInteger atomicInteger = new AtomicInteger(); + //创建一个具有2个核心线程、5个最大线程,使用容量为10的ArrayBlockingQueue阻塞队列作为工 + ThreadPoolExecutor threadPool = new ThreadPoolExecutor( + 2, 5, + 5, TimeUnit.SECONDS, + new ArrayBlockingQueue<>(10), + new ThreadFactoryBuilder().setNameFormat("demo-threadpool-%d").get(), + new ThreadPoolExecutor.AbortPolicy()); + //threadPool.allowCoreThreadTimeOut(true); +// printStats(threadPool); + //每隔1秒提交一次,一共提交20次任务 + IntStream.rangeClosed(1, 20).forEach(i -> { + + try { + TimeUnit.SECONDS.sleep(1); + } catch (InterruptedException e) { + e.printStackTrace(); + } + int id = atomicInteger.incrementAndGet(); + try { + + threadPool.submit(() -> { + log.info("{} started", id); + //每个任务耗时10秒 + try { + TimeUnit.SECONDS.sleep(10); + } catch (InterruptedException e) { + } + log.info("{} finished", id); + }); + } catch (Exception ex) { + //提交出现异常的话,打印出错信息并为计数器减一 + log.error("error submitting task {}", id, ex); + atomicInteger.decrementAndGet(); + } + }); + + TimeUnit.SECONDS.sleep(60); + return atomicInteger.intValue(); + } + + +} diff --git a/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/threadpool/ThreadPoolOOMTest.java b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/threadpool/ThreadPoolOOMTest.java new file mode 100644 index 00000000..20792a7b --- /dev/null +++ b/lesson-code/java-common-mistakes/src/main/java/cn/cunchang/threadpool/ThreadPoolOOMTest.java @@ -0,0 +1,97 @@ +package cn.cunchang.threadpool; + +import jodd.util.concurrent.ThreadFactoryBuilder; +import lombok.extern.slf4j.Slf4j; + +import java.util.UUID; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * 线程池oom + * + * @author cunchang + * @date 2021/7/13 1:49 上午 + */ +@Slf4j +public class ThreadPoolOOMTest { + + public static void main(String[] args) throws InterruptedException { + // Executors.newFixedThreadPool,固定线程,队列无限大,导致oom +// newFixedThreadPool_oom(); + + // Executors.newCachedThreadPool,无限创建线程,导致oom +// newCachedThreadPool_oom(); + + } + + /** + * -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError + *

+ * 任务较多并且执行较慢的话,队列可能会快速积压,导致oom + * + * @throws InterruptedException + */ + public static void newFixedThreadPool_oom() throws InterruptedException { + + ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(1); + printStats(threadPool); + for (int i = 0; i < 100000000; i++) { + threadPool.execute(() -> { + String payload = IntStream.rangeClosed(1, 1000000) + .mapToObj(__ -> "a") + .collect(Collectors.joining("")) + UUID.randomUUID().toString(); + try { + TimeUnit.HOURS.sleep(1); + } catch (InterruptedException e) { + } + log.info(payload); + }); + } + + threadPool.shutdown(); + threadPool.awaitTermination(1, TimeUnit.HOURS); + } + + /** + * @throws InterruptedException + */ + public static void newCachedThreadPool_oom() throws InterruptedException { + + ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool(); + printStats(threadPool); + for (int i = 0; i < 100000000; i++) { + threadPool.execute(() -> { + String payload = IntStream.rangeClosed(1, 1000000) + .mapToObj(__ -> "a") + .collect(Collectors.joining("")) + UUID.randomUUID().toString(); + try { + TimeUnit.HOURS.sleep(1); + } catch (InterruptedException e) { + } + log.info(payload); + }); + } + + threadPool.shutdown(); + threadPool.awaitTermination(1, TimeUnit.HOURS); + } + + + private static void printStats(ThreadPoolExecutor threadPool) { + Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> { + log.info("========================="); + log.info("Pool Size: {}", threadPool.getPoolSize()); + log.info("Active Threads: {}", threadPool.getActiveCount()); + log.info("Number of Tasks Completed: {}", threadPool.getCompletedTaskCount()); + log.info("Number of Tasks in Queue: {}", threadPool.getQueue().size()); + + log.info("========================="); + }, 0, 1, TimeUnit.SECONDS); + } +} diff --git a/lesson-code/java-common-mistakes/src/main/resources/logback.xml b/lesson-code/java-common-mistakes/src/main/resources/logback.xml new file mode 100644 index 00000000..920d0c29 --- /dev/null +++ b/lesson-code/java-common-mistakes/src/main/resources/logback.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + System.err + + + ${pattern} + + + + + + + + + \ No newline at end of file diff --git a/log/jcl/pom.xml b/log/jcl/pom.xml new file mode 100644 index 00000000..faa3e775 --- /dev/null +++ b/log/jcl/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + + cn.cunchang + jcl + 1.0-SNAPSHOT + + + + commons-logging + commons-logging + 1.2 + + + + log4j + log4j + 1.2.17 + + + + junit + junit + 4.13 + + + \ No newline at end of file diff --git a/log/jcl/src/main/java/cn/cunchang/JCLTest.java b/log/jcl/src/main/java/cn/cunchang/JCLTest.java new file mode 100644 index 00000000..b2473a05 --- /dev/null +++ b/log/jcl/src/main/java/cn/cunchang/JCLTest.java @@ -0,0 +1,35 @@ +package cn.cunchang; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Test; + +/** + * 全称为Jakarta Commons Logging,是Apache提供的一个通用日志API。 + *

+ * 它是为 "所有的Java日志实现"提供一个统一的接口,它自身也提供一个日志的实现,但是功能非常常弱 (SimpleLog)。 + * 所以一般不会单独使用它。他允许开发人员使用不同的具体日志实现工具: Log4j, Jdk 自带的日志(JUL) + *

+ * JCL 有两个基本的抽象类:Log(基本记录器)和LogFactory(负责创建Log实例)。 + */ +public class JCLTest { + + /** + * 不引入log4j,使用jul + * 引入log4j,使用log4j + */ + @Test + public void testQuick() { + // 创建日志对象 + Log log = LogFactory.getLog(this.getClass()); + // 日志记录输出 + log.fatal("fatal"); + log.error("error"); + log.warn("warn"); + log.info("info"); + log.debug("debug"); + } + + + +} diff --git a/log/jcl/src/main/resources/log4j.properties b/log/jcl/src/main/resources/log4j.properties new file mode 100644 index 00000000..8308f75b --- /dev/null +++ b/log/jcl/src/main/resources/log4j.properties @@ -0,0 +1,11 @@ +# 指定 RootLogger 顶级父元素默认配置信息 +# 指定日志级别=trace,使用的 apeender 为=console +log4j.rootLogger = trace,console + +# 指定控制台日志输出的 appender +log4j.appender.console = org.apache.log4j.ConsoleAppender +# 指定消息格式 layout +log4j.appender.console.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.console.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n + diff --git a/log/jul/pom.xml b/log/jul/pom.xml new file mode 100644 index 00000000..4bc8c1d8 --- /dev/null +++ b/log/jul/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + cn.cunchang + jul + 1.0-SNAPSHOT + + + + + junit + junit + 4.13 + + + + \ No newline at end of file diff --git a/log/jul/src/main/java/cn/cunchang/JULTest.java b/log/jul/src/main/java/cn/cunchang/JULTest.java new file mode 100644 index 00000000..ad97168f --- /dev/null +++ b/log/jul/src/main/java/cn/cunchang/JULTest.java @@ -0,0 +1,180 @@ +package cn.cunchang; + +import cn.cunchang.log.MyJULLogFilter; +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.util.logging.*; + +public class JULTest { + + + @Test + public void testQuick() { + // 1、创建日志记录器对象 Logger + Logger logger = Logger.getLogger(this.getClass().getName()); + // 2、日志记录输出 + logger.info("hello jul"); + + logger.log(Level.INFO, "info msg"); + String name = "jack"; + int age = 18; + logger.log(Level.INFO, "用户信息:{0},{1}", new Object[]{name, age}); + } + + /** + * 日志级别分类 + * + * @see java.util.logging.Level 中定义了日志的级别 + */ + @Test + public void testLogLevel() { + // 1.获取日志对象 + Logger logger = Logger.getLogger(this.getClass().getName()); + // 2.日志记录输出 + logger.severe("severe"); + logger.warning("warning"); + logger.info("info"); + logger.config("cofnig"); + logger.fine("fine"); + logger.finer("finer"); + logger.finest("finest"); + } + + /** + * 自定义日志配置 + * + * @throws Exception + */ + @Test + public void testLogConfig() throws Exception { + // 1.获取日志对象 + Logger logger = Logger.getLogger(this.getClass().getName()); + + // 自定义日志配置 + // a.关闭系统默认配置 + logger.setUseParentHandlers(false); + // b.创建handler对象 + ConsoleHandler consoleHandler = new ConsoleHandler(); + // c.创建formatter对象 + SimpleFormatter simpleFormatter = new SimpleFormatter(); + // d.进行关联 + consoleHandler.setFormatter(simpleFormatter); + logger.addHandler(consoleHandler); + // e.设置日志级别 + logger.setLevel(Level.ALL); + consoleHandler.setLevel(Level.ALL); + + // 输出到日志文件 + FileHandler fileHandler = new FileHandler(System.getProperty("user.home") + "/logs/jul.log"); + fileHandler.setFormatter(simpleFormatter); + logger.addHandler(fileHandler); + + // 2.日志记录输出 + logger.severe("severe"); + logger.warning("warning"); + logger.info("info"); + logger.config("config"); + logger.fine("fine"); + logger.finer("finer"); + logger.finest("finest"); + } + + /** + * Logger之间的父子关系

+ *

+ * JUL中Logger之间存在父子关系,这种父子关系通过树状结构存储, + * JUL在初始化时会创建一个顶层 RootLogger作为所有Logger父Logger, + * 存储上作为树状结构的根节点。并父子关系通过路径来关联。 + */ + @Test + public void testLogParent() { + // 日志记录器对象父子关系 + Logger logger1 = Logger.getLogger("cn.cunchang.log"); + Logger logger2 = Logger.getLogger("cn.cunchang"); + + System.out.println("父子日志记录器:" + (logger1.getParent() == logger2)); + // 所有日志记录器对象的顶级父元素 class为java.util.logging.LogManager$RootLogger name为"" + System.out.println("logger2 parent:" + logger2.getParent() + + ",name:" + logger2.getParent().getName()); + } + + /** + * 日志配置文件

+ * /Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib + *

+ * 默认配置文件路径$JAVAHOME\jre\lib\logging.properties + */ + @Test + public void testProperties() throws IOException { + // 读取自定义配置文件 + InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("jul.properties"); + // 获取日志管理器对象 + LogManager logManager = LogManager.getLogManager(); + // 日志管理区加载配置文件 + logManager.readConfiguration(inputStream); + + Logger logger = Logger.getLogger(this.getClass().getName()); + logger.severe("severe"); + logger.warning("warning"); + logger.info("info"); + logger.config("config"); + logger.fine("fine"); + logger.finer("finer"); + logger.finest("finest"); + } + + /** + * JUL的架构实现 + */ + @Test + public void testLogInner() throws IOException { + /* + * 1、获取日志对象logger + * 1.1、初始化LogManager,LogManager.getLogManager() + * - 初始化rootLogger为java.util.logging.LogManager.RootLogger + * - 设置rootLogger的级别为Level.INFO + * - 将rootLogger添加到LogManager + * 1.2、初始化Logger,LogManager.demandLogger(name, resourceBundleName, caller); + * - name一般是包名,logger只会初始化一次 + * - 初始化Logger时默认使用rootLogger的配置(handler、format等) + * + */ +// Logger logger = Logger.getLogger(this.getClass().getName()); + // cn.cunchang.log.MyJULLogFilter会过滤掉"cn.cunchang.log" + Logger logger = Logger.getLogger("cn.cunchang.log"); + + // 2、自定义日志配置 + // a.关闭系统默认配置 + logger.setUseParentHandlers(false); + // b.创建handler对象,用来处理日志输出位置 + ConsoleHandler consoleHandler = new ConsoleHandler(); + // c.创建formatter对象,是用来格式化LogRecord的 + SimpleFormatter simpleFormatter = new SimpleFormatter(); + // d.进行关联 + consoleHandler.setFormatter(simpleFormatter); + logger.addHandler(consoleHandler); + // e.设置日志级别 + logger.setLevel(Level.ALL); + // f.设置日志过滤器,日志级别之外更细粒度的控制 + logger.setFilter(new MyJULLogFilter()); + consoleHandler.setLevel(Level.ALL); + + /* + * 3、日志记录输出 + * msg会被封装成LogRecord + */ + logger.severe("severe"); + logger.warning("warning"); + logger.info("info"); + logger.config("config"); + logger.fine("fine"); + logger.finer("finer"); + logger.finest("finest"); + + + + + } +} diff --git a/log/jul/src/main/java/cn/cunchang/log/MyJULLogFilter.java b/log/jul/src/main/java/cn/cunchang/log/MyJULLogFilter.java new file mode 100644 index 00000000..6c970d66 --- /dev/null +++ b/log/jul/src/main/java/cn/cunchang/log/MyJULLogFilter.java @@ -0,0 +1,24 @@ +package cn.cunchang.log; + +import java.util.logging.Filter; +import java.util.logging.LogRecord; + +/** + * @author cunchang + */ +public class MyJULLogFilter implements Filter { + + /** + * + * @param record + * @return + */ + @Override + public boolean isLoggable(LogRecord record) { + if (record.getLoggerName().equals("cn.cunchang.log")) { + return false; + } + return true; + } + +} diff --git a/log/jul/src/main/resources/jul.properties b/log/jul/src/main/resources/jul.properties new file mode 100644 index 00000000..7029cd72 --- /dev/null +++ b/log/jul/src/main/resources/jul.properties @@ -0,0 +1,38 @@ +# RootLogger 顶级父元素指定的默认处理器为:ConsoleHandler +handlers= java.util.logging.FileHandler + +# RootLogger 顶级父元素默认的日志级别为:ALL +.level= ALL + +# 自定义 Logger 使用 +cn.cunchang.handlers = java.util.logging.ConsoleHandler +cn.cunchang.level = CONFIG + +# 关闭默认配置 +cn.cunchang.useParentHanlders = false + + +# 向日志文件输出的 handler 对象 +# 指定日志文件路径 /logs/java0.log +java.util.logging.FileHandler.pattern = /Users/cunchang/logs/java%u.log +# 指定日志文件内容大小 +java.util.logging.FileHandler.limit = 50000 +# 指定日志文件数量 +java.util.logging.FileHandler.count = 1 +# 指定 handler 对象日志消息格式对象 +java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter +# 指定以追加方式添加日志内容 +java.util.logging.FileHandler.append = true + + +# 向控制台输出的 handler 对象 +# 指定 handler 对象的日志级别 +java.util.logging.ConsoleHandler.level = ALL +# 指定 handler 对象的日志消息格式对象 +java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter +# 指定 handler 对象的字符集 +java.util.logging.ConsoleHandler.encoding = UTF-8 + +# 指定日志消息格式 +java.util.logging.SimpleFormatter.format = %4$s: %5$s [%1$tc]%n + diff --git a/log/log4j/pom.xml b/log/log4j/pom.xml new file mode 100644 index 00000000..0cd10d5b --- /dev/null +++ b/log/log4j/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + + cn.cunchang + log4j + 1.0-SNAPSHOT + + + + log4j + log4j + 1.2.17 + + + + junit + junit + 4.12 + + + + mysql + mysql-connector-java + 8.0.21 + + + \ No newline at end of file diff --git a/log/log4j/src/main/java/cn/cunchang/Log4jTest.java b/log/log4j/src/main/java/cn/cunchang/Log4jTest.java new file mode 100644 index 00000000..1af1f2f4 --- /dev/null +++ b/log/log4j/src/main/java/cn/cunchang/Log4jTest.java @@ -0,0 +1,170 @@ +package cn.cunchang; + + +import org.apache.log4j.BasicConfigurator; +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; +import org.apache.log4j.helpers.Loader; +import org.apache.log4j.helpers.LogLog; +import org.junit.Test; + + +/** + * @author cunchang + */ +public class Log4jTest { + + /** + * 日志级别 + * fatal 指出每个严重的错误事件将会导致应用程序的退出。 + * error 指出虽然发生错误事件,但仍然不影响系统的继续运行。 + * warn 表明会出现潜在的错误情形。 + * info 一般和在粗粒度级别上,强调应用程序的运行全程。 + * debug 一般用于细粒度级别上,对调试应用程序非常有帮助。 + * trace 是程序追踪,可以用于输出程序运行中的变量,显示执行的流程。 + *

+ * 一般只使用4个级别,优先级从高到低为 ERROR > WARN > INFO > DEBUG + */ + @Test + public void testQuick() { + // 初始化系统配置,不需要配置文件 + BasicConfigurator.configure(); + // 创建日志记录器对象 + Logger logger = Logger.getLogger(this.getClass()); + // 日志记录输出 + logger.info("hello log4j"); + + // 日志级别 + logger.fatal("fatal");// 严重错误,一般会造成系统崩溃和终止运行 + logger.error("error");// 错误信息,但不会影响系统运行 + logger.warn("warn");// 警告信息,可能会发生问题 + logger.info("info");// 程序运行信息,数据库的连接、网络、IO操作等 + logger.debug("debug");// 调试信息,一般在开发阶段使用,记录程序的变量、参数 + logger.trace("trace");// 追踪信息,记录程序的所有流程信 + } + + /** + * 熟悉log4j组件和配置文件 + */ + @Test + public void test组件和配置文件() { + PropertyConfigurator.configure(Loader.getResource("log4j_组件和配置文件.properties")); + Logger logger = Logger.getLogger(this.getClass()); + + // 日志级别 + logger.fatal("fatal"); + logger.error("error"); + logger.warn("warn"); + logger.info("info"); + logger.debug("debug"); + logger.trace("trace"); + } + + + /** + * log4j内部日志 LogLog + */ + @Test + public void test内部日志() { + // 开启内部日志 + LogLog.setInternalDebugging(true); + + PropertyConfigurator.configure(Loader.getResource("log4j_组件和配置文件.properties")); + Logger logger = Logger.getLogger(this.getClass()); + + logger.fatal("fatal"); + logger.error("error"); + logger.warn("warn"); + logger.info("info"); + logger.debug("debug"); + logger.trace("trace"); + } + + /** + * log4j Layout配置 + */ + @Test + public void testLayout配置() { + // 开启内部日志 + LogLog.setInternalDebugging(true); + PropertyConfigurator.configure(Loader.getResource("log4j_Layout配置.properties")); + Logger logger = Logger.getLogger(this.getClass()); + + logger.fatal("fatal"); + logger.error("error"); + logger.warn("warn"); + logger.info("info"); + logger.debug("debug"); + logger.trace("trace"); + } + + /** + * log4j FileAppender配置 + */ + @Test + public void testFileAppender配置() { + // 开启内部日志 + LogLog.setInternalDebugging(true); + PropertyConfigurator.configure(Loader.getResource("log4j_FileAppender配置.properties")); + Logger logger = Logger.getLogger(this.getClass()); + + for (int i = 0; i < 100; i++) { + logger.fatal("fatal"); + logger.error("error"); + logger.warn("warn"); + logger.info("info"); + logger.debug("debug"); + logger.trace("trace"); + } + } + + + /** + * log4j JDBCAppender配置 + */ + @Test + public void testJDBCAppender配置() { + // 开启内部日志 + LogLog.setInternalDebugging(true); + PropertyConfigurator.configure(Loader.getResource("log4j_JDBCAppender配置.properties")); + Logger logger = Logger.getLogger(this.getClass()); + + for (int i = 0; i < 100; i++) { + logger.fatal("fatal"); + logger.error("error"); + logger.warn("warn"); + logger.info("info"); + logger.debug("debug"); + logger.trace("trace"); + } + } + + + /** + * 自定义Logger是为了,不同业务日志输出到不同位置
+ * 比如业务代码输出到文件,log4j日志输出到控制台 + */ + @Test + public void testCustomLogger() { + // 开启内部日志 + LogLog.setInternalDebugging(true); + PropertyConfigurator.configure(Loader.getResource("log4j_自定义Logger.properties")); + // 自定义 cn.cunchang + Logger myLogger = Logger.getLogger(this.getClass()); + myLogger.fatal("myLogger fatal"); + myLogger.error("myLogger error"); + myLogger.warn("myLogger warn"); + myLogger.info("myLogger info"); + myLogger.debug("myLogger debug"); + myLogger.trace("myLogger trace"); + // 自定义 org.apache + Logger rootLogger = Logger.getLogger(Logger.class); + rootLogger.fatal("rootLogger fatal"); + rootLogger.error("rootLogger error"); + rootLogger.warn("rootLogger warn"); + rootLogger.info("rootLogger info"); + rootLogger.debug("rootLogger debug"); + rootLogger.trace("rootLogger trace"); + } + +} diff --git a/log/log4j/src/main/resources/log.sql b/log/log4j/src/main/resources/log.sql new file mode 100644 index 00000000..629df2f8 --- /dev/null +++ b/log/log4j/src/main/resources/log.sql @@ -0,0 +1,17 @@ +use xxx_project_db; + +CREATE TABLE `log` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `project_name` VARCHAR(255) DEFAULT NULL COMMENT '目项名', + `create_date` VARCHAR(255) DEFAULT NULL COMMENT '创建时间', + `level` VARCHAR(255) DEFAULT NULL COMMENT '优先级', + `category` VARCHAR(255) DEFAULT NULL COMMENT '所在类的全名', + `file_name` VARCHAR(255) DEFAULT NULL COMMENT '输出日志消息产生时所在的文件名称 ', + `thread_name` VARCHAR(255) DEFAULT NULL COMMENT '日志事件的线程名', + `line` VARCHAR(255) DEFAULT NULL COMMENT '号行', + `all_category` VARCHAR(255) DEFAULT NULL COMMENT '日志事件的发生位置', + `message` VARCHAR(4000) DEFAULT NULL COMMENT '输出代码中指定的消息', + PRIMARY KEY (`id`) +); + + diff --git a/log/log4j/src/main/resources/log4j/log4j.properties b/log/log4j/src/main/resources/log4j/log4j.properties new file mode 100644 index 00000000..9237fb3b --- /dev/null +++ b/log/log4j/src/main/resources/log4j/log4j.properties @@ -0,0 +1,79 @@ +# 指定 RootLogger 顶级父元素默认配置信息 +# 指定日志级别=trace,使用的 apeender 为=console +log4j.rootLogger = trace,console + +# 自定义 logger 对象设置 +log4j.logger.cn.cunchang = info,console +log4j.logger.org.apache = error + +# 指定控制台日志输出的 appender +log4j.appender.console = org.apache.log4j.ConsoleAppender +# 指定消息格式 layout +log4j.appender.console.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.console.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n + + +# %m 输出代码中指定的日志信息 +# %p 输出优先级,及 DEBUG、INFO 等 +# %n 换行符(Windows平台的换行符为 "\n",Unix 平台为 "\n") +# %r 输出自应用启动到输出该 log 信息耗费的毫秒数 +# %c 输出打印语句所属的类的全名 +# %t 输出产生该日志的线程全名 +# %d 输出服务器当前时间,默认为 ISO8601,也可以指定格式,如:%d{yyyy年MM月dd日 HH:mm:ss} +# %l 输出日志时间发生的位置,包括类名、线程、及在代码中的行数。如:Test.main(Test.java:10) +# %F 输出日志消息产生时所在的文件名称 +# %L 输出代码中的行号 +# %% 输出一个 "%" 字符 + +# 日志文件输出的 appender 对象 +log4j.appender.file = org.apache.log4j.FileAppender +# 指定消息格式 layout +log4j.appender.file.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.file.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n +# 指定日志文件保存路径 +log4j.appender.file.file = /Users/cunchang/logs/log4j.log +# 指定日志文件的字符集 +log4j.appender.file.encoding = UTF-8 + + +# 按照文件大小拆分的 appender 对象 +# 日志文件输出的 appender 对象 +log4j.appender.rollingFile = org.apache.log4j.RollingFileAppender +# 指定消息格式 layout +log4j.appender.rollingFile.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.rollingFile.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n +# 指定日志文件保存路径 +log4j.appender.rollingFile.file = /Users/cunchang/logs/log4j.log +# 指定日志文件的字符集 +log4j.appender.rollingFile.encoding = UTF-8 +# 指定日志文件内容的大小 +log4j.appender.rollingFile.maxFileSize = 1MB +# 指定日志文件的数量 +log4j.appender.rollingFile.maxBackupIndex = 10 + + +# 按照时间规则拆分的 appender 对象 +log4j.appender.dailyFile = org.apache.log4j.DailyRollingFileAppender +# 指定消息格式 layout +log4j.appender.dailyFile.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.dailyFile.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n +# 指定日志文件保存路径 +log4j.appender.dailyFile.file = /Users/cunchang/logs/log4j.log +# 指定日志文件的字符集 +log4j.appender.dailyFile.encoding = UTF-8 +# 指定日期拆分规则 +log4j.appender.dailyFile.datePattern = '.'yyyy-MM-dd-HH-mm-ss + + +#mysql +log4j.appender.logDB=org.apache.log4j.jdbc.JDBCAppender +log4j.appender.logDB.layout=org.apache.log4j.PatternLayout +log4j.appender.logDB.Driver=com.mysql.jdbc.Driver +log4j.appender.logDB.URL=jdbc:mysql://localhost:3306/xxx_project_db +log4j.appender.logDB.User=root +log4j.appender.logDB.Password=123456 +log4j.appender.logDB.Sql=INSERT INTO log(project_name,create_date,level,category,file_name,thread_name,line,all_category,message) values('shop','%d{yyyy-MM-dd HH:mm:ss}','%p','%c','%F','%t','%L','%l','%m') \ No newline at end of file diff --git "a/log/log4j/src/main/resources/log4j_FileAppender\351\205\215\347\275\256.properties" "b/log/log4j/src/main/resources/log4j_FileAppender\351\205\215\347\275\256.properties" new file mode 100644 index 00000000..00e0891c --- /dev/null +++ "b/log/log4j/src/main/resources/log4j_FileAppender\351\205\215\347\275\256.properties" @@ -0,0 +1,64 @@ +# 指定 RootLogger 顶级父元素默认配置信息 +# 指定日志级别=trace,使用的 appender= +log4j.rootLogger = trace,dailyFile + +# 指定控制台日志输出的 appender +log4j.appender.console = org.apache.log4j.ConsoleAppender +# 指定消息格式 layout +log4j.appender.console.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.console.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n + +# %m 输出代码中指定的日志信息 +# %p 输出优先级,及 DEBUG、INFO 等 +# %n 换行符(Windows平台的换行符为 "\n",Unix 平台为 "\n") +# %r 输出自应用启动到输出该 log 信息耗费的毫秒数 +# %c 输出打印语句所属的类的全名 +# %t 输出产生该日志的线程全名 +# %d 输出服务器当前时间,默认为 ISO8601,也可以指定格式,如:%d{yyyy年MM月dd日mm毫秒 HH:mm:ss.SSS} +# %l 输出日志时间发生的位置,包括类名、线程、及在代码中的行数。如:Test.main(Test.java:10) +# %F 输出日志消息产生时所在的文件名称 +# %L 输出代码中的行号 +# %% 输出一个 "%" 字符 + + +# 日志文件输出的 appender 对象 +log4j.appender.file = org.apache.log4j.FileAppender +# 指定消息格式 layout +log4j.appender.file.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.file.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n +# 指定日志文件保存路径 +log4j.appender.file.file = /Users/cunchang/logs/log4j.log +# 指定日志文件的字符集 +log4j.appender.file.encoding = UTF-8 + +# 按照文件大小拆分的 appender 对象 +# 日志文件输出的 appender 对象 +log4j.appender.rollingFile = org.apache.log4j.RollingFileAppender +# 指定消息格式 layout +log4j.appender.rollingFile.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.rollingFile.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n +# 指定日志文件保存路径 +log4j.appender.rollingFile.file = /Users/cunchang/logs/log4j.log +# 指定日志文件的字符集 +log4j.appender.rollingFile.encoding = UTF-8 +# 指定日志文件内容的大小 +log4j.appender.rollingFile.maxFileSize = 1KB +# 指定日志文件的数量,现象超过1KB生成一个新日志文件 +log4j.appender.rollingFile.maxBackupIndex = 10 + + +# 按照时间规则拆分的 appender 对象 +log4j.appender.dailyFile = org.apache.log4j.DailyRollingFileAppender +# 指定消息格式 layout +log4j.appender.dailyFile.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.dailyFile.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n +# 指定日志文件保存路径 +log4j.appender.dailyFile.file = /Users/cunchang/logs/log4j.log +# 指定日志文件的字符集 +log4j.appender.dailyFile.encoding = UTF-8 +# 指定日期拆分规则,现象按照秒生成一个新日志文件 +log4j.appender.dailyFile.datePattern = '.'yyyy-MM-dd-HH-mm-ss diff --git "a/log/log4j/src/main/resources/log4j_JDBCAppender\351\205\215\347\275\256.properties" "b/log/log4j/src/main/resources/log4j_JDBCAppender\351\205\215\347\275\256.properties" new file mode 100644 index 00000000..06c08cae --- /dev/null +++ "b/log/log4j/src/main/resources/log4j_JDBCAppender\351\205\215\347\275\256.properties" @@ -0,0 +1,72 @@ +# 指定 RootLogger 顶级父元素默认配置信息 +# 指定日志级别=trace,使用的 appender= +log4j.rootLogger = trace,logDB + +# 指定控制台日志输出的 appender +log4j.appender.console = org.apache.log4j.ConsoleAppender +# 指定消息格式 layout +log4j.appender.console.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.console.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n + +# %m 输出代码中指定的日志信息 +# %p 输出优先级,及 DEBUG、INFO 等 +# %n 换行符(Windows平台的换行符为 "\n",Unix 平台为 "\n") +# %r 输出自应用启动到输出该 log 信息耗费的毫秒数 +# %c 输出打印语句所属的类的全名 +# %t 输出产生该日志的线程全名 +# %d 输出服务器当前时间,默认为 ISO8601,也可以指定格式,如:%d{yyyy年MM月dd日mm毫秒 HH:mm:ss.SSS} +# %l 输出日志时间发生的位置,包括类名、线程、及在代码中的行数。如:Test.main(Test.java:10) +# %F 输出日志消息产生时所在的文件名称 +# %L 输出代码中的行号 +# %% 输出一个 "%" 字符 + + +# 日志文件输出的 appender 对象 +log4j.appender.file = org.apache.log4j.FileAppender +# 指定消息格式 layout +log4j.appender.file.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.file.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n +# 指定日志文件保存路径 +log4j.appender.file.file = /Users/cunchang/logs/log4j.log +# 指定日志文件的字符集 +log4j.appender.file.encoding = UTF-8 + +# 按照文件大小拆分的 appender 对象 +# 日志文件输出的 appender 对象 +log4j.appender.rollingFile = org.apache.log4j.RollingFileAppender +# 指定消息格式 layout +log4j.appender.rollingFile.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.rollingFile.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n +# 指定日志文件保存路径 +log4j.appender.rollingFile.file = /Users/cunchang/logs/log4j.log +# 指定日志文件的字符集 +log4j.appender.rollingFile.encoding = UTF-8 +# 指定日志文件内容的大小 +log4j.appender.rollingFile.maxFileSize = 1KB +# 指定日志文件的数量,现象超过1KB生成一个新日志文件 +log4j.appender.rollingFile.maxBackupIndex = 10 + +# 按照时间规则拆分的 appender 对象 +log4j.appender.dailyFile = org.apache.log4j.DailyRollingFileAppender +# 指定消息格式 layout +log4j.appender.dailyFile.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.dailyFile.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n +# 指定日志文件保存路径 +log4j.appender.dailyFile.file = /Users/cunchang/logs/log4j.log +# 指定日志文件的字符集 +log4j.appender.dailyFile.encoding = UTF-8 +# 指定日期拆分规则,现象按照秒生成一个新日志文件 +log4j.appender.dailyFile.datePattern = '.'yyyy-MM-dd-HH-mm-ss + +#mysql +log4j.appender.logDB=org.apache.log4j.jdbc.JDBCAppender +log4j.appender.logDB.layout=org.apache.log4j.PatternLayout +log4j.appender.logDB.Driver=com.mysql.jdbc.Driver +log4j.appender.logDB.URL=jdbc:mysql://localhost:3306/xxx_project_db +log4j.appender.logDB.User=root +log4j.appender.logDB.Password=123456 +log4j.appender.logDB.Sql=INSERT INTO log(project_name,create_date,level,category,file_name,thread_name,line,all_category,message) values('shop','%d{yyyy-MM-dd HH:mm:ss}','%p','%c','%F','%t','%L','%l','%m') \ No newline at end of file diff --git "a/log/log4j/src/main/resources/log4j_Layout\351\205\215\347\275\256.properties" "b/log/log4j/src/main/resources/log4j_Layout\351\205\215\347\275\256.properties" new file mode 100644 index 00000000..ca84b449 --- /dev/null +++ "b/log/log4j/src/main/resources/log4j_Layout\351\205\215\347\275\256.properties" @@ -0,0 +1,23 @@ +# 指定 RootLogger 顶级父元素默认配置信息 +# 指定日志级别=trace,使用的 apeender 为=console +log4j.rootLogger = trace,console + +# 指定控制台日志输出的 appender +log4j.appender.console = org.apache.log4j.ConsoleAppender +# 指定消息格式 layout +log4j.appender.console.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.console.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n + +# %m 输出代码中指定的日志信息 +# %p 输出优先级,及 DEBUG、INFO 等 +# %n 换行符(Windows平台的换行符为 "\n",Unix 平台为 "\n") +# %r 输出自应用启动到输出该 log 信息耗费的毫秒数 +# %c 输出打印语句所属的类的全名 +# %t 输出产生该日志的线程全名 +# %d 输出服务器当前时间,默认为 ISO8601,也可以指定格式,如:%d{yyyy年MM月dd日 HH:mm:ss} +# %l 输出日志时间发生的位置,包括类名、线程、及在代码中的行数。如:Test.main(Test.java:10) +# %F 输出日志消息产生时所在的文件名称 +# %L 输出代码中的行号 +# %% 输出一个 "%" 字符 + diff --git "a/log/log4j/src/main/resources/log4j_\347\273\204\344\273\266\345\222\214\351\205\215\347\275\256\346\226\207\344\273\266.properties" "b/log/log4j/src/main/resources/log4j_\347\273\204\344\273\266\345\222\214\351\205\215\347\275\256\346\226\207\344\273\266.properties" new file mode 100644 index 00000000..bbdd578c --- /dev/null +++ "b/log/log4j/src/main/resources/log4j_\347\273\204\344\273\266\345\222\214\351\205\215\347\275\256\346\226\207\344\273\266.properties" @@ -0,0 +1,9 @@ +# 指定 RootLogger 顶级父元素默认配置信息 +# 指定日志级别=trace,使用的 apeender 为=console +log4j.rootLogger = trace,console + +# 指定控制台日志输出的 appender +log4j.appender.console = org.apache.log4j.ConsoleAppender +# 指定消息格式 layout +log4j.appender.console.layout = org.apache.log4j.SimpleLayout + diff --git "a/log/log4j/src/main/resources/log4j_\350\207\252\345\256\232\344\271\211Logger.properties" "b/log/log4j/src/main/resources/log4j_\350\207\252\345\256\232\344\271\211Logger.properties" new file mode 100644 index 00000000..4e18c1d3 --- /dev/null +++ "b/log/log4j/src/main/resources/log4j_\350\207\252\345\256\232\344\271\211Logger.properties" @@ -0,0 +1,78 @@ +# 指定 RootLogger 顶级父元素默认配置信息 +# 指定日志级别=trace,使用的 appender=console +log4j.rootLogger = trace,console + +# 自定义 logger 对象设置,会继承rootLogger的日志级别(覆盖)和appender(追加) +# 指定日志级别=info,使用的 appender=file +log4j.logger.cn.cunchang = info,file +log4j.logger.org.apache = error + + +# 指定控制台日志输出的 appender +log4j.appender.console = org.apache.log4j.ConsoleAppender +# 指定消息格式 layout +log4j.appender.console.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.console.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n + +# %m 输出代码中指定的日志信息 +# %p 输出优先级,及 DEBUG、INFO 等 +# %n 换行符(Windows平台的换行符为 "\n",Unix 平台为 "\n") +# %r 输出自应用启动到输出该 log 信息耗费的毫秒数 +# %c 输出打印语句所属的类的全名 +# %t 输出产生该日志的线程全名 +# %d 输出服务器当前时间,默认为 ISO8601,也可以指定格式,如:%d{yyyy年MM月dd日mm毫秒 HH:mm:ss.SSS} +# %l 输出日志时间发生的位置,包括类名、线程、及在代码中的行数。如:Test.main(Test.java:10) +# %F 输出日志消息产生时所在的文件名称 +# %L 输出代码中的行号 +# %% 输出一个 "%" 字符 + + +# 日志文件输出的 appender 对象 +log4j.appender.file = org.apache.log4j.FileAppender +# 指定消息格式 layout +log4j.appender.file.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.file.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n +# 指定日志文件保存路径 +log4j.appender.file.file = /Users/cunchang/logs/log4j.log +# 指定日志文件的字符集 +log4j.appender.file.encoding = UTF-8 + +# 按照文件大小拆分的 appender 对象 +# 日志文件输出的 appender 对象 +log4j.appender.rollingFile = org.apache.log4j.RollingFileAppender +# 指定消息格式 layout +log4j.appender.rollingFile.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.rollingFile.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n +# 指定日志文件保存路径 +log4j.appender.rollingFile.file = /Users/cunchang/logs/log4j.log +# 指定日志文件的字符集 +log4j.appender.rollingFile.encoding = UTF-8 +# 指定日志文件内容的大小 +log4j.appender.rollingFile.maxFileSize = 1KB +# 指定日志文件的数量,现象超过1KB生成一个新日志文件 +log4j.appender.rollingFile.maxBackupIndex = 10 + +# 按照时间规则拆分的 appender 对象 +log4j.appender.dailyFile = org.apache.log4j.DailyRollingFileAppender +# 指定消息格式 layout +log4j.appender.dailyFile.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.dailyFile.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n +# 指定日志文件保存路径 +log4j.appender.dailyFile.file = /Users/cunchang/logs/log4j.log +# 指定日志文件的字符集 +log4j.appender.dailyFile.encoding = UTF-8 +# 指定日期拆分规则,现象按照秒生成一个新日志文件 +log4j.appender.dailyFile.datePattern = '.'yyyy-MM-dd-HH-mm-ss + +#mysql +log4j.appender.logDB=org.apache.log4j.jdbc.JDBCAppender +log4j.appender.logDB.layout=org.apache.log4j.PatternLayout +log4j.appender.logDB.Driver=com.mysql.jdbc.Driver +log4j.appender.logDB.URL=jdbc:mysql://localhost:3306/xxx_project_db +log4j.appender.logDB.User=root +log4j.appender.logDB.Password=123456 +log4j.appender.logDB.Sql=INSERT INTO log(project_name,create_date,level,category,file_name,thread_name,line,all_category,message) values('shop','%d{yyyy-MM-dd HH:mm:ss}','%p','%c','%F','%t','%L','%l','%m') \ No newline at end of file diff --git a/log/log4j2/pom.xml b/log/log4j2/pom.xml new file mode 100644 index 00000000..0ae7422a --- /dev/null +++ b/log/log4j2/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + cn.cunchang + log4j2 + 1.0-SNAPSHOT + + + + + org.slf4j + slf4j-api + 1.7.26 + + + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.9.1 + + + + + org.apache.logging.log4j + log4j-api + 2.11.1 + + + + org.apache.logging.log4j + log4j-core + 2.11.1 + + + + + com.lmax + disruptor + 3.3.4 + + + + + junit + junit + 4.12 + + + \ No newline at end of file diff --git a/log/log4j2/src/main/java/cn/cunchang/Log4j2Test.java b/log/log4j2/src/main/java/cn/cunchang/Log4j2Test.java new file mode 100644 index 00000000..81add656 --- /dev/null +++ b/log/log4j2/src/main/java/cn/cunchang/Log4j2Test.java @@ -0,0 +1,27 @@ +package cn.cunchang; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.Test; + +public class Log4j2Test { + + // 定义日志记录器对象 + public static final Logger log = LogManager.getLogger(Log4j2Test.class); + + /** + * log4j-api 门面 + * log4j-core 实现 + */ + @Test + public void testQuick() { + // 日志消息输出 + log.fatal("fatal"); + log.error("error"); + log.warn("warn"); + log.info("inf"); + log.debug("debug"); + log.trace("trace"); + } + +} diff --git a/log/log4j2/src/main/java/cn/cunchang/Slf4jTest.java b/log/log4j2/src/main/java/cn/cunchang/Slf4jTest.java new file mode 100644 index 00000000..7c3cd86e --- /dev/null +++ b/log/log4j2/src/main/java/cn/cunchang/Slf4jTest.java @@ -0,0 +1,25 @@ +package cn.cunchang; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Slf4jTest { + + public static final Logger log = LoggerFactory.getLogger(Slf4jTest.class); + + /** + * slf4j-api 门面 + * log4j-slf4j-impl 适配器 + * log4j-core 实现 + */ + @Test + public void test日志门面() { + // 日志输出 + log.error("error"); + log.warn("wring"); + log.info("info"); // 默认级别 + log.debug("debug"); + log.trace("trace"); + } +} diff --git a/log/log4j2/src/main/resources/AsyncAppender/log4j2.xml b/log/log4j2/src/main/resources/AsyncAppender/log4j2.xml new file mode 100644 index 00000000..743d75d8 --- /dev/null +++ b/log/log4j2/src/main/resources/AsyncAppender/log4j2.xml @@ -0,0 +1,69 @@ + + + + + + + /Users/cunchang/logs/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git "a/log/log4j2/src/main/resources/AsyncLogger\345\205\250\345\261\200/log4j2.component.properties" "b/log/log4j2/src/main/resources/AsyncLogger\345\205\250\345\261\200/log4j2.component.properties" new file mode 100644 index 00000000..36ce3003 --- /dev/null +++ "b/log/log4j2/src/main/resources/AsyncLogger\345\205\250\345\261\200/log4j2.component.properties" @@ -0,0 +1,2 @@ +# 全局异步 +Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector \ No newline at end of file diff --git "a/log/log4j2/src/main/resources/AsyncLogger\345\205\250\345\261\200/log4j2.xml" "b/log/log4j2/src/main/resources/AsyncLogger\345\205\250\345\261\200/log4j2.xml" new file mode 100644 index 00000000..8deb2c1f --- /dev/null +++ "b/log/log4j2/src/main/resources/AsyncLogger\345\205\250\345\261\200/log4j2.xml" @@ -0,0 +1,62 @@ + + + + + + + /Users/cunchang/logs/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git "a/log/log4j2/src/main/resources/AsyncLogger\346\267\267\345\220\210/log4j2.xml" "b/log/log4j2/src/main/resources/AsyncLogger\346\267\267\345\220\210/log4j2.xml" new file mode 100644 index 00000000..493a7152 --- /dev/null +++ "b/log/log4j2/src/main/resources/AsyncLogger\346\267\267\345\220\210/log4j2.xml" @@ -0,0 +1,71 @@ + + + + + + + /Users/cunchang/logs/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/log/log4j2/src/main/resources/log4j2.xml b/log/log4j2/src/main/resources/log4j2.xml new file mode 100644 index 00000000..493a7152 --- /dev/null +++ b/log/log4j2/src/main/resources/log4j2.xml @@ -0,0 +1,71 @@ + + + + + + + /Users/cunchang/logs/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/log/logback/pom.xml b/log/logback/pom.xml new file mode 100644 index 00000000..a040d86d --- /dev/null +++ b/log/logback/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + cn.cunchang + logback + 1.0-SNAPSHOT + + + + org.slf4j + slf4j-api + 1.7.26 + + + + ch.qos.logback + logback-classic + 1.2.3 + + + + junit + junit + 4.13 + + + + \ No newline at end of file diff --git a/log/logback/src/main/java/cn/cunchang/LogbackTest.java b/log/logback/src/main/java/cn/cunchang/LogbackTest.java new file mode 100644 index 00000000..016b7846 --- /dev/null +++ b/log/logback/src/main/java/cn/cunchang/LogbackTest.java @@ -0,0 +1,107 @@ +package cn.cunchang; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.util.StatusPrinter; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.InputStream; + +public class LogbackTest { + + public static final Logger log = LoggerFactory.getLogger(LogbackTest.class); + + @Test + public void testQuick() { + log.error("error"); + log.warn("wring"); + log.info("info"); + log.debug("debug");// 默认级别 + log.trace("trace"); + } + + /** + * logback自动加载配置文件的优先级如下: + * 1.classpath下的logback-test.xml + * 2.classpath下的logback.groovy + * 3.classpath下的logback.xml + * 4.META-INF/services/ch.qos.logback.classic.spi.Configurator中的 logback 配置实现类 + * 5.logback自带的默认配置文件BasicConfigurator + */ + @Test + public void test配置文件() { + reloadConfig("logback_配置文件.xml"); + log.error("error"); + log.warn("wring"); + log.info("info"); + log.debug("debug"); + log.trace("trace"); + } + + @Test + public void testAppender配置() { +// reloadConfig("logback_FileAppender配置.xml"); + reloadConfig("logback_HtmlAppender配置.xml"); + log.error("error"); + log.warn("wring"); + log.info("info"); + log.debug("debug"); + log.trace("trace"); + } + + @Test + public void testRollingFileAppender配置() { + reloadConfig("logback_RollingFileAppender配置.xml"); + for (int i = 0; i < 100; i++) { + log.error("error"); + log.warn("wring"); + log.info("info"); + log.debug("debug"); + log.trace("trace"); + } + } + + @Test + public void test异步配置() { + reloadConfig("logback_异步配置.xml"); + for (int i = 0; i < 100; i++) { + log.error("error"); + log.warn("wring"); + log.info("info"); + log.debug("debug"); + log.trace("trace"); + } + } + + @Test + public void test自定义logger() { + reloadConfig("logback_自定义logger.xml"); + log.error("error"); + log.warn("wring"); + log.info("info"); + log.debug("debug"); + log.trace("trace"); + } + + /** + * 加载自定义logback配置文件 + * + * @param logbackConfigPath + */ + public void reloadConfig(String logbackConfigPath) { + LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); + + InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(logbackConfigPath); + JoranConfigurator joranConfigurator = new JoranConfigurator(); + joranConfigurator.setContext(loggerContext); + loggerContext.reset(); + try { + joranConfigurator.doConfigure(inputStream); + } catch (Exception e) { + log.error("logbackConfigPath Load logback config file error. Message: {}", e.getMessage()); + } + StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext); + } +} diff --git a/log/logback/src/main/java/cn/cunchang/logback.xml b/log/logback/src/main/java/cn/cunchang/logback.xml new file mode 100644 index 00000000..bb729b31 --- /dev/null +++ b/log/logback/src/main/java/cn/cunchang/logback.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + System.err + + + ${pattern} + + + + + + + ${log_dir}/logback.log + + + ${pattern} + + + + + + + ${log_dir}/logback.html + + + + %-5level%d{yyyy-MM-dd HH:mm:ss.SSS}%c%M%L%thread%m + + + + + + + + + ${log_dir}/roll_logback.log + + + ${pattern} + + + + + ${log_dir}/rolling.%d{yyyy-MM-dd}.log%i.gz + + 1MB + + + + + ERROR + ACCEPT + DENY + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git "a/log/logback/src/main/resources/logback_FileAppender\351\205\215\347\275\256.xml" "b/log/logback/src/main/resources/logback_FileAppender\351\205\215\347\275\256.xml" new file mode 100644 index 00000000..9c14c7e3 --- /dev/null +++ "b/log/logback/src/main/resources/logback_FileAppender\351\205\215\347\275\256.xml" @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + System.err + + + ${pattern} + + + + + + + ${log_dir}/logback.log + + + ${pattern} + + + + + + + + + + \ No newline at end of file diff --git "a/log/logback/src/main/resources/logback_HtmlAppender\351\205\215\347\275\256.xml" "b/log/logback/src/main/resources/logback_HtmlAppender\351\205\215\347\275\256.xml" new file mode 100644 index 00000000..ea130174 --- /dev/null +++ "b/log/logback/src/main/resources/logback_HtmlAppender\351\205\215\347\275\256.xml" @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + System.err + + + ${pattern} + + + + + + + ${log_dir}/logback.log + + + ${pattern} + + + + + + + ${log_dir}/logback.html + + + + %-5level%d{yyyy-MM-dd HH:mm:ss.SSS}%c%M%L%thread%m + + + + + + + + + + + + \ No newline at end of file diff --git "a/log/logback/src/main/resources/logback_RollingFileAppender\351\205\215\347\275\256.xml" "b/log/logback/src/main/resources/logback_RollingFileAppender\351\205\215\347\275\256.xml" new file mode 100644 index 00000000..8541e05b --- /dev/null +++ "b/log/logback/src/main/resources/logback_RollingFileAppender\351\205\215\347\275\256.xml" @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + System.err + + + ${pattern} + + + + + + + ${log_dir}/roll_logback.log + + + ${pattern} + + + + + ${log_dir}/rolling.%d{yyyy-MM-dd}.log%i.gz + + 1KB + + + + + ERROR + + ACCEPT + + DENY + + + + + + + + + + + \ No newline at end of file diff --git "a/log/logback/src/main/resources/logback_\345\274\202\346\255\245\351\205\215\347\275\256.xml" "b/log/logback/src/main/resources/logback_\345\274\202\346\255\245\351\205\215\347\275\256.xml" new file mode 100644 index 00000000..026a3b1f --- /dev/null +++ "b/log/logback/src/main/resources/logback_\345\274\202\346\255\245\351\205\215\347\275\256.xml" @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + System.err + + + ${pattern} + + + + + + + ${log_dir}/roll_logback.log + + + ${pattern} + + + + + ${log_dir}/rolling.%d{yyyy-MM-dd}.log%i.gz + + 1KB + + + + + ERROR + + ACCEPT + + DENY + + + + + + + + + + + + + + + + \ No newline at end of file diff --git "a/log/logback/src/main/resources/logback_\350\207\252\345\256\232\344\271\211logger.xml" "b/log/logback/src/main/resources/logback_\350\207\252\345\256\232\344\271\211logger.xml" new file mode 100644 index 00000000..8e69e606 --- /dev/null +++ "b/log/logback/src/main/resources/logback_\350\207\252\345\256\232\344\271\211logger.xml" @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + System.err + + + ${pattern} + + + + + + + + \ No newline at end of file diff --git "a/log/logback/src/main/resources/logback_\351\205\215\347\275\256\346\226\207\344\273\266.xml" "b/log/logback/src/main/resources/logback_\351\205\215\347\275\256\346\226\207\344\273\266.xml" new file mode 100644 index 00000000..920d0c29 --- /dev/null +++ "b/log/logback/src/main/resources/logback_\351\205\215\347\275\256\346\226\207\344\273\266.xml" @@ -0,0 +1,37 @@ + + + + + + + + + + + System.err + + + ${pattern} + + + + + + + + + \ No newline at end of file diff --git a/log/slf4j/pom.xml b/log/slf4j/pom.xml new file mode 100644 index 00000000..7f99bc0e --- /dev/null +++ b/log/slf4j/pom.xml @@ -0,0 +1,81 @@ + + + 4.0.0 + + cn.cunchang + slf4j + 1.0-SNAPSHOT + + + + + + org.slf4j + slf4j-api + 1.7.27 + + + + + + + ch.qos.logback + logback-classic + 1.2.3 + + + + + + org.slf4j + log4j-over-slf4j + 1.7.25 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + junit + junit + 4.13 + + + + \ No newline at end of file diff --git a/log/slf4j/src/main/java/cn/cunchang/Log4jTest.java b/log/slf4j/src/main/java/cn/cunchang/Log4jTest.java new file mode 100644 index 00000000..f85201f8 --- /dev/null +++ b/log/slf4j/src/main/java/cn/cunchang/Log4jTest.java @@ -0,0 +1,22 @@ +package cn.cunchang; + +import org.apache.log4j.Logger; +import org.junit.Test; + +public class Log4jTest { + + // 定义 log4j 日志记录器 + public static final Logger LOGGER = Logger.getLogger(Log4jTest.class); + + /** + * 桥接器
+ * logback替换log4j,代码不需要修改 + * + * + */ + @Test + public void test桥接器() { + LOGGER.info("hello lgo4j"); + } + +} diff --git a/log/slf4j/src/main/java/cn/cunchang/Slf4jTest.java b/log/slf4j/src/main/java/cn/cunchang/Slf4jTest.java new file mode 100644 index 00000000..7458e505 --- /dev/null +++ b/log/slf4j/src/main/java/cn/cunchang/Slf4jTest.java @@ -0,0 +1,40 @@ +package cn.cunchang; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Slf4jTest { + + public static final Logger log = LoggerFactory.getLogger(Slf4jTest.class); + + /** + * http://slf4j.org/manual.html + * 适配器
+ * slf4j-simple、logback、nop、log4j、jul + * + */ + @Test + public void test日志门面() { + // 日志输出 + log.error("error"); + log.warn("wring"); + log.info("info"); // 默认级别 + log.debug("debug"); + log.trace("trace"); + + // 使用占位符输出日志信息 + String name = "寸长"; + Integer age = 18; + log.info("用户:{},{}",name,age); + + // 将系统的异常信息输出 + try { + int i = 1/0; + } catch (Exception e) { + // e.printStackTrace(); + log.error("出现异常:",e); + + } + } +} diff --git a/log/slf4j/src/main/resources/log4j.properties b/log/slf4j/src/main/resources/log4j.properties new file mode 100644 index 00000000..cd822732 --- /dev/null +++ b/log/slf4j/src/main/resources/log4j.properties @@ -0,0 +1,10 @@ +# 指定 RootLogger 顶级父元素默认配置信息 +# 指定日志级别=trace,使用的 apeender 为=console +log4j.rootLogger = trace,console + +# 指定控制台日志输出的 appender +log4j.appender.console = org.apache.log4j.ConsoleAppender +# 指定消息格式 layout +log4j.appender.console.layout = org.apache.log4j.PatternLayout +# 指定消息格式的内容 +log4j.appender.console.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n diff --git a/log/springboot-log/pom.xml b/log/springboot-log/pom.xml new file mode 100644 index 00000000..7b35ca05 --- /dev/null +++ b/log/springboot-log/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.4.1 + + + cn.cunchang + springboot-log + 0.0.1-SNAPSHOT + springboot-log + Demo project for Spring Boot + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/log/springboot-log/src/main/java/cn/cunchang/SpringbootLogApplication.java b/log/springboot-log/src/main/java/cn/cunchang/SpringbootLogApplication.java new file mode 100644 index 00000000..181d8374 --- /dev/null +++ b/log/springboot-log/src/main/java/cn/cunchang/SpringbootLogApplication.java @@ -0,0 +1,13 @@ +package cn.cunchang; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringbootLogApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringbootLogApplication.class, args); + } + +} diff --git a/log/springboot-log/src/main/resources/application.properties b/log/springboot-log/src/main/resources/application.properties new file mode 100644 index 00000000..699f0a1a --- /dev/null +++ b/log/springboot-log/src/main/resources/application.properties @@ -0,0 +1,15 @@ +# 指定自定义 logger 对象日志级别 +logging.level.cn.cunchang=trace + +# 指定控制台输出消息格式 +logging.pattern.console=[%-5level] %d{yyyy-MM-dd HH:mm:ss} %c [%thread]===== %msg %n + +# 指定存放日志文件的具体路径 +# logging.file=/Users/cunchang/logs/springboot.log +# 指定日志文件存放的目录,默认的文件名 spring.log +logging.file.path=/Users/cunchang/logs/springboot/ +# 指定日志文件消息格式 +logging.pattern.file=[%-5level] %d{yyyy-MM-dd HH:mm:ss} %c [%thread]===== %msg %n + +# 指定项目使用的具体环境 +spring.profiles.active=pro diff --git a/log/springboot-log/src/main/resources/logback-spring.xml b/log/springboot-log/src/main/resources/logback-spring.xml new file mode 100644 index 00000000..58c707c8 --- /dev/null +++ b/log/springboot-log/src/main/resources/logback-spring.xml @@ -0,0 +1,28 @@ + + + + + + + + + + System.err + + + + ${pattern} + + + [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] xxxxxxxx %m %n + + + + + + + + + \ No newline at end of file diff --git a/log/springboot-log/src/main/resources/logconfig/application.properties b/log/springboot-log/src/main/resources/logconfig/application.properties new file mode 100644 index 00000000..699f0a1a --- /dev/null +++ b/log/springboot-log/src/main/resources/logconfig/application.properties @@ -0,0 +1,15 @@ +# 指定自定义 logger 对象日志级别 +logging.level.cn.cunchang=trace + +# 指定控制台输出消息格式 +logging.pattern.console=[%-5level] %d{yyyy-MM-dd HH:mm:ss} %c [%thread]===== %msg %n + +# 指定存放日志文件的具体路径 +# logging.file=/Users/cunchang/logs/springboot.log +# 指定日志文件存放的目录,默认的文件名 spring.log +logging.file.path=/Users/cunchang/logs/springboot/ +# 指定日志文件消息格式 +logging.pattern.file=[%-5level] %d{yyyy-MM-dd HH:mm:ss} %c [%thread]===== %msg %n + +# 指定项目使用的具体环境 +spring.profiles.active=pro diff --git a/log/springboot-log/src/main/resources/logconfig/log4j2.xml b/log/springboot-log/src/main/resources/logconfig/log4j2.xml new file mode 100644 index 00000000..dd6d85f9 --- /dev/null +++ b/log/springboot-log/src/main/resources/logconfig/log4j2.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/log/springboot-log/src/main/resources/logconfig/logback.xml b/log/springboot-log/src/main/resources/logconfig/logback.xml new file mode 100644 index 00000000..0ba3fcf9 --- /dev/null +++ b/log/springboot-log/src/main/resources/logconfig/logback.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + System.err + + + ${pattern} + + + + + + + + + \ No newline at end of file diff --git a/log/springboot-log/src/test/java/cn/cunchang/SpringbootLogApplicationTests.java b/log/springboot-log/src/test/java/cn/cunchang/SpringbootLogApplicationTests.java new file mode 100644 index 00000000..c928c823 --- /dev/null +++ b/log/springboot-log/src/test/java/cn/cunchang/SpringbootLogApplicationTests.java @@ -0,0 +1,29 @@ +package cn.cunchang; + +import org.apache.logging.log4j.LogManager; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class SpringbootLogApplicationTests { + + // 声明日志记录器对象 + public static final Logger log = LoggerFactory.getLogger(SpringbootLogApplicationTests.class); + + @Test + public void contextLoads() { + // 打印日志信息 + log.error("error"); + log.warn("warn"); + log.info("info"); // 默认日志级别 + log.debug("debug"); + log.trace("trace"); + + // 使用 lo4j2 使用桥接器切换为 slf4j 门面和 logback 日志实现 + org.apache.logging.log4j.Logger logger = LogManager.getLogger(SpringbootLogApplicationTests.class); + logger.info("log4j2 info"); + } + +} diff --git "a/log/\346\227\245\345\277\227\346\212\200\346\234\257 \357\274\210\344\270\212\357\274\211.pdf" "b/log/\346\227\245\345\277\227\346\212\200\346\234\257 \357\274\210\344\270\212\357\274\211.pdf" new file mode 100644 index 00000000..89ce79a2 Binary files /dev/null and "b/log/\346\227\245\345\277\227\346\212\200\346\234\257 \357\274\210\344\270\212\357\274\211.pdf" differ diff --git "a/log/\346\227\245\345\277\227\346\212\200\346\234\257 \357\274\210\344\270\213\357\274\211.pdf" "b/log/\346\227\245\345\277\227\346\212\200\346\234\257 \357\274\210\344\270\213\357\274\211.pdf" new file mode 100644 index 00000000..37892c3a Binary files /dev/null and "b/log/\346\227\245\345\277\227\346\212\200\346\234\257 \357\274\210\344\270\213\357\274\211.pdf" differ diff --git a/mvc/servlet/build/classes/cn/lastwhisper/service/AbstractHelloService.class b/mvc/servlet/build/classes/cn/lastwhisper/service/AbstractHelloService.class new file mode 100644 index 00000000..5ed306ab Binary files /dev/null and b/mvc/servlet/build/classes/cn/lastwhisper/service/AbstractHelloService.class differ diff --git a/mvc/servlet/build/classes/cn/lastwhisper/service/HelloService.class b/mvc/servlet/build/classes/cn/lastwhisper/service/HelloService.class new file mode 100644 index 00000000..fa8bf628 Binary files /dev/null and b/mvc/servlet/build/classes/cn/lastwhisper/service/HelloService.class differ diff --git a/mvc/servlet/build/classes/cn/lastwhisper/service/HelloServiceExt.class b/mvc/servlet/build/classes/cn/lastwhisper/service/HelloServiceExt.class new file mode 100644 index 00000000..a74484bf Binary files /dev/null and b/mvc/servlet/build/classes/cn/lastwhisper/service/HelloServiceExt.class differ diff --git a/mvc/servlet/build/classes/cn/lastwhisper/service/HelloServiceImpl.class b/mvc/servlet/build/classes/cn/lastwhisper/service/HelloServiceImpl.class new file mode 100644 index 00000000..fcd72c2f Binary files /dev/null and b/mvc/servlet/build/classes/cn/lastwhisper/service/HelloServiceImpl.class differ diff --git a/mvc/servlet/build/classes/cn/lastwhisper/servlet/HelloServlet.class b/mvc/servlet/build/classes/cn/lastwhisper/servlet/HelloServlet.class new file mode 100644 index 00000000..ea0e7aa8 Binary files /dev/null and b/mvc/servlet/build/classes/cn/lastwhisper/servlet/HelloServlet.class differ diff --git a/mvc/servlet/build/classes/cn/lastwhisper/servlet/MyServletContainerInitializer.class b/mvc/servlet/build/classes/cn/lastwhisper/servlet/MyServletContainerInitializer.class new file mode 100644 index 00000000..3cbcff3a Binary files /dev/null and b/mvc/servlet/build/classes/cn/lastwhisper/servlet/MyServletContainerInitializer.class differ diff --git a/mvc/servlet/build/classes/cn/lastwhisper/servlet/UserFilter.class b/mvc/servlet/build/classes/cn/lastwhisper/servlet/UserFilter.class new file mode 100644 index 00000000..01ed9760 Binary files /dev/null and b/mvc/servlet/build/classes/cn/lastwhisper/servlet/UserFilter.class differ diff --git a/mvc/servlet/build/classes/cn/lastwhisper/servlet/UserListener.class b/mvc/servlet/build/classes/cn/lastwhisper/servlet/UserListener.class new file mode 100644 index 00000000..25b26a24 Binary files /dev/null and b/mvc/servlet/build/classes/cn/lastwhisper/servlet/UserListener.class differ diff --git a/mvc/servlet/build/classes/cn/lastwhisper/servlet/UserServlet.class b/mvc/servlet/build/classes/cn/lastwhisper/servlet/UserServlet.class new file mode 100644 index 00000000..253929bd Binary files /dev/null and b/mvc/servlet/build/classes/cn/lastwhisper/servlet/UserServlet.class differ diff --git a/mvc/springmvc/src/main/java/cn/lastwhisper/bean/User.java b/mvc/springmvc/src/main/java/cn/lastwhisper/bean/User.java new file mode 100644 index 00000000..1f704a6d --- /dev/null +++ b/mvc/springmvc/src/main/java/cn/lastwhisper/bean/User.java @@ -0,0 +1,33 @@ +package cn.lastwhisper.bean; + +/** + * + * @author lastwhisper + * @date 2020/6/3 + */ +public class User { + + private String username; + private String password; + + public User(String username, String password) { + this.username = username; + this.password = password; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/mvc/springmvc/src/main/java/cn/lastwhisper/controller/ParameterController1.java b/mvc/springmvc/src/main/java/cn/lastwhisper/controller/ParameterController1.java index 8267cb0d..c82364a1 100644 --- a/mvc/springmvc/src/main/java/cn/lastwhisper/controller/ParameterController1.java +++ b/mvc/springmvc/src/main/java/cn/lastwhisper/controller/ParameterController1.java @@ -68,4 +68,6 @@ public void testParam4(@PathVariable("username") String username, @PathVariable System.out.println(username+","+age); } + + } \ No newline at end of file diff --git a/mvc/springmvc/src/main/java/cn/lastwhisper/controller/ParameterController2.java b/mvc/springmvc/src/main/java/cn/lastwhisper/controller/ParameterController2.java new file mode 100644 index 00000000..c5c61963 --- /dev/null +++ b/mvc/springmvc/src/main/java/cn/lastwhisper/controller/ParameterController2.java @@ -0,0 +1,39 @@ +package cn.lastwhisper.controller; + +import cn.lastwhisper.bean.User; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.List; + +/** + * + * @author lastwhisper + * @date 2020/6/3 + */ +@Controller +@RequestMapping("param2") +public class ParameterController2 { + + @RequestMapping("test1") + @ResponseBody + public String testParam1(List list) { + for (Object o : list) { + System.out.println(o); + } + return "success"; + } + + @RequestMapping("test2") + @ResponseBody + public String testParam2(@RequestBody List list) { + for (Object o : list) { + System.out.println(o); + } + return "success"; + } +} + + diff --git a/mvc/src/main/webapp/WEB-INF/web.xml b/mvc/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 9f88c1f9..00000000 --- a/mvc/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - Archetype Created Web Application - diff --git a/mvc/src/main/webapp/index.jsp b/mvc/src/main/webapp/index.jsp deleted file mode 100644 index c38169bb..00000000 --- a/mvc/src/main/webapp/index.jsp +++ /dev/null @@ -1,5 +0,0 @@ - - -

Hello World!

- - diff --git a/notes/leetcode/leetcode-56.vsdx b/notes/leetcode/leetcode-56.vsdx new file mode 100644 index 00000000..7fd62ba0 Binary files /dev/null and b/notes/leetcode/leetcode-56.vsdx differ diff --git "a/notes/leetcode/\357\274\210\346\250\241\346\235\277\357\274\211LeetCode \347\254\254 \351\242\230\357\274\232\342\200\234\342\200\235\351\242\230\350\247\243\351\205\215\345\233\276.pptx" "b/notes/leetcode/\357\274\210\346\250\241\346\235\277\357\274\211LeetCode \347\254\254 \351\242\230\357\274\232\342\200\234\342\200\235\351\242\230\350\247\243\351\205\215\345\233\276.pptx" deleted file mode 100644 index 365bc558..00000000 Binary files "a/notes/leetcode/\357\274\210\346\250\241\346\235\277\357\274\211LeetCode \347\254\254 \351\242\230\357\274\232\342\200\234\342\200\235\351\242\230\350\247\243\351\205\215\345\233\276.pptx" and /dev/null differ diff --git a/orm/jdbc/README.md b/orm/jdbc/README.md new file mode 100644 index 00000000..e375d947 --- /dev/null +++ b/orm/jdbc/README.md @@ -0,0 +1,144 @@ +# JDBC开发步骤 + +创建一个以JDBC连接数据库的程序,包含7个步骤: + +## 1、加载JDBC驱动程序: + +在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机),这通过java.lang.Class.forName(String className)实现。 例如: + +```Java +try{ + //加载MySql的驱动类 + Class.forName("com.mysql.jdbc.Driver") ; +}catch(ClassNotFoundException e){ + System.out.println("找不到驱动程序类 ,加载驱动失败!"); + e.printStackTrace() ; +} +``` + +成功加载后,会将Driver类的实例注册到DriverManager类中。 + +## 2、提供JDBC连接的URL + +连接URL定义了连接数据库时的协议、子协议、数据源标识。 + +- 书写形式:协议:子协议:数据源标识 +- 协议:在JDBC中总是以jdbc开始 +- 子协议:是桥连接的驱动程序或是数据库管理系统名称。 +- 数据源标识:标记找到数据库来源的地址与连接端口。 + +例如:(MySql的连接URL) + +jdbc:mysql:[//localhost:3306/test?useUnicode=true&characterEncoding=gbk](//localhost:3306/test?useUnicode=true&characterEncoding=gbk); + +useUnicode=true:表示使用Unicode字符集。如果characterEncoding设置为gb2312或GBK,本参数必须设置为true 。characterEncoding=gbk:字符编码方式。 + +## 3、创建数据库的连接 + +要连接数据库,需要向java.sql.DriverManager请求并获得Connection对象,该对象就代表一个数据库的连接。Mysql Connection接口实现类com.mysql.cj.jdbc.ConnectionImpl + +例如: + +```Java +//连接MySql数据库,用户名和密码都是root +String url = "jdbc:mysql://localhost:3306/test" ; +String username = "root" ; +String password = "gg" ; +try{ + Connection con = DriverManager.getConnection(url , username , password); +}catch(SQLException se){ + System.out.println("数据库连接失败!"); + se.printStackTrace() ; +} +``` + +## 4、创建一个Statement + +要执行SQL语句,必须获得java.sql.Statement实例,Statement实例分为以下3 种类型: + +1、执行静态SQL语句。通常通过Statement实例实现。 + +2、执行动态SQL语句。通常通过PreparedStatement实例实现。 + +3、执行数据库存储过程。通常通过CallableStatement实例实现。 + +具体的实现方式: + +```Java +Statement stmt = con.createStatement() ; +ResultSet rs = stmt.executeQuery("SELECT firstname,lastname FROM people"); + +PreparedStatement pstmt = con.prepareStatement("update people set firstname=? , lastname=? where id=?") ; +CallableStatement cstmt = con.prepareCall("{CALL demoSp(? , ?)}") ; +``` + +## 5、执行SQL语句 + +Statement接口提供了三种执行SQL语句的方法:executeQuery 、executeUpdate 和execute + +1、ResultSet executeQuery(String sqlString):执行查询数据库的SQL语句,返回一个结果集(ResultSet)对象。 + +2、int executeUpdate(String sqlString):用于执行INSERT、UPDATE或DELETE语句以及SQL DDL语句,如:CREATE TABLE和DROP TABLE等 + +3、execute(sqlString):用于执行返回多个结果集、多个更新计数或二者组合的语句。 + +具体实现的代码: + +```java +ResultSet rs = stmt.executeQuery("SELECT * FROM ...") ; +int rows = stmt.executeUpdate("INSERT INTO ...") ; +boolean flag = stmt.execute(String sql) ; +``` + +## 6、处理结果 + +两种情况: + +1、执行更新返回的是本次操作影响到的记录数。 + +2、执行查询返回的结果是一个ResultSet对象。 + +ResultSet包含符合SQL语句中条件的所有行,并且它通过一套get方法提供了对这些行中数据的访问。 使用结果集(ResultSet)对象的访问方法获取数据: + +```java +while(rs.next()){ + String name = rs.getString("name") ; + String pass = rs.getString(1) ; // 此方法比较高效(列是从左到右编号的,并且从列1开始) +} +``` + +## 7、关闭JDBC对象 + +操作完成以后要把所有使用的JDBC对象全都关闭,以释放JDBC资源,关闭顺序和声明顺序相反: + +1、关闭记录集 + +2、关闭声明 + +3、关闭连接对象 + +```java +if(rs != null){ // 关闭记录集 + try{ + rs.close() ; + }catch(SQLException e){ + e.printStackTrace() ; + } +} + +if(stmt != null){ // 关闭声明 + try{ + stmt.close() ; + }catch(SQLException e){ + e.printStackTrace() ; + } +} +if(conn != null){ // 关闭连接对象 + try{ + conn.close() ; + }catch(SQLException e){ + e.printStackTrace() ; + } +} +``` + diff --git a/orm/jdbc/pom.xml b/orm/jdbc/pom.xml index 6f912f00..d15daba6 100644 --- a/orm/jdbc/pom.xml +++ b/orm/jdbc/pom.xml @@ -2,14 +2,17 @@ - - orm - cn.lastwhisper - 1.0-SNAPSHOT - + + + + + 4.0.0 + cn.lastwhisper--> jdbc + 1.0-SNAPSHOT--> + diff --git a/orm/jpa/jpa-onetomany/src/main/java/cn/lastwhisper/jpaonetomany/domain/Customer.java b/orm/jpa/jpa-onetomany/src/main/java/cn/lastwhisper/jpaonetomany/domain/Customer.java index a86e3931..1a8ebe7b 100644 --- a/orm/jpa/jpa-onetomany/src/main/java/cn/lastwhisper/jpaonetomany/domain/Customer.java +++ b/orm/jpa/jpa-onetomany/src/main/java/cn/lastwhisper/jpaonetomany/domain/Customer.java @@ -1,6 +1,8 @@ package cn.lastwhisper.jpaonetomany.domain; import lombok.*; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; import javax.persistence.*; import java.io.Serializable; diff --git a/orm/mongodb/pom.xml b/orm/mongodb/pom.xml new file mode 100644 index 00000000..4b4ab923 --- /dev/null +++ b/orm/mongodb/pom.xml @@ -0,0 +1,64 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.2.1.RELEASE + + + cn.cunchang + mongodb + 0.0.1-SNAPSHOT + mongodb + Demo project for Spring Boot Data MongoDB + + 1.8 + + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + org.springframework.boot + spring-boot-starter-web + + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + junit + junit + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + + diff --git a/orm/mongodb/src/main/java/cn/cunchang/Application.java b/orm/mongodb/src/main/java/cn/cunchang/Application.java new file mode 100644 index 00000000..2ba8082d --- /dev/null +++ b/orm/mongodb/src/main/java/cn/cunchang/Application.java @@ -0,0 +1,13 @@ +package cn.cunchang; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/orm/mongodb/src/main/java/cn/cunchang/domain/Comment.java b/orm/mongodb/src/main/java/cn/cunchang/domain/Comment.java new file mode 100644 index 00000000..5ae35add --- /dev/null +++ b/orm/mongodb/src/main/java/cn/cunchang/domain/Comment.java @@ -0,0 +1,147 @@ +package cn.cunchang.domain; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.index.CompoundIndex; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.Field; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Date; + +/** + * 文章评论实体类 + */ +//把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的文档。 +//@Document(collection="mongodb 对应 collection 名") +// 若未加 @Document ,该 bean save 到 mongo 的 comment collection +// 若添加 @Document ,则 save 到 comment collection +@Document(collection="comment")//可以省略,如果省略,则默认使用类名小写映射集合 +//复合索引 +@CompoundIndex( def = "{'userid': 1, 'nickname': -1}") +public class Comment implements Serializable { + //主键标识,该属性的值会自动对应mongodb的主键字段"_id",如果该属性名就叫“id”,则该注解可以省略,否则必须写 + @Id + private String id;//主键 + //该属性对应mongodb的字段的名字,如果一致,则无需该注解 + @Field("content") + private String content;//吐槽内容 + private Date publishtime;//发布日期 + //添加了一个单字段的索引 + @Indexed + private String userid;//发布人ID + private String nickname;//昵称 + private LocalDateTime createdatetime;//评论的日期时间 + private Integer likenum;//点赞数 + private Integer replynum;//回复数 + private String state;//状态 + private String parentid;//上级ID + private String articleid; + //getter and setter..... + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public Date getPublishtime() { + return publishtime; + } + + public void setPublishtime(Date publishtime) { + this.publishtime = publishtime; + } + + public String getUserid() { + return userid; + } + + public void setUserid(String userid) { + this.userid = userid; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public LocalDateTime getCreatedatetime() { + return createdatetime; + } + + public void setCreatedatetime(LocalDateTime createdatetime) { + this.createdatetime = createdatetime; + } + + public Integer getLikenum() { + return likenum; + } + + public void setLikenum(Integer likenum) { + this.likenum = likenum; + } + + public Integer getReplynum() { + return replynum; + } + + public void setReplynum(Integer replynum) { + this.replynum = replynum; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public String getParentid() { + return parentid; + } + + public void setParentid(String parentid) { + this.parentid = parentid; + } + + public String getArticleid() { + return articleid; + } + + public void setArticleid(String articleid) { + this.articleid = articleid; + } + + @Override + public String toString() { + return "Comment{" + + "id='" + id + '\'' + + ", content='" + content + '\'' + + ", publishtime=" + publishtime + + ", userid='" + userid + '\'' + + ", nickname='" + nickname + '\'' + + ", createdatetime=" + createdatetime + + ", likenum=" + likenum + + ", replynum=" + replynum + + ", state='" + state + '\'' + + ", parentid='" + parentid + '\'' + + ", articleid='" + articleid + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/orm/mongodb/src/main/java/cn/cunchang/repository/CommentRepository.java b/orm/mongodb/src/main/java/cn/cunchang/repository/CommentRepository.java new file mode 100644 index 00000000..fa39100b --- /dev/null +++ b/orm/mongodb/src/main/java/cn/cunchang/repository/CommentRepository.java @@ -0,0 +1,12 @@ +package cn.cunchang.repository; + +import cn.cunchang.domain.Comment; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.mongodb.repository.MongoRepository; + +public interface CommentRepository extends MongoRepository { + + Page findByParentid(String parentid, Pageable pageable); + +} diff --git a/orm/mongodb/src/main/java/cn/cunchang/service/CommentService.java b/orm/mongodb/src/main/java/cn/cunchang/service/CommentService.java new file mode 100644 index 00000000..ebbd3b3c --- /dev/null +++ b/orm/mongodb/src/main/java/cn/cunchang/service/CommentService.java @@ -0,0 +1,90 @@ +package cn.cunchang.service; + +import cn.cunchang.domain.Comment; +import cn.cunchang.repository.CommentRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class CommentService { + + @Autowired + private CommentRepository commentRepository; + @Autowired + private MongoTemplate mongoTemplate; + + + + /** + * 保存一个评论 + * @param comment + */ + public void saveComment(Comment comment){ + //如果需要自定义主键,可以在这里指定主键;如果不指定主键,MongoDB会自动生成主键 + //设置一些默认初始值。。。 + //调用dao + commentRepository.save(comment); + } + + /** + * 更新评论 + * @param comment + */ + public void updateComment(Comment comment){ + //调用dao + commentRepository.save(comment); + } + + /** + * 根据id删除评论 + * @param id + */ + public void deleteCommentById(String id){ + //调用dao + commentRepository.deleteById(id); + } + + /** + * 查询所有评论 + * @return + */ + public List findCommentList(){ + //调用dao + return commentRepository.findAll(); + } + + /** + * 根据id查询评论 + * @param id + * @return + */ + public Comment findCommentById(String id){ + //调用dao + return commentRepository.findById(id).get(); + } + + + public Page findCommentListByParentid(String parentid,int page,int size) { + return commentRepository.findByParentid(parentid,PageRequest.of(page-1,size)); + } + + public void updateCommentLikenum(String id){ + + // 查询条件 + Query query = Query.query(Criteria.where("_id").is(id)); + // 更新条件 + Update update = new Update(); + update.inc("likenum"); + mongoTemplate.updateFirst(query,update,Comment.class); + } + +} \ No newline at end of file diff --git a/orm/mongodb/src/main/resources/application.yml b/orm/mongodb/src/main/resources/application.yml new file mode 100644 index 00000000..eece65c8 --- /dev/null +++ b/orm/mongodb/src/main/resources/application.yml @@ -0,0 +1,13 @@ +spring: + #数据源配置 + data: + mongodb: + # 主机地址 + host: 127.0.0.1 + # 数据库 + database: articledb + # 默认端口是27017 + port: 27017 + # 也可以使用uri连接 + # bobo:123456 账号密码 +# uri: mongodb://bobo:123456@180.76.159.126:27017,180.76.159.126:27018,180.76.159.126:27019/articledb?connect=replicaSet&slaveOk=true&replicaSet=myrs \ No newline at end of file diff --git a/orm/mongodb/src/test/java/cn/cunchang/ApplicationTests.java b/orm/mongodb/src/test/java/cn/cunchang/ApplicationTests.java new file mode 100644 index 00000000..c13144bc --- /dev/null +++ b/orm/mongodb/src/test/java/cn/cunchang/ApplicationTests.java @@ -0,0 +1,13 @@ +package cn.cunchang; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/orm/mongodb/src/test/java/cn/cunchang/service/CommentServiceTest.java b/orm/mongodb/src/test/java/cn/cunchang/service/CommentServiceTest.java new file mode 100644 index 00000000..d6af5098 --- /dev/null +++ b/orm/mongodb/src/test/java/cn/cunchang/service/CommentServiceTest.java @@ -0,0 +1,66 @@ +package cn.cunchang.service; + +import cn.cunchang.domain.Comment; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.Page; +import org.springframework.test.context.junit4.SpringRunner; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author cunchang + * @date 2021/4/5 1:43 下午 + */ +@RunWith(SpringRunner.class) +@SpringBootTest +public class CommentServiceTest { + + @Autowired + private CommentService commentService; + + + @Test + public void testFindCommentList() { + List commentList = commentService.findCommentList(); + System.out.println(commentList); + } + + @Test + public void testFindCommentById() { + Comment commentById = commentService.findCommentById("606aa5b81cc0086e2eedd0d5"); + System.out.println(commentById); + } + + @Test + public void testSaveComment(){ + Comment comment=new Comment(); + // 不设置 id,MongoDB 会帮我们生成一个 ObjectId + comment.setArticleid("100000"); + comment.setContent("测试添加的数据的评论"); + comment.setCreatedatetime(LocalDateTime.now()); + comment.setUserid("1004"); + comment.setNickname("tomcat"); + comment.setState("1"); + comment.setLikenum(0); + comment.setReplynum(0); + comment.setParentid("606aa5b81cc0086e2eedd0d5"); + commentService.saveComment(comment); + } + + @Test + public void testFindCommentListByParentid() { + Page page = commentService.findCommentListByParentid("606aa5b81cc0086e2eedd0d5", 1, 2); + System.out.println(page.getTotalElements()); + System.out.println(page.getContent()); + } + + @Test + public void testUpdateCommentLikenum() { + commentService.updateCommentLikenum("606aa6ece3f00c7ab1909598"); + } + +} \ No newline at end of file diff --git a/orm/mybatis/mybatis-action/dirty-read/README.md b/orm/mybatis/mybatis-action/dirty-read/README.md new file mode 100644 index 00000000..0c116c34 --- /dev/null +++ b/orm/mybatis/mybatis-action/dirty-read/README.md @@ -0,0 +1,18 @@ +# mybatis一级缓存导致的脏读 + + + +## mybatis下读已提交测试 + +| 步骤 | thread A | thread B | +| ---- | -------------------------------------------------- | ------------------------- | +| 1 | 开启事务 | | +| 2 | User user1 = userMapper.selectById(1L);user1不为空 | 开启事务 | +| 3 | Thread.sleep(10s); | userMapper.deleteById(1L) | +| 4 | | 提交事务 | +| 5 | User user2= userMapper.selectById(1L);user2不为空 | | +| 6 | 提交事务 | | + +- 按照mysql`读已提交`的规则,第5步应该返回空 +- 第2步有sql打印,第5步无sql打印,且user1==user2,说明user2是mybatis的缓存 + diff --git a/orm/mybatis/mybatis-action/dirty-read/init.sql b/orm/mybatis/mybatis-action/dirty-read/init.sql new file mode 100644 index 00000000..d6b0d180 --- /dev/null +++ b/orm/mybatis/mybatis-action/dirty-read/init.sql @@ -0,0 +1,12 @@ +CREATE TABLE `user` +( + `id` int NOT NULL AUTO_INCREMENT, + `username` varchar(32) NOT NULL COMMENT '用户名称', + `birthday` datetime DEFAULT NULL COMMENT '生日', + `sex` char(1) DEFAULT NULL COMMENT '性别', + `address` varchar(256) DEFAULT NULL COMMENT '地址', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO `user` (`id`, `username`, `birthday`, `sex`, `address`) VALUES +('1', 'tomcat1', '2021-03-16 22:37:51', '男', '北京市顺义区1'); diff --git a/orm/mybatis/mybatis-action/dirty-read/pom.xml b/orm/mybatis/mybatis-action/dirty-read/pom.xml new file mode 100644 index 00000000..c30b92f6 --- /dev/null +++ b/orm/mybatis/mybatis-action/dirty-read/pom.xml @@ -0,0 +1,96 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.2.0.RELEASE + + + cn.cunchang + dirty-read + 0.0.1-SNAPSHOT + springboot-ssm + Demo project for Spring Boot mybatis-xml + + + 1.8 + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.1.2 + + + + com.alibaba + druid-spring-boot-starter + 1.1.21 + + + + mysql + mysql-connector-java + + + + + io.springfox + springfox-swagger2 + 2.9.2 + + + io.springfox + springfox-swagger-ui + 2.9.2 + + + io.swagger + swagger-models + 1.5.22 + + + io.swagger + swagger-annotations + 1.5.22 + + + + org.projectlombok + lombok + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/Application.java b/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/Application.java new file mode 100644 index 00000000..372d4b71 --- /dev/null +++ b/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/Application.java @@ -0,0 +1,14 @@ +package cn.cunchang; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/config/RdsDataSourceConfiguration.java b/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/config/RdsDataSourceConfiguration.java new file mode 100644 index 00000000..56887c7a --- /dev/null +++ b/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/config/RdsDataSourceConfiguration.java @@ -0,0 +1,58 @@ +package cn.cunchang.config; + +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.SqlSessionTemplate; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; + +import javax.sql.DataSource; +import java.util.Properties; + +@Configuration +@MapperScan(basePackages = "cn.cunchang.mapper", sqlSessionFactoryRef = "sqlSessionFactory") +@Slf4j +public class RdsDataSourceConfiguration { + + @Bean(name = "dataSource") + @ConfigurationProperties(prefix = "spring.datasource.rds") + public DataSource dataSource() { + return DruidDataSourceBuilder.create().build(); + } + + @Bean(name = "sqlSessionFactory") + public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) { + final SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); + bean.setDataSource(dataSource); + ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + try { + bean.setConfigLocation(resolver.getResource("classpath:mybatis/mybatis-config.xml")); + bean.setMapperLocations(resolver.getResources("classpath:mybatis/mapper/*.xml")); + Properties prop = new Properties(); + bean.setConfigurationProperties(prop); + return bean.getObject(); + } catch (Exception e) { + log.error("初始化数据库异常", e); + throw new RuntimeException(e); + } + } + + @Bean(name = "transactionManager") + public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DataSource dataSource) { + return new DataSourceTransactionManager(dataSource); + } + + @Bean(name = "sqlSessionTemplate") + public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) { + return new SqlSessionTemplate(sqlSessionFactory); + } + +} \ No newline at end of file diff --git a/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/config/SwaggerConfig.java b/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/config/SwaggerConfig.java new file mode 100644 index 00000000..062dc691 --- /dev/null +++ b/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/config/SwaggerConfig.java @@ -0,0 +1,29 @@ +package cn.cunchang.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + * @author cunchang + */ +@Configuration +@EnableSwagger2 +public class SwaggerConfig { + @Bean + public Docket createRestApi() { + return new Docket(DocumentationType.SWAGGER_2) + .pathMapping("/") + .select() + .apis(RequestHandlerSelectors.basePackage("cn.cunchang")) + .paths(PathSelectors.any()) + .build().apiInfo(new ApiInfoBuilder() + .version("1.0") + .build()); + } +} diff --git a/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/controller/UserController.java b/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/controller/UserController.java new file mode 100644 index 00000000..0efa2032 --- /dev/null +++ b/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/controller/UserController.java @@ -0,0 +1,68 @@ +package cn.cunchang.controller; + +import cn.cunchang.mapper.UserMapper; +import cn.cunchang.model.User; +import io.swagger.annotations.Api; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Isolation; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Date; +import java.util.concurrent.TimeUnit; + +/** + * @author cunchang + * @date 2020/5/31 + */ +@Api(value = "UserController", description = "") +@RestController +@RequestMapping("") +public class UserController { + + @Autowired + private UserMapper userMapper; + + @GetMapping("/init") + @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, + rollbackFor = Exception.class) + public String init() { + User user = new User(); + user.setId(1L); + user.setUsername("tomcat1"); + user.setBirthday(new Date()); + user.setSex("男"); + user.setAddress("北京市顺义区1"); + + int row = userMapper.insert(user); + return "succes"+row; + } + + @GetMapping("/rctx1") + @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, + rollbackFor = Exception.class) + public String rctx1() throws InterruptedException { + User user1 = userMapper.selectById(1L); + System.err.println("delete前,用户id=1的信息:"+user1); + // 睡10s,等delete执行完 + TimeUnit.SECONDS.sleep(10L); + + User user2 = userMapper.selectById(1L); + System.err.println("delete后,用户id=1的信息:"+user2); + System.err.println("user1==user2?:"+(user1==user2)); + return "succes"; + } + + @GetMapping("/rctx2") + @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, + rollbackFor = Exception.class) + public String rctx2() { + int row = userMapper.deleteById(1L); + return "succes"; + } + + +} diff --git a/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/mapper/UserMapper.java b/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/mapper/UserMapper.java new file mode 100644 index 00000000..50f26cdd --- /dev/null +++ b/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/mapper/UserMapper.java @@ -0,0 +1,48 @@ +package cn.cunchang.mapper; + +import cn.cunchang.model.User; +import org.apache.ibatis.annotations.Options; +import org.apache.ibatis.mapping.StatementType; + +/** + * 用户数据层 + * + * @author cunchang + * @date 2020/5/31 + */ +public interface UserMapper { + + /** + * 根据用户 id 查询单个用户 + * + * @param userId 用户 id + * @return 用户 + */ + @Options(flushCache= Options.FlushCachePolicy.TRUE,statementType = StatementType.PREPARED) + User selectById(Long id); + + /** + * 保存用户 + * + * @param user 用户 + * @return int 更新行数量 + */ + int insert(User user); + + /** + * 更新用户 + * + * @param user 用户 + * @return int 更新行数量 + */ + int updateById(User user); + + /** + * 根据用户 id 删除用户 + * + * @param userId 用户 id + * @return int 更新行数量 + */ + int deleteById(Long id); + +} diff --git a/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/model/User.java b/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/model/User.java new file mode 100644 index 00000000..10d4a644 --- /dev/null +++ b/orm/mybatis/mybatis-action/dirty-read/src/main/java/cn/cunchang/model/User.java @@ -0,0 +1,40 @@ +package cn.cunchang.model; + +import lombok.Data; +import lombok.ToString; + +import java.util.Date; + +/** + * @author cunchang + * @date 2020/5/30 + */ +@Data +@ToString +public class User { + + private Long id; + + /** + * 用户名称 + */ + private String username; + + /** + * 生日 + */ + private Date birthday; + + /** + * 性别 + */ + private String sex; + + /** + * 地址 + */ + private String address; + + + +} diff --git a/orm/mybatis/mybatis-action/dirty-read/src/main/resources/application.yml b/orm/mybatis/mybatis-action/dirty-read/src/main/resources/application.yml new file mode 100644 index 00000000..17eef61e --- /dev/null +++ b/orm/mybatis/mybatis-action/dirty-read/src/main/resources/application.yml @@ -0,0 +1,28 @@ +logging: + level: + cn: + cunchang: + mapper: debug +spring: + datasource: + rds: + url: jdbc:mysql://localhost:3306/orm?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true + driver-class-name: com.mysql.jdbc.Driver + username: root + password: 123456 + initialSize: 10 + maxActive: 30 + minIdle: 10 + #获取连接等待超时时间 + maxWait: 60000 + #间隔多久进行一次检测,检测需要关闭的空闲连接 + timeBetweenEvictionRunsMillis: 60000 + #一个连接在池中最小生存的时间 + minEvictableIdleTimeMillis: 300000 + validationQuery: SELECT 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + #打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false + poolPreparedStatements: false + maxPoolPreparedStatementPerConnectionSize: 20 diff --git a/orm/mybatis/mybatis-action/dirty-read/src/main/resources/mybatis/mapper/UserMapper.xml b/orm/mybatis/mybatis-action/dirty-read/src/main/resources/mybatis/mapper/UserMapper.xml new file mode 100644 index 00000000..46f275fb --- /dev/null +++ b/orm/mybatis/mybatis-action/dirty-read/src/main/resources/mybatis/mapper/UserMapper.xml @@ -0,0 +1,39 @@ + + + + + + + + id, username,birthday, sex , address + + + + + + INSERT INTO user (id,username, birthday, sex, address) + VALUES (#{id},#{username}, #{birthday}, #{sex}, #{address}) + + + + UPDATE user + + username = #{username}, + birthday = #{birthday}, + sex = #{sex}, + address = #{address}, + + WHERE + id = #{id} + + + + DELETE FROM `user` + WHERE `id` = #{id} + + + \ No newline at end of file diff --git a/orm/mybatis/mybatis-action/dirty-read/src/main/resources/mybatis/mybatis-config.xml b/orm/mybatis/mybatis-action/dirty-read/src/main/resources/mybatis/mybatis-config.xml new file mode 100644 index 00000000..1efddd51 --- /dev/null +++ b/orm/mybatis/mybatis-action/dirty-read/src/main/resources/mybatis/mybatis-config.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/orm/mybatis/mybatis-action/insert-fetch-id/pom.xml b/orm/mybatis/mybatis-action/insert-fetch-id/pom.xml new file mode 100644 index 00000000..50c2d861 --- /dev/null +++ b/orm/mybatis/mybatis-action/insert-fetch-id/pom.xml @@ -0,0 +1,43 @@ + + + + 4.0.0 + mybatis-crud + cn.lastwhisper + 1.0-SNAPSHOT + + + + org.mybatis + mybatis + 3.4.5 + + + + mysql + mysql-connector-java + 8.0.21 + + + + log4j + log4j + 1.2.12 + + + + junit + junit + 4.10 + + + + org.projectlombok + lombok + 1.18.10 + + + + \ No newline at end of file diff --git a/orm/mybatis/mybatis-action/insert-fetch-id/sql/rt.sql b/orm/mybatis/mybatis-action/insert-fetch-id/sql/rt.sql new file mode 100644 index 00000000..8c1eed69 --- /dev/null +++ b/orm/mybatis/mybatis-action/insert-fetch-id/sql/rt.sql @@ -0,0 +1,13 @@ +CREATE DATABASE orm; +USE orm; +DROP TABLE IF EXISTS `user`; + +CREATE TABLE `user` +( + `id` int(11) NOT NULL auto_increment, + `username` varchar(32) NOT NULL COMMENT '用户名称', + `birthday` datetime default NULL COMMENT '生日', + `sex` char(1) default NULL COMMENT '性别', + `address` varchar(256) default NULL COMMENT '地址', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/orm/mybatis/mybatis-action/insert-fetch-id/src/main/java/cn/cunchang/dao/UserMapper.java b/orm/mybatis/mybatis-action/insert-fetch-id/src/main/java/cn/cunchang/dao/UserMapper.java new file mode 100644 index 00000000..efe6b792 --- /dev/null +++ b/orm/mybatis/mybatis-action/insert-fetch-id/src/main/java/cn/cunchang/dao/UserMapper.java @@ -0,0 +1,86 @@ +package cn.cunchang.dao; + +import cn.cunchang.domain.User; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Options; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.SelectKey; + +import java.util.List; + +/** + * @author Administrator + */ +public interface UserMapper { + + /** + * 普通新增 + * @param user + * @return + */ + int insert(User user); + + /** + * xml配置标签获取id + * @param user + * @return + */ + int insert1(User user); + + /** + * xml配置useGeneratedKeys + * @param user + * @return + */ + int insert2(User user); + + /** + * 结合@Param注解 + * @param user + * @return + */ + int insert3(@Param("do") User user); + + /** + * 注解配置 + * @param user + * @return + */ + @Insert("insert into user(username,sex,birthday,address) values(#{username},#{sex},#{birthday},#{address})") + @SelectKey(keyColumn = "id", keyProperty = "id", resultType = Integer.class, before = + false, statement = {"select last_insert_id()"}) + int insert4(User user); + + /** + * 普通批量插入 + * @param list + * @return + */ + int insertBatch(@Param("list") List list); + + /** + * 批量插入xml配置 + * @param list + * @return + */ + int insertBatch1(@Param("list") List list); + + /** + * 批量插入注解配置 + * @param list + * @return + */ + @Insert("") + @Options(useGeneratedKeys = true, keyProperty = "id") + int insertBatch2(@Param("list") List list); + + + + /*************ExecutorType.BATCH模式************/ + + + +} diff --git a/orm/mybatis/mybatis-action/insert-fetch-id/src/main/java/cn/cunchang/domain/User.java b/orm/mybatis/mybatis-action/insert-fetch-id/src/main/java/cn/cunchang/domain/User.java new file mode 100644 index 00000000..aa3680d0 --- /dev/null +++ b/orm/mybatis/mybatis-action/insert-fetch-id/src/main/java/cn/cunchang/domain/User.java @@ -0,0 +1,24 @@ +package cn.cunchang.domain; + +import lombok.*; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author Administrator + */ +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +@ToString +public class User implements Serializable { + + private Integer id; + private String username; + private Date birthday; + private String sex; + private String address; + +} \ No newline at end of file diff --git a/orm/mybatis/mybatis-action/insert-fetch-id/src/main/resources/SqlMapConfig.xml b/orm/mybatis/mybatis-action/insert-fetch-id/src/main/resources/SqlMapConfig.xml new file mode 100644 index 00000000..2e4b5dac --- /dev/null +++ b/orm/mybatis/mybatis-action/insert-fetch-id/src/main/resources/SqlMapConfig.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/orm/mybatis/mybatis-action/insert-fetch-id/src/main/resources/cn/cunchang/dao/UserMapper.xml b/orm/mybatis/mybatis-action/insert-fetch-id/src/main/resources/cn/cunchang/dao/UserMapper.xml new file mode 100644 index 00000000..f18232e2 --- /dev/null +++ b/orm/mybatis/mybatis-action/insert-fetch-id/src/main/resources/cn/cunchang/dao/UserMapper.xml @@ -0,0 +1,46 @@ + + + + + + insert into user(username,birthday,sex,address) + values(#{username},#{birthday},#{sex},#{address}) + + + + + select last_insert_id(); + + insert into user(username,birthday,sex,address) + values(#{username},#{birthday},#{sex},#{address}) + + + + insert into user(username,birthday,sex,address) + values(#{username},#{birthday},#{sex},#{address}) + + + + insert into user(username,birthday,sex,address) + values(#{do.username},#{do.birthday},#{do.sex},#{do.address}) + + + + insert into user(username,birthday,sex,address) + values + + (#{do.username},#{do.birthday},#{do.sex},#{do.address}) + + + + + insert into user(username,birthday,sex,address) + values + + (#{do.username},#{do.birthday},#{do.sex},#{do.address}) + + + + \ No newline at end of file diff --git a/orm/mybatis/mybatis-action/insert-fetch-id/src/main/resources/log4j.properties b/orm/mybatis/mybatis-action/insert-fetch-id/src/main/resources/log4j.properties new file mode 100644 index 00000000..ad1a14eb --- /dev/null +++ b/orm/mybatis/mybatis-action/insert-fetch-id/src/main/resources/log4j.properties @@ -0,0 +1,12 @@ +# Set root category priority to INFO and its only appender to CONSOLE. +#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal +log4j.rootCategory=debug, CONSOLE, LOGFILE + +# Set the enterprise logger category to FATAL and its only appender to CONSOLE. +log4j.logger.cn.cunchang=CONSOLE + +# CONSOLE is set to be a ConsoleAppender using a PatternLayout. +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n + diff --git a/orm/mybatis/mybatis-action/insert-fetch-id/src/test/java/cn/lastwhisper/test/ExecutorTypeBatch.java b/orm/mybatis/mybatis-action/insert-fetch-id/src/test/java/cn/lastwhisper/test/ExecutorTypeBatch.java new file mode 100644 index 00000000..28bb5ddb --- /dev/null +++ b/orm/mybatis/mybatis-action/insert-fetch-id/src/test/java/cn/lastwhisper/test/ExecutorTypeBatch.java @@ -0,0 +1,62 @@ +package cn.lastwhisper.test; + +import cn.cunchang.dao.UserMapper; +import cn.cunchang.domain.User; +import org.apache.ibatis.io.Resources; +import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.InputStream; +import java.sql.PreparedStatement; +import java.util.ArrayList; +import java.util.List; + +/** + * @author cunchang + * @date 2021/11/25 11:12 下午 + */ +public class ExecutorTypeBatch { + + private InputStream in; + SqlSessionFactory sqlSessionFactory; + + + @Test + public void testInsertBatch1(List userList) { + // 创建 SqlSession 对象 + SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH,false); + // 创建 Dao 的代理对象 + UserMapper userMapper = session.getMapper(UserMapper.class); + + for (User user : userList) { + userMapper.insert(user); + } + + session.commit(); + //7.释放资源 + session.close(); + } + + + @Before//在测试方法执行之前执行 + public void init() throws Exception { + //1.读取配置文件 + in = Resources.getResourceAsStream("SqlMapConfig.xml"); + //2.创建构建者对象 + SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); + //3.创建 SqlSession 工厂对象 + SqlSessionFactory factory = builder.build(in); + + } + + @After//在测试方法执行完成之后执行 + public void destroy() throws Exception { + in.close(); + } + +} diff --git a/orm/mybatis/mybatis-action/insert-fetch-id/src/test/java/cn/lastwhisper/test/InsertFetchIdTest.java b/orm/mybatis/mybatis-action/insert-fetch-id/src/test/java/cn/lastwhisper/test/InsertFetchIdTest.java new file mode 100644 index 00000000..6d49b993 --- /dev/null +++ b/orm/mybatis/mybatis-action/insert-fetch-id/src/test/java/cn/lastwhisper/test/InsertFetchIdTest.java @@ -0,0 +1,90 @@ +package cn.lastwhisper.test; + +import cn.cunchang.dao.UserMapper; +import cn.cunchang.domain.User; +import org.apache.ibatis.io.Resources; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * 增删改查 + */ +public class InsertFetchIdTest { + private InputStream in; + private SqlSession session; + private UserMapper userMapper; + + @Test + public void testInsert1() { + User user = new User(); + user.setUsername("tomcat"); + user.setAddress("北京市顺义区"); + user.setSex("男"); + user.setBirthday(new Date()); + System.out.println("保存操作之前:" + user); + Assert.assertEquals(1, userMapper.insert(user)); +// Assert.assertEquals(1, userMapper.insert1(user)); +// Assert.assertEquals(1, userMapper.insert2(user)); +// Assert.assertEquals(1, userMapper.insert3(user)); +// Assert.assertEquals(1, userMapper.insert4(user)); + System.out.println("保存操作之后:" + user); + } + + @Test + public void testInsertBatch1() { + User user1 = new User(); + user1.setUsername("tomcat1"); + user1.setAddress("北京市顺义区1"); + user1.setSex("男"); + user1.setBirthday(new Date()); + + User user2 = new User(); + user2.setUsername("tomcat2"); + user2.setAddress("北京市顺义区2"); + user2.setSex("男"); + user2.setBirthday(new Date()); + List list = new ArrayList<>(); + list.add(user1); + list.add(user2); + + System.out.println("保存操作之前:" + list); + Assert.assertEquals(list.size(), userMapper.insertBatch(list)); +// Assert.assertEquals(list.size(), userMapper.insertBatch1(list)); +// Assert.assertEquals(list.size(), userMapper.insertBatch2(list)); + System.out.println("保存操作之后:" + list); + } + + + @Before//在测试方法执行之前执行 + public void init() throws Exception { + //1.读取配置文件 + in = Resources.getResourceAsStream("SqlMapConfig.xml"); + //2.创建构建者对象 + SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); + //3.创建 SqlSession 工厂对象 + SqlSessionFactory factory = builder.build(in); + //4.创建 SqlSession 对象 + session = factory.openSession(); + //5.创建 Dao 的代理对象 + userMapper = session.getMapper(UserMapper.class); + } + + @After//在测试方法执行完成之后执行 + public void destroy() throws Exception { + session.commit(); + //7.释放资源 + session.close(); + in.close(); + } + +} \ No newline at end of file diff --git a/orm/mybatis/mybatis-annotation-crud/pom.xml b/orm/mybatis/mybatis-annotation-crud/pom.xml index c0cd15fd..b60231fe 100644 --- a/orm/mybatis/mybatis-annotation-crud/pom.xml +++ b/orm/mybatis/mybatis-annotation-crud/pom.xml @@ -2,13 +2,43 @@ - - mybatis - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 + 4.0.0 mybatis-annotation-crud + cn.lastwhisper + 1.0-SNAPSHOT + + + + org.mybatis + mybatis + 3.4.5 + + + + mysql + mysql-connector-java + 8.0.21 + + + + log4j + log4j + 1.2.12 + + + + junit + junit + 4.10 + + + + org.projectlombok + lombok + 1.18.10 + + + \ No newline at end of file diff --git a/orm/mybatis/mybatis-cache/readme.md b/orm/mybatis/mybatis-cache/readme.md index 8c6f1ced..6779cdda 100644 --- a/orm/mybatis/mybatis-cache/readme.md +++ b/orm/mybatis/mybatis-cache/readme.md @@ -4,3 +4,4 @@ mybatis一级缓存和二级缓存 当我们在使用二级缓存时,所缓存的类一定要实现 java.io.Serializable 接口,这种就可以使用序列化 方式来保存对象。 + diff --git a/orm/mybatis/mybatis-crud/pom.xml b/orm/mybatis/mybatis-crud/pom.xml index 0f43643c..50c2d861 100644 --- a/orm/mybatis/mybatis-crud/pom.xml +++ b/orm/mybatis/mybatis-crud/pom.xml @@ -2,13 +2,42 @@ - - mybatis - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 + 4.0.0 mybatis-crud + cn.lastwhisper + 1.0-SNAPSHOT + + + + org.mybatis + mybatis + 3.4.5 + + + + mysql + mysql-connector-java + 8.0.21 + + + + log4j + log4j + 1.2.12 + + + + junit + junit + 4.10 + + + + org.projectlombok + lombok + 1.18.10 + + \ No newline at end of file diff --git a/orm/mybatis/mybatis-crud/sql/rt.sql b/orm/mybatis/mybatis-crud/sql/rt.sql new file mode 100644 index 00000000..8c1eed69 --- /dev/null +++ b/orm/mybatis/mybatis-crud/sql/rt.sql @@ -0,0 +1,13 @@ +CREATE DATABASE orm; +USE orm; +DROP TABLE IF EXISTS `user`; + +CREATE TABLE `user` +( + `id` int(11) NOT NULL auto_increment, + `username` varchar(32) NOT NULL COMMENT '用户名称', + `birthday` datetime default NULL COMMENT '生日', + `sex` char(1) default NULL COMMENT '性别', + `address` varchar(256) default NULL COMMENT '地址', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/orm/mybatis/mybatis-crud/src/main/java/cn/lastwhisper/mybatiscrud/domain/User.java b/orm/mybatis/mybatis-crud/src/main/java/cn/lastwhisper/mybatiscrud/domain/User.java index 3706bb70..64d398d5 100644 --- a/orm/mybatis/mybatis-crud/src/main/java/cn/lastwhisper/mybatiscrud/domain/User.java +++ b/orm/mybatis/mybatis-crud/src/main/java/cn/lastwhisper/mybatiscrud/domain/User.java @@ -14,9 +14,16 @@ @Setter @ToString public class User implements Serializable { - private Integer userId; - private String userName; - private Date userBirthday; - private String userSex; - private String userAddress; + +// private Integer userId; +// private String userName; +// private Date userBirthday; +// private String userSex; +// private String userAddress; + + private Integer id; + private String username; + private Date birthday; + private String sex; + private String address; } \ No newline at end of file diff --git a/orm/mybatis/mybatis-crud/src/main/resources/SqlMapConfig.xml b/orm/mybatis/mybatis-crud/src/main/resources/SqlMapConfig.xml index fe3b79b8..2d8a5b97 100644 --- a/orm/mybatis/mybatis-crud/src/main/resources/SqlMapConfig.xml +++ b/orm/mybatis/mybatis-crud/src/main/resources/SqlMapConfig.xml @@ -25,7 +25,7 @@ - + diff --git a/orm/mybatis/mybatis-crud/src/test/java/cn/lastwhisper/test/MybatisCRUDTest.java b/orm/mybatis/mybatis-crud/src/test/java/cn/lastwhisper/test/MybatisCRUDTest.java index 837619c8..e1a89a72 100644 --- a/orm/mybatis/mybatis-crud/src/test/java/cn/lastwhisper/test/MybatisCRUDTest.java +++ b/orm/mybatis/mybatis-crud/src/test/java/cn/lastwhisper/test/MybatisCRUDTest.java @@ -35,13 +35,14 @@ public void testFindOne() { @Test public void testSave() { User user = new User(); - user.setUserName("modify User property"); - user.setUserAddress("北京市顺义区"); - user.setUserSex("男"); - user.setUserBirthday(new Date()); + user.setUsername("modify User property"); + user.setAddress("北京市顺义区"); + user.setSex("男"); + user.setBirthday(new Date()); System.out.println("保存操作之前: " + user); //5.执行保存方法 - userMapper.saveUser(user); + int row = userMapper.saveUser(user); + System.out.println("更新行数:"+row); System.out.println("保存操作之后: " + user);//出现id值 } @@ -50,7 +51,7 @@ public void testUpdateUser()throws Exception{ // 根据 id 查询 User user = userMapper.findById(52); //6.执行操作 - user.setUserAddress("北京市顺义区"); + user.setAddress("北京市顺义区"); int res = userMapper.updateUser(user); System.out.println(res); } diff --git a/orm/mybatis/mybatis-crud/src/test/java/cn/lastwhisper/test/MybatisSelectTest.java b/orm/mybatis/mybatis-crud/src/test/java/cn/lastwhisper/test/MybatisSelectTest.java index 39b7e1a6..46666088 100644 --- a/orm/mybatis/mybatis-crud/src/test/java/cn/lastwhisper/test/MybatisSelectTest.java +++ b/orm/mybatis/mybatis-crud/src/test/java/cn/lastwhisper/test/MybatisSelectTest.java @@ -62,7 +62,7 @@ public void testFindTotal() throws Exception { public void testFindByQueryVo() { QueryVo vo = new QueryVo(); User user = new User(); - user.setUserName("%王%"); + user.setUsername("%王%"); vo.setUser(user); List users = userMapper.findUserByVo(vo); for(User u : users) { diff --git a/orm/mybatis/mybatis-datasource-tx/pom.xml b/orm/mybatis/mybatis-datasource-tx/pom.xml deleted file mode 100644 index d7bd23cd..00000000 --- a/orm/mybatis/mybatis-datasource-tx/pom.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - mybatis - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - mybatis-datasource-tx - - \ No newline at end of file diff --git a/orm/mybatis/mybatis-datasource-tx/src/main/java/cn/lastwhisper/mybatis/datasource/dao/UserMapper.java b/orm/mybatis/mybatis-datasource-tx/src/main/java/cn/lastwhisper/mybatis/datasource/dao/UserMapper.java deleted file mode 100644 index f5db06be..00000000 --- a/orm/mybatis/mybatis-datasource-tx/src/main/java/cn/lastwhisper/mybatis/datasource/dao/UserMapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.lastwhisper.mybatis.datasource.dao; - - -import cn.lastwhisper.mybatis.datasource.domain.User; - -/** - * @author Administrator - */ -public interface UserMapper { - - /** - * 根据 id 查询 - * @param userId - * @return - */ - User findUserById(Integer userId); - -} diff --git a/orm/mybatis/mybatis-datasource-tx/src/main/java/cn/lastwhisper/mybatis/datasource/domain/QueryVo.java b/orm/mybatis/mybatis-datasource-tx/src/main/java/cn/lastwhisper/mybatis/datasource/domain/QueryVo.java deleted file mode 100644 index 899bd3ba..00000000 --- a/orm/mybatis/mybatis-datasource-tx/src/main/java/cn/lastwhisper/mybatis/datasource/domain/QueryVo.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.lastwhisper.mybatis.datasource.domain; - -import java.io.Serializable; - -/** - * @author Administrator - */ -public class QueryVo implements Serializable { - private User user; - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } -} \ No newline at end of file diff --git a/orm/mybatis/mybatis-datasource-tx/src/main/java/cn/lastwhisper/mybatis/datasource/domain/User.java b/orm/mybatis/mybatis-datasource-tx/src/main/java/cn/lastwhisper/mybatis/datasource/domain/User.java deleted file mode 100644 index 421fb839..00000000 --- a/orm/mybatis/mybatis-datasource-tx/src/main/java/cn/lastwhisper/mybatis/datasource/domain/User.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.lastwhisper.mybatis.datasource.domain; - -import lombok.*; - -import java.io.Serializable; -import java.util.Date; - -/** - * @author Administrator - */ -@AllArgsConstructor -@NoArgsConstructor -@Getter -@Setter -@ToString -public class User implements Serializable { - private Integer userid; - private String username; - private Date userbirthday; - private String usersex; - private String useraddress; -} \ No newline at end of file diff --git a/orm/mybatis/mybatis-datasource-tx/src/main/resources/SqlMapConfig.xml b/orm/mybatis/mybatis-datasource-tx/src/main/resources/SqlMapConfig.xml deleted file mode 100644 index a53a6654..00000000 --- a/orm/mybatis/mybatis-datasource-tx/src/main/resources/SqlMapConfig.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/orm/mybatis/mybatis-datasource-tx/src/main/resources/cn/lastwhisper/mybatis/datasource/dao/UserMapper.xml b/orm/mybatis/mybatis-datasource-tx/src/main/resources/cn/lastwhisper/mybatis/datasource/dao/UserMapper.xml deleted file mode 100644 index 4d0de673..00000000 --- a/orm/mybatis/mybatis-datasource-tx/src/main/resources/cn/lastwhisper/mybatis/datasource/dao/UserMapper.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/orm/mybatis/mybatis-datasource-tx/src/main/resources/log4j.properties b/orm/mybatis/mybatis-datasource-tx/src/main/resources/log4j.properties deleted file mode 100644 index db708da3..00000000 --- a/orm/mybatis/mybatis-datasource-tx/src/main/resources/log4j.properties +++ /dev/null @@ -1,19 +0,0 @@ -# Set root category priority to INFO and its only appender to CONSOLE. -#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal -log4j.rootCategory=debug, CONSOLE, LOGFILE - -# Set the enterprise logger category to FATAL and its only appender to CONSOLE. -log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE - -# CONSOLE is set to be a ConsoleAppender using a PatternLayout. -log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender -log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout -log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n - -# LOGFILE is set to be a File appender using a PatternLayout. -log4j.appender.LOGFILE=org.apache.log4j.FileAppender -#log4j.appender.LOGFILE.File=d:\axis.log -log4j.appender.LOGFILE.Append=true -log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout -log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n - diff --git a/orm/mybatis/mybatis-datasource-tx/src/test/java/cn/lastwhisper/test/MybatisCRUDTest.java b/orm/mybatis/mybatis-datasource-tx/src/test/java/cn/lastwhisper/test/MybatisCRUDTest.java deleted file mode 100644 index 9f514376..00000000 --- a/orm/mybatis/mybatis-datasource-tx/src/test/java/cn/lastwhisper/test/MybatisCRUDTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.lastwhisper.test; - -import cn.lastwhisper.mybatis.datasource.dao.UserMapper; -import cn.lastwhisper.mybatis.datasource.domain.User; -import org.apache.ibatis.io.Resources; -import org.apache.ibatis.session.SqlSession; -import org.apache.ibatis.session.SqlSessionFactory; -import org.apache.ibatis.session.SqlSessionFactoryBuilder; -import org.junit.Test; - -import java.io.InputStream; - -/** - * 增删改查 - */ -public class MybatisCRUDTest { - private InputStream in; - private SqlSession session; - private UserMapper userMapper; - - - /** - * mybatis数据源 - * PooledDataSource中找到popConnection()方法 - */ - @Test - public void testSql() throws Exception { - InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml"); - SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); - SqlSession sqlSession = factory.openSession(); - UserMapper userMapper = sqlSession.getMapper(UserMapper.class); - User user = userMapper.findUserById(42); - System.out.println(user); - - // 释放资源 - sqlSession.close(); - in.close(); - } - - -} \ No newline at end of file diff --git a/orm/mybatis/mybatis-design/pom.xml b/orm/mybatis/mybatis-design/pom.xml deleted file mode 100644 index d824f953..00000000 --- a/orm/mybatis/mybatis-design/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - mybatis - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - mybatis-design - - - - - log4j - log4j - 1.2.12 - - - - dom4j - dom4j - 1.6.1 - - - - mysql - mysql-connector-java - 5.1.6 - - - - jaxen - jaxen - 1.1.6 - - - junit - junit - 4.10 - - - - \ No newline at end of file diff --git a/orm/mybatis/mybatis-design/readme.md b/orm/mybatis/mybatis-design/readme.md deleted file mode 100644 index 617f3b10..00000000 --- a/orm/mybatis/mybatis-design/readme.md +++ /dev/null @@ -1 +0,0 @@ -手写 Mybatis 框架 \ No newline at end of file diff --git a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/dao/IUserDao.java b/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/dao/IUserDao.java deleted file mode 100644 index f17b67d0..00000000 --- a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/dao/IUserDao.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.lastwhisper.dao; - -import cn.lastwhisper.domain.User; -import cn.lastwhisper.mybatis.annotations.Select; - -import java.util.List; - -/** - * @author 黑马程序员 - * @Company http://www.ithiema.com - * - * 用户的持久层接口 - */ -public interface IUserDao { - - /** - * 查询所有操作 - * @return - */ - @Select("select * from user") - List findAll(); -} diff --git a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/domain/User.java b/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/domain/User.java deleted file mode 100644 index 7a2feb43..00000000 --- a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/domain/User.java +++ /dev/null @@ -1,68 +0,0 @@ -package cn.lastwhisper.domain; - -import java.io.Serializable; -import java.util.Date; - -/** - * @author 黑马程序员 - * @Company http://www.ithiema.com - */ -public class User implements Serializable{ - - private Integer id; - private String username; - private Date birthday; - private String sex; - private String address; - - public Integer getId() { - return id; - } - - public void setId(Integer id) { - this.id = id; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public Date getBirthday() { - return birthday; - } - - public void setBirthday(Date birthday) { - this.birthday = birthday; - } - - public String getSex() { - return sex; - } - - public void setSex(String sex) { - this.sex = sex; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - @Override - public String toString() { - return "User{" + - "id=" + id + - ", username='" + username + '\'' + - ", birthday=" + birthday + - ", sex='" + sex + '\'' + - ", address='" + address + '\'' + - '}'; - } -} diff --git a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/annotations/Select.java b/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/annotations/Select.java deleted file mode 100644 index a1506862..00000000 --- a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/annotations/Select.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.lastwhisper.mybatis.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author 黑马程序员 - * @Company http://www.ithiema.com - * 查询的注解 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface Select { - - /** - * 配置SQL语句的 - * @return - */ - String value(); -} diff --git a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/cfg/Configuration.java b/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/cfg/Configuration.java deleted file mode 100644 index 9c3a8e75..00000000 --- a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/cfg/Configuration.java +++ /dev/null @@ -1,59 +0,0 @@ -package cn.lastwhisper.mybatis.cfg; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author 黑马程序员 - * @Company http://www.ithiema.com - * 自定义mybatis的配置类 - */ -public class Configuration { - - private String driver; - private String url; - private String username; - private String password; - - private Map mappers = new HashMap(); - - public Map getMappers() { - return mappers; - } - - public void setMappers(Map mappers) { - this.mappers.putAll(mappers);//此处需要使用追加的方式 - } - - public String getDriver() { - return driver; - } - - public void setDriver(String driver) { - this.driver = driver; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } -} diff --git a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/cfg/Mapper.java b/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/cfg/Mapper.java deleted file mode 100644 index b1bcd9e0..00000000 --- a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/cfg/Mapper.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.lastwhisper.mybatis.cfg; - -/** - * @author 黑马程序员 - * @Company http://www.ithiema.com - * 用于封装执行的SQL语句和结果类型的全限定类名 - */ -public class Mapper { - - private String queryString;//SQL - private String resultType;//实体类的全限定类名 - - public String getQueryString() { - return queryString; - } - - public void setQueryString(String queryString) { - this.queryString = queryString; - } - - public String getResultType() { - return resultType; - } - - public void setResultType(String resultType) { - this.resultType = resultType; - } -} diff --git a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/io/Resources.java b/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/io/Resources.java deleted file mode 100644 index 541331b7..00000000 --- a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/io/Resources.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.lastwhisper.mybatis.io; - -import java.io.InputStream; - -/** - * @author 黑马程序员 - * @Company http://www.ithiema.com - * 使用类加载器读取配置文件的类 - */ -public class Resources { - - /** - * 根据传入的参数,获取一个字节输入流 - * @param filePath - * @return - */ - public static InputStream getResourceAsStream(String filePath){ - return Resources.class.getClassLoader().getResourceAsStream(filePath); - } -} diff --git a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/SqlSession.java b/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/SqlSession.java deleted file mode 100644 index 1e9754a6..00000000 --- a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/SqlSession.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.lastwhisper.mybatis.sqlsession; - -/** - * @author 黑马程序员 - * @Company http://www.ithiema.com - * 自定义Mybatis中和数据库交互的核心类 - * 它里面可以创建dao接口的代理对象 - */ -public interface SqlSession { - - /** - * 根据参数创建一个代理对象 - * @param daoInterfaceClass dao的接口字节码 - * @param - * @return - */ - T getMapper(Class daoInterfaceClass); - - /** - * 释放资源 - */ - void close(); -} diff --git a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/SqlSessionFactory.java b/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/SqlSessionFactory.java deleted file mode 100644 index d3c20e75..00000000 --- a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/SqlSessionFactory.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.lastwhisper.mybatis.sqlsession; - -/** - * @author 黑马程序员 - * @Company http://www.ithiema.com - */ -public interface SqlSessionFactory { - - /** - * 用于打开一个新的SqlSession对象 - * @return - */ - SqlSession openSession(); -} diff --git a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/SqlSessionFactoryBuilder.java b/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/SqlSessionFactoryBuilder.java deleted file mode 100644 index 23ec39ed..00000000 --- a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/SqlSessionFactoryBuilder.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.lastwhisper.mybatis.sqlsession; - -import cn.lastwhisper.mybatis.cfg.Configuration; -import cn.lastwhisper.mybatis.sqlsession.defaults.DefaultSqlSessionFactory; -import cn.lastwhisper.mybatis.utils.XMLConfigBuilder; - -import java.io.InputStream; - -/** - * @author 黑马程序员 - * @Company http://www.ithiema.com - * 用于创建一个SqlSessionFactory对象 - */ -public class SqlSessionFactoryBuilder { - - /** - * 根据参数的字节输入流来构建一个SqlSessionFactory工厂 - * @param config - * @return - */ - public SqlSessionFactory build(InputStream config) { - Configuration cfg = XMLConfigBuilder.loadConfiguration(config); - return new DefaultSqlSessionFactory(cfg); - } -} diff --git a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/defaults/DefaultSqlSession.java b/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/defaults/DefaultSqlSession.java deleted file mode 100644 index 16fe42e8..00000000 --- a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/defaults/DefaultSqlSession.java +++ /dev/null @@ -1,52 +0,0 @@ -package cn.lastwhisper.mybatis.sqlsession.defaults; - - -import cn.lastwhisper.mybatis.cfg.Configuration; -import cn.lastwhisper.mybatis.sqlsession.SqlSession; -import cn.lastwhisper.mybatis.sqlsession.proxy.MapperProxy; -import cn.lastwhisper.mybatis.utils.DataSourceUtil; - -import java.lang.reflect.Proxy; -import java.sql.Connection; - -/** - * @author 黑马程序员 - * @Company http://www.ithiema.com - * SqlSession接口的实现类 - */ -public class DefaultSqlSession implements SqlSession { - - private Configuration cfg; - private Connection connection; - - public DefaultSqlSession(Configuration cfg){ - this.cfg = cfg; - connection = DataSourceUtil.getConnection(cfg); - } - - /** - * 用于创建代理对象 - * @param daoInterfaceClass dao的接口字节码 - * @param - * @return - */ - @Override - public T getMapper(Class daoInterfaceClass) { - return (T) Proxy.newProxyInstance(daoInterfaceClass.getClassLoader(), - new Class[]{daoInterfaceClass},new MapperProxy(cfg.getMappers(),connection)); - } - - /** - * 用于释放资源 - */ - @Override - public void close() { - if(connection != null) { - try { - connection.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } -} diff --git a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/defaults/DefaultSqlSessionFactory.java b/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/defaults/DefaultSqlSessionFactory.java deleted file mode 100644 index 3c8cb400..00000000 --- a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/defaults/DefaultSqlSessionFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.lastwhisper.mybatis.sqlsession.defaults; - - -import cn.lastwhisper.mybatis.cfg.Configuration; -import cn.lastwhisper.mybatis.sqlsession.SqlSession; -import cn.lastwhisper.mybatis.sqlsession.SqlSessionFactory; - -/** - * @author 黑马程序员 - * @Company http://www.ithiema.com - * SqlSessionFactory接口的实现类 - */ -public class DefaultSqlSessionFactory implements SqlSessionFactory { - - private Configuration cfg; - - public DefaultSqlSessionFactory(Configuration cfg) { - this.cfg = cfg; - } - - /** - * 用于创建一个新的操作数据库对象 - * @return - */ - @Override - public SqlSession openSession() { - return new DefaultSqlSession(cfg); - } -} diff --git a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/proxy/MapperProxy.java b/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/proxy/MapperProxy.java deleted file mode 100644 index b0754fee..00000000 --- a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/sqlsession/proxy/MapperProxy.java +++ /dev/null @@ -1,52 +0,0 @@ -package cn.lastwhisper.mybatis.sqlsession.proxy; - - -import cn.lastwhisper.mybatis.cfg.Mapper; -import cn.lastwhisper.mybatis.utils.Executor; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.sql.Connection; -import java.util.Map; - -/** - * @author 黑马程序员 - * @Company http://www.ithiema.com - */ -public class MapperProxy implements InvocationHandler { - - //map的key是全限定类名+方法名 - private Map mappers; - private Connection conn; - - public MapperProxy(Map mappers,Connection conn){ - this.mappers = mappers; - this.conn = conn; - } - - /** - * 用于对方法进行增强的,我们的增强其实就是调用selectList方法 - * @param proxy - * @param method - * @param args - * @return - * @throws Throwable - */ - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - //1.获取方法名 - String methodName = method.getName(); - //2.获取方法所在类的名称 - String className = method.getDeclaringClass().getName(); - //3.组合key - String key = className+"."+methodName; - //4.获取mappers中的Mapper对象 - Mapper mapper = mappers.get(key); - //5.判断是否有mapper - if(mapper == null){ - throw new IllegalArgumentException("传入的参数有误"); - } - //6.调用工具类执行查询所有 - return new Executor().selectList(mapper,conn); - } -} diff --git a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/utils/DataSourceUtil.java b/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/utils/DataSourceUtil.java deleted file mode 100644 index bf62c05f..00000000 --- a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/utils/DataSourceUtil.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.lastwhisper.mybatis.utils; - -import cn.lastwhisper.mybatis.cfg.Configuration; - -import java.sql.Connection; -import java.sql.DriverManager; - -/** - * @author 黑马程序员 - * @Company http://www.ithiema.com - * 用于创建数据源的工具类 - */ -public class DataSourceUtil { - - /** - * 用于获取一个连接 - * @param cfg - * @return - */ - public static Connection getConnection(Configuration cfg){ - try { - Class.forName(cfg.getDriver()); - return DriverManager.getConnection(cfg.getUrl(), cfg.getUsername(), cfg.getPassword()); - }catch(Exception e){ - throw new RuntimeException(e); - } - } -} diff --git a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/utils/Executor.java b/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/utils/Executor.java deleted file mode 100644 index 359014e8..00000000 --- a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/utils/Executor.java +++ /dev/null @@ -1,86 +0,0 @@ -package cn.lastwhisper.mybatis.utils; - - -import cn.lastwhisper.mybatis.cfg.Mapper; - -import java.beans.PropertyDescriptor; -import java.lang.reflect.Method; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.util.ArrayList; -import java.util.List; - -/** - * @author 黑马程序员 - * @Company http://www.ithiema.com - * 负责执行SQL语句,并且封装结果集 - */ -public class Executor { - - public List selectList(Mapper mapper, Connection conn) { - PreparedStatement pstm = null; - ResultSet rs = null; - try { - //1.取出mapper中的数据 - String queryString = mapper.getQueryString();//select * from user - String resultType = mapper.getResultType();//com.itheima.domain.User - Class domainClass = Class.forName(resultType); - //2.获取PreparedStatement对象 - pstm = conn.prepareStatement(queryString); - //3.执行SQL语句,获取结果集 - rs = pstm.executeQuery(); - //4.封装结果集 - List list = new ArrayList();//定义返回值 - while (rs.next()) { - //实例化要封装的实体类对象 - E obj = (E) domainClass.newInstance(); - - //取出结果集的元信息:ResultSetMetaData - ResultSetMetaData rsmd = rs.getMetaData(); - //取出总列数 - int columnCount = rsmd.getColumnCount(); - //遍历总列数 - for (int i = 1; i <= columnCount; i++) { - //获取每列的名称,列名的序号是从1开始的 - String columnName = rsmd.getColumnName(i); - //根据得到列名,获取每列的值 - Object columnValue = rs.getObject(columnName); - //给obj赋值:使用Java内省机制(借助PropertyDescriptor实现属性的封装) - PropertyDescriptor pd = new PropertyDescriptor(columnName, domainClass);//要求:实体类的属性和数据库表的列名保持一种 - //获取它的写入方法 - Method writeMethod = pd.getWriteMethod(); - //把获取的列的值,给对象赋值 - writeMethod.invoke(obj, columnValue); - } - //把赋好值的对象加入到集合中 - list.add(obj); - } - return list; - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - release(pstm, rs); - } - } - - - private void release(PreparedStatement pstm, ResultSet rs) { - if (rs != null) { - try { - rs.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - if (pstm != null) { - try { - pstm.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } -} diff --git a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/utils/XMLConfigBuilder.java b/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/utils/XMLConfigBuilder.java deleted file mode 100644 index 87b60ce6..00000000 --- a/orm/mybatis/mybatis-design/src/main/java/cn/lastwhisper/mybatis/utils/XMLConfigBuilder.java +++ /dev/null @@ -1,219 +0,0 @@ -package cn.lastwhisper.mybatis.utils; - -//import com.itheima.mybatis.annotations.Select; - -import cn.lastwhisper.mybatis.annotations.Select; -import cn.lastwhisper.mybatis.cfg.Configuration; -import cn.lastwhisper.mybatis.cfg.Mapper; -import cn.lastwhisper.mybatis.io.Resources; -import org.dom4j.Attribute; -import org.dom4j.Document; -import org.dom4j.Element; -import org.dom4j.io.SAXReader; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * @author 黑马程序员 - * @Company http://www.ithiema.com - * 用于解析配置文件 - */ -public class XMLConfigBuilder { - - - /** - * 解析主配置文件,把里面的内容填充到DefaultSqlSession所需要的地方 - * 使用的技术: - * dom4j+xpath - */ - public static Configuration loadConfiguration(InputStream config) { - try { - //定义封装连接信息的配置对象(mybatis的配置对象) - Configuration cfg = new Configuration(); - - //1.获取SAXReader对象 - SAXReader reader = new SAXReader(); - //2.根据字节输入流获取Document对象 - Document document = reader.read(config); - //3.获取根节点 - Element root = document.getRootElement(); - //4.使用xpath中选择指定节点的方式,获取所有property节点 - List propertyElements = root.selectNodes("//property"); - //5.遍历节点 - for (Element propertyElement : propertyElements) { - //判断节点是连接数据库的哪部分信息 - //取出name属性的值 - String name = propertyElement.attributeValue("name"); - if ("driver".equals(name)) { - //表示驱动 - //获取property标签value属性的值 - String driver = propertyElement.attributeValue("value"); - cfg.setDriver(driver); - } - if ("url".equals(name)) { - //表示连接字符串 - //获取property标签value属性的值 - String url = propertyElement.attributeValue("value"); - cfg.setUrl(url); - } - if ("username".equals(name)) { - //表示用户名 - //获取property标签value属性的值 - String username = propertyElement.attributeValue("value"); - cfg.setUsername(username); - } - if ("password".equals(name)) { - //表示密码 - //获取property标签value属性的值 - String password = propertyElement.attributeValue("value"); - cfg.setPassword(password); - } - } - //取出mappers中的所有mapper标签,判断他们使用了resource还是class属性 - List mapperElements = root.selectNodes("//mappers/mapper"); - //遍历集合 - for (Element mapperElement : mapperElements) { - //判断mapperElement使用的是哪个属性 - Attribute attribute = mapperElement.attribute("resource"); - if (attribute != null) { - System.out.println("使用的是XML"); - //表示有resource属性,用的是XML - //取出属性的值 - String mapperPath = attribute.getValue();//获取属性的值"com/itheima/dao/IUserDao.xml" - //把映射配置文件的内容获取出来,封装成一个map - Map mappers = loadMapperConfiguration(mapperPath); - //给configuration中的mappers赋值 - cfg.setMappers(mappers); - } else { - System.out.println("使用的是注解"); - //表示没有resource属性,用的是注解 - //获取class属性的值 - String daoClassPath = mapperElement.attributeValue("class"); - //根据daoClassPath获取封装的必要信息 - Map mappers = loadMapperAnnotation(daoClassPath); - //给configuration中的mappers赋值 - cfg.setMappers(mappers); - } - } - //返回Configuration - return cfg; - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - try { - config.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - } - - /** - * 根据传入的参数,解析XML,并且封装到Map中 - * @param mapperPath 映射配置文件的位置 - * @return map中包含了获取的唯一标识(key是由dao的全限定类名和方法名组成) - * 以及执行所需的必要信息(value是一个Mapper对象,里面存放的是执行的SQL语句和要封装的实体类全限定类名) - */ - private static Map loadMapperConfiguration(String mapperPath) throws IOException { - InputStream in = null; - try { - //定义返回值对象 - Map mappers = new HashMap(); - //1.根据路径获取字节输入流 - in = Resources.getResourceAsStream(mapperPath); - //2.根据字节输入流获取Document对象 - SAXReader reader = new SAXReader(); - Document document = reader.read(in); - //3.获取根节点 - Element root = document.getRootElement(); - //4.获取根节点的namespace属性取值 - String namespace = root.attributeValue("namespace");//是组成map中key的部分 - //5.获取所有的select节点 - List selectElements = root.selectNodes("//select"); - //6.遍历select节点集合 - for (Element selectElement : selectElements) { - //取出id属性的值 组成map中key的部分 - String id = selectElement.attributeValue("id"); - //取出resultType属性的值 组成map中value的部分 - String resultType = selectElement.attributeValue("resultType"); - //取出文本内容 组成map中value的部分 - String queryString = selectElement.getText(); - //创建Key - String key = namespace + "." + id; - //创建Value - Mapper mapper = new Mapper(); - mapper.setQueryString(queryString); - mapper.setResultType(resultType); - //把key和value存入mappers中 - mappers.put(key, mapper); - } - return mappers; - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - in.close(); - } - } - - /** - * 根据传入的参数,得到dao中所有被select注解标注的方法。 - * 根据方法名称和类名,以及方法上注解value属性的值,组成Mapper的必要信息 - * @param daoClassPath - * @return - */ - private static Map loadMapperAnnotation(String daoClassPath) throws Exception { - //定义返回值对象 - Map mappers = new HashMap(); - - //1.得到dao接口的字节码对象 - Class daoClass = Class.forName(daoClassPath); - //2.得到dao接口中的方法数组 - Method[] methods = daoClass.getMethods(); - //3.遍历Method数组 - for (Method method : methods) { - //取出每一个方法,判断是否有select注解 - boolean isAnnotated = method.isAnnotationPresent(Select.class); - if (isAnnotated) { - //创建Mapper对象 - Mapper mapper = new Mapper(); - //取出注解的value属性值 - Select selectAnno = method.getAnnotation(Select.class); - String queryString = selectAnno.value(); - mapper.setQueryString(queryString); - //获取当前方法的返回值,还要求必须带有泛型信息 - Type type = method.getGenericReturnType();//List - //判断type是不是参数化的类型 - if (type instanceof ParameterizedType) { - //强转 - ParameterizedType ptype = (ParameterizedType) type; - //得到参数化类型中的实际类型参数 - Type[] types = ptype.getActualTypeArguments(); - //取出第一个 - Class domainClass = (Class) types[0]; - //获取domainClass的类名 - String resultType = domainClass.getName(); - //给Mapper赋值 - mapper.setResultType(resultType); - } - //组装key的信息 - //获取方法的名称 - String methodName = method.getName(); - String className = method.getDeclaringClass().getName(); - String key = className + "." + methodName; - //给map赋值 - mappers.put(key, mapper); - } - } - return mappers; - } - - -} diff --git a/orm/mybatis/mybatis-design/src/main/resources/SqlMapConfig.xml b/orm/mybatis/mybatis-design/src/main/resources/SqlMapConfig.xml deleted file mode 100644 index 088013e6..00000000 --- a/orm/mybatis/mybatis-design/src/main/resources/SqlMapConfig.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/orm/mybatis/mybatis-design/src/main/resources/com/itheima/dao/IUserDao.xml b/orm/mybatis/mybatis-design/src/main/resources/com/itheima/dao/IUserDao.xml deleted file mode 100644 index 6905b083..00000000 --- a/orm/mybatis/mybatis-design/src/main/resources/com/itheima/dao/IUserDao.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/orm/mybatis/mybatis-design/src/test/java/cn/lastwhisper/test/MybatisTest.java b/orm/mybatis/mybatis-design/src/test/java/cn/lastwhisper/test/MybatisTest.java deleted file mode 100644 index e81d322e..00000000 --- a/orm/mybatis/mybatis-design/src/test/java/cn/lastwhisper/test/MybatisTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.lastwhisper.test; - -import cn.lastwhisper.dao.IUserDao; -import cn.lastwhisper.domain.User; -import cn.lastwhisper.mybatis.io.Resources; -import cn.lastwhisper.mybatis.sqlsession.SqlSession; -import cn.lastwhisper.mybatis.sqlsession.SqlSessionFactory; -import cn.lastwhisper.mybatis.sqlsession.SqlSessionFactoryBuilder; - -import java.io.InputStream; -import java.util.List; - -/** - * @author 黑马程序员 - * @Company http://www.ithiema.com - * mybatis的入门案例 - */ -public class MybatisTest { - - /** - * 入门案例 - * @param args - */ - public static void main(String[] args) throws Exception { - //1.读取配置文件 - InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml"); - //2.创建SqlSessionFactory工厂 - SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); - SqlSessionFactory factory = builder.build(in); - //3.使用工厂生产SqlSession对象 - SqlSession session = factory.openSession(); - //4.使用SqlSession创建Dao接口的代理对象 - IUserDao userDao = session.getMapper(IUserDao.class); - //5.使用代理对象执行方法 - List users = userDao.findAll(); - for (User user : users) { - System.out.println(user); - } - //6.释放资源 - session.close(); - in.close(); - } -} diff --git a/orm/mybatis/mybatis-dynamicsql/src/main/resources/cn/lastwhisper/mybatis/dynamicsql/dao/UserMapper.xml b/orm/mybatis/mybatis-dynamicsql/src/main/resources/cn/lastwhisper/mybatis/dynamicsql/dao/UserMapper.xml index bd58eacf..e0ba2683 100644 --- a/orm/mybatis/mybatis-dynamicsql/src/main/resources/cn/lastwhisper/mybatis/dynamicsql/dao/UserMapper.xml +++ b/orm/mybatis/mybatis-dynamicsql/src/main/resources/cn/lastwhisper/mybatis/dynamicsql/dao/UserMapper.xml @@ -23,9 +23,9 @@ select 字段 from user where id in (?) 标签用于遍历集合,它的属性: collection:代表要遍历的集合元素,注意编写时不要写#{} + item:代表遍历集合的每个元素,生成的变量名 open:代表语句的开始部分 close:代表结束部分 - item:代表遍历集合的每个元素,生成的变量名 separator:代表分隔符 --> diff --git a/orm/mybatis/mybatis-interceptor/pom.xml b/orm/mybatis/mybatis-interceptor/pom.xml index b5649d92..a7ec3788 100644 --- a/orm/mybatis/mybatis-interceptor/pom.xml +++ b/orm/mybatis/mybatis-interceptor/pom.xml @@ -9,6 +9,6 @@ 4.0.0 - mybatis-interceptor + mybatis-interceptor-datascope \ No newline at end of file diff --git a/orm/mybatis/mybatis-lazy/src/main/resources/SqlMapConfig.xml b/orm/mybatis/mybatis-lazy/src/main/resources/SqlMapConfig.xml index df1fb7d4..178ab376 100644 --- a/orm/mybatis/mybatis-lazy/src/main/resources/SqlMapConfig.xml +++ b/orm/mybatis/mybatis-lazy/src/main/resources/SqlMapConfig.xml @@ -28,7 +28,7 @@ - + diff --git a/orm/mybatis/mybatis-lazy/src/test/java/cn/lastwhisper/test/UserTest.java b/orm/mybatis/mybatis-lazy/src/test/java/cn/lastwhisper/test/UserTest.java index 49eb92c6..adfded7f 100644 --- a/orm/mybatis/mybatis-lazy/src/test/java/cn/lastwhisper/test/UserTest.java +++ b/orm/mybatis/mybatis-lazy/src/test/java/cn/lastwhisper/test/UserTest.java @@ -27,11 +27,11 @@ public void testFindAll() { //6.执行操作 List users = userMapper.findAll(); // 延迟加载不使用,不加载Account的查询语句 - //for (User user : users) { - // System.out.println("-------每个用户的内容---------"); - // System.out.println(user); - // System.out.println(user.getAccounts()); - //} + for (User user : users) { + System.out.println("-------每个用户的内容---------"); +// System.out.println(user); + System.out.println(user.getAccounts()); + } } @Before//在测试方法执行之前执行 diff --git a/orm/mybatis/mybatis-onetomany/src/main/resources/cn/lastwhisper/mybatis/onetomany/dao/UserMapper.xml b/orm/mybatis/mybatis-onetomany/src/main/resources/cn/lastwhisper/mybatis/onetomany/dao/UserMapper.xml index b57eef3c..5fdc7e7c 100644 --- a/orm/mybatis/mybatis-onetomany/src/main/resources/cn/lastwhisper/mybatis/onetomany/dao/UserMapper.xml +++ b/orm/mybatis/mybatis-onetomany/src/main/resources/cn/lastwhisper/mybatis/onetomany/dao/UserMapper.xml @@ -24,13 +24,11 @@ \ No newline at end of file diff --git a/orm/orm.sql b/orm/mybatis/orm.sql similarity index 100% rename from orm/orm.sql rename to orm/mybatis/orm.sql diff --git a/orm/mybatis/pom.xml b/orm/mybatis/pom.xml index 1cbba4b4..7e28da99 100644 --- a/orm/mybatis/pom.xml +++ b/orm/mybatis/pom.xml @@ -11,11 +11,9 @@ pom mybatis-basic - mybatis-design mybatis-crud mybatis-dynamicsql - mybatis-datasource-tx mybatis-onetoone mybatis-onetomany mybatis-manytomany diff --git a/orm/pom.xml b/orm/pom.xml deleted file mode 100644 index fd76b827..00000000 --- a/orm/pom.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - 4.0.0 - - cn.lastwhisper - orm - pom - 1.0-SNAPSHOT - - mybatis - jpa - jdbc - - - - \ No newline at end of file diff --git a/spring-annotation/README.md b/spring-annotation/README.md index db1582f1..e4cc3ce8 100644 --- a/spring-annotation/README.md +++ b/spring-annotation/README.md @@ -7,6 +7,23 @@ 6.aop aop原理 7.transaction 声明式事务原理 8.ext 扩展 - + +比较重要的模块 +componentregister 组件注册 +lifecycle2 生命周期 +aop aop原理 +transaction 声明式事务原理 +ext 扩展 + + +spring官网 +https://docs.spring.io/spring-framework/docs/current/reference/html/core.html + +课程注释 + https://www.cnblogs.com/wjqhuaxia/p/12261814.html -https://www.cnblogs.com/zhulibin2012/p/11106112.html \ No newline at end of file +https://www.cnblogs.com/zhulibin2012/p/11106112.html + +别人写的源码分析 + +https://segmentfault.com/a/1190000022694615 \ No newline at end of file diff --git a/spring-annotation/aop-@Aspect/pom.xml b/spring-annotation/aop-@Aspect/pom.xml new file mode 100644 index 00000000..48010efa --- /dev/null +++ b/spring-annotation/aop-@Aspect/pom.xml @@ -0,0 +1,34 @@ + + + + 4.0.0 + + cn.lastwhisper + aop-Aspect + 1.0-SNAPSHOT + + + + + org.springframework + spring-aspects + 4.3.12.RELEASE + + + + org.springframework + spring-context + 4.3.12.RELEASE + + + + junit + junit + 4.12 + test + + + + \ No newline at end of file diff --git a/spring-annotation/aop/src/main/java/cn/lastwhisper/aop/LogAspects.java b/spring-annotation/aop-@Aspect/src/main/java/cn/lastwhisper/aop/LogAspects.java similarity index 99% rename from spring-annotation/aop/src/main/java/cn/lastwhisper/aop/LogAspects.java rename to spring-annotation/aop-@Aspect/src/main/java/cn/lastwhisper/aop/LogAspects.java index 67d3a95d..224b2b65 100644 --- a/spring-annotation/aop/src/main/java/cn/lastwhisper/aop/LogAspects.java +++ b/spring-annotation/aop-@Aspect/src/main/java/cn/lastwhisper/aop/LogAspects.java @@ -1,5 +1,6 @@ package cn.lastwhisper.aop; + import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.*; diff --git a/spring-annotation/aop/src/main/java/cn/lastwhisper/aop/MathCalculator.java b/spring-annotation/aop-@Aspect/src/main/java/cn/lastwhisper/aop/MathCalculator.java similarity index 100% rename from spring-annotation/aop/src/main/java/cn/lastwhisper/aop/MathCalculator.java rename to spring-annotation/aop-@Aspect/src/main/java/cn/lastwhisper/aop/MathCalculator.java diff --git a/spring-annotation/aop-@Aspect/src/main/java/cn/lastwhisper/aop/TestClient.java b/spring-annotation/aop-@Aspect/src/main/java/cn/lastwhisper/aop/TestClient.java new file mode 100644 index 00000000..eeec9c31 --- /dev/null +++ b/spring-annotation/aop-@Aspect/src/main/java/cn/lastwhisper/aop/TestClient.java @@ -0,0 +1,16 @@ +package cn.lastwhisper.aop; + +import cn.lastwhisper.aop.config.MainConfigOfAop; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +public class TestClient { + + public static void main(String[] args) { + AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAop.class); + MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class); + + mathCalculator.div(2, 1); + + } + +} \ No newline at end of file diff --git a/spring-annotation/aop-@Aspect/src/main/java/cn/lastwhisper/aop/config/MainConfigOfAop.java b/spring-annotation/aop-@Aspect/src/main/java/cn/lastwhisper/aop/config/MainConfigOfAop.java new file mode 100644 index 00000000..63fbad01 --- /dev/null +++ b/spring-annotation/aop-@Aspect/src/main/java/cn/lastwhisper/aop/config/MainConfigOfAop.java @@ -0,0 +1,194 @@ +package cn.lastwhisper.aop.config; + +import cn.lastwhisper.aop.LogAspects; +import cn.lastwhisper.aop.MathCalculator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +/** + * AOP:面向切面编程,指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式。 + * + * 1)导入AOP依赖:spring-aspects + * 2)准备一个业务处理类(MathCalculator):在业务处理时将日志进行打印(方法执行前、方法执行后、方法出现异常时...) + * 3)准备一个日志切面类(LogAspects):在业务处理类运行的不同时期执行不同的通知 + * 通知方法: + * (1)前置通知(@Before):logStart,在目标方法(div)执行之前运行 + * (2)后置通知(@After):logEnd,在目标方法(div)执行之后运行 + * (3)返回通知(@AfterReturning):logReturn,在目标方法(div)执行返回之后运行 + * (4)异常通知(@AfterThrowing):logException,在目标方法(div)执行时出现异常之后运行 + * (5)环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced()) + * 4)通知注解:给切面类的方法标注何时运行(@Before、@After...) + * 5)将业务处理类和日志切面类都加入到容器中,并告诉Spring那个是切面类(@Aspect) + * 6)给配置类中加 @EnableAspectJAutoProxy(开启基于注解的aop模式) + * + * AOP原理:看给容器中注册了什么组件,这个组件什么时候工作,这个组件的功能是什么? + * 1)@EnableAspectJAutoProxy注解的功能(看给容器中注册了什么组件) + * 导入组件@Import(AspectJAutoProxyRegistrar.class) + * AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口 + * 利用AspectJAutoProxyRegistrar自定义给容器注册bean + * 给容器中注册了一个AnnotationAwareAspectJAutoProxyCreator组件,组件名称叫做org.springframework.aop.config.internalAutoProxyCreator + * + * 2)AnnotationAwareAspectJAutoProxyCreator(这个组件什么时候工作) + * AnnotationAwareAspectJAutoProxyCreator + * ——》父类 AspectJAwareAdvisorAutoProxyCreator + * ——》父类 AbstractAdvisorAutoProxyCreator + * ——》父类 AbstractAutoProxyCreator + * implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware + * 重点关注后置处理器(在bean初始化完成前后做事情)、获取BeanFactory + * + * 在整个继承结构中,给关注点设置断点 + * AbstractAutoProxyCreator.setBeanFactory();因为它获取了BeanFactory + * AbstractAutoProxyCreator.postProcessAfterInitialization、postProcessBeforeInstantiation;因为它有后置处理器的逻辑 + * + * AbstractAdvisorAutoProxyCreator.setBeanFactory();重写了setBeanFactory(),执行自己的initBeanFactory() + * + * AspectJAwareAdvisorAutoProxyCreator没有需要关注的点 + * + * AnnotationAwareAspectJAutoProxyCreator.initBeanFactory;重新父类initBeanFactory()方法 + * + * 3)AnnotationAwareAspectJAutoProxyCreator创建和注册的过程(这个组件什么时候工作) + * 1)传入配置类,创建IOC容器 + * 2)注册配置类,AbstractApplicationContext.refresh()刷新容器 + * 3) + * // Register bean processors that intercept bean creation. + * registerBeanPostProcessors(beanFactory); + * PostProcessorRegistrationDelegate.registerBeanPostProcessors():注册bean的后置处理器,用于拦截bean的创建 + * *注册bean的后置处理器的流程: + * 1)获取IOC容器中已经定义的(还未创建),需要创建对象的所有BeanPostProcessor + * 2)给容器中加入别的BeanPostProcessor + * 3)分离BeanPostProcessor,分别注册BeanPostProcessor + * 1.First, register the BeanPostProcessors that implement PriorityOrdered + * 2.Next, register the BeanPostProcessors that implement Ordered. + * 3.Now, register all regular BeanPostProcessors. + * 4)注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,保存在容器中 + * 由于AnnotationAwareAspectJAutoProxyCreator实现了Ordered与xxxBeanPostProcessor接口在(3)的2步骤开始注册 + * *AnnotationAwareAspectJAutoProxyCreator注册流程(225行:BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);) + * 1.创建名称为internalAutoProxyCreator的BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)实例 + * 504行:doCreateBean() + * internalAutoProxyCreator——》513行:instanceWrapper = createBeanInstance(beanName, mbd, args) + * AnnotationAwareAspectJAutoProxyCreator——》515行:final Object bean = instanceWrapper.getWrappedInstance() + * 2.populateBean:给bean的属性赋值 + * 3.initializeBean:初始化bean + * *初始化bean的流程: + * 1.invokeAwareMethods:处理Aware接口的回调 + * 2.applyBeanPostProcessorsBeforeInitialization:后置处理器的Before的回调 + * 3.invokeInitMethods:执行初始化方法 + * 4.applyBeanPostProcessorsAfterInitialization:后置处理器的After的回调 + * 4.BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功 + * AnnotationAwareAspectJAutoProxyCreator调用父类的setBeanFactory(AbstractAdvisorAutoProxyCreator.setBeanFactory) + * 父类的setBeanFactory调用自身的initBeanFactory + * 5)registerBeanPostProcessors 把BeanPostProcessor注册到BeanFactory中(PostProcessorRegistrationDelegate.addBeanPostProcessor(postProcessor))——————————————注册 + * =======以上是注册AnnotationAwareAspectJAutoProxyCreator的过程======== + * + * AnnotationAwareAspectJAutoProxyCreator的后置处理器类型:InstantiationAwareBeanPostProcessor + * 下面看看InstantiationAwareBeanPostProcessor的调用时机 + * 4)finishBeanFactoryInitialization(beanFactory):完成BeanFactory初始化,创建剩下的单实例bean + * 1) + * // Instantiate all remaining (non-lazy-init) singletons. + * finishBeanFactoryInitialization——》beanFactory.preInstantiateSingletons(); + * 遍历获取容器中的所有的beanDefinitionNames,依次创建FactoryBean和普通Bean + * getBean——》doGetBean——》getSingleton + * 2)getSingleton() 创建bean + * 1)先从缓存中检查手动注册的单例对象 + * AbstractBeanFactory.doGetBean——》getSingleton(beanName); + * 2)缓存没有就走createBean()创建Bean + * [BeanPostProcessor在Bean实例创建前后调用] + * [InstantiationAwareBeanPostProcessor在Bean实例创建前先获取代理对象]//AnnotationAwareAspectJAutoProxyCreator + * 1)、resolveBeforeInstantiation解析BeforeInstantiation,创建代理对象 + * bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); + * 在这里会处理InstantiationAwareBeanPostProcessor,回调AbstractAutoProxyCreator.postProcessBeforeInstantiation方法 + * if (bean != null) { + * bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); + * } + * 2)、代理对象创建失败的话,doCreateBean(3.3.4流程),创建普通对象 + * =======以上是InstantiationAwareBeanPostProcessor的调用时机======== + * + * 下面看看InstantiationAwareBeanPostProcessor被调用时主要干什么事情(创建代理对象,将通知方法,包装成拦截器) + * 5)AnnotationAwareAspectJAutoProxyCreator[InstantiationAwareBeanPostProcessor]的作用: + * 1)Bean创建之前,调用postProcessBeforeInstantiation() + * 1)判断当前Bean是否在advisedBeans(保存了所有需要增强的Bean)中 + * 2)判断当前Bean是否是基础类(Advice、Pointcut、Advisor、AopInfrastructureBean)或者是切面(是否有@Aspect,有就是切面) + * 3)是否需要跳过 + * 1)拿到候选的增强器,就是切面里面的通知方法 [List candidateAdvisors],增强器类型 InstantiationModelAwarePointcutAdvisor + * 如果是AspectJPointcutAdvisor返回true + * 2)父类返回false + * 2)、Bean创建之后,调用postProcessAfterInitialization() + * 关注mathCalculator、LogAspects创建 + * wrapIfNecessary方法会创建代理对象,返回给spring: + * 1)、getAdvicesAndAdvisorsForBean获取当前Bean可应用的通知方法 + * 关注findEligibleAdvisors + * 1)、找到候选的所有通知方法。findCandidateAdvisors();所有切面都在这里面 + * 2)、获取可应用到当前Bean的通知方法。findAdvisorsThatCanApply(); + * AopUtils.findAdvisorsThatCanApply这里面有切点表达式的匹配代码 + * 3)、sortAdvisors(eligibleAdvisors)对通知方法进行排序,根据这排序器AnnotationAwareOrderComparator + * 2)、保存当前Bean到advisedBeans(保存了所有需要增强的Bean)中——有待商议 + * 3)、createProxy()如果当前Bean需要增强,创建当前Bean的代理对象 + * 1)、将通知方法Advisor保存到ProxyFactory中,默认会添加一个ExposeInvocationInterceptor,用于记录当前调用的MethodInvocation + * 2)、proxyFactory.getProxy()创建代理对象 + * createAopProxy()创建JdkDynamicAopProxy或者ObjenesisCglibAopProxy + * 然后JdkDynamicAopProxy.getProxy()获取代理类 + * 3)、将代理类放到proxyTypes(key:Bean,value:代理类)中 + * 3)、以后从容器中获取到的就是这个Bean的代理对象,执行目标方法的时候,代理对象会执行通知方法 + * + * =======以上是InstantiationAwareBeanPostProcessor被调用时干什么事情======== + * 下面看看代理对象创建好了,我们在Spring获取Bean组件,并且调用方法时,增强方法是怎么工作的 + * + * 6)目标方法执行时的拦截器链(将每一个通知方法包装成拦截器) + * 断点放到Bean调用方法的地方,强制步入-步出,强制步入-步出,强制步入-步出,就会进入下面的方法 + * 1)、CglibAopProxy.intercept()拦截目标方法执行 + * 2)、根据ProxyFactory获取将要执行的目标方法拦截器链 + * this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass) + * this.advised的实现类是ProxyFactory + * 1)、创建interceptorList保存拦截器链 + * 2)、遍历所有通知方法,转成Interceptor,registry.getInterceptors(advisor) + * 如果是MethodInterceptor直接加入集合 + * 如果不是,使用AdvisorAdapter将通知方法转为MethodInterceptor加入集合 + * 3)、没有拦截器链,执行目标方法 + * 4)、有拦截器链,CglibMethodInvocation.proceed()执行拦截器链 + * 5)、proceed()拦截器链的触发过程 + * 1)、如果拦截器的索引等于拦截器数组-1(最后一个拦截器调用完成或者一开始就没有拦截器),直接执行目标方法 + * 2)、如果jdk动态代理 + * 3)、如果cglib动态代理,MethodInterceptor.invoke(this); + * 这里的MethodInterceptor是所有的通知方法,this是CglibMethodInvocation + * + * ExposeInvocationInterceptor,用于记录当前调用的MethodInvocation + * + * + * 总结: + * 1)、@EnableAspectJAutoProxy 开启AOP功能 + * 2)、@EnableAspectJAutoProxy 会给容器中注册一个组件AnnotationAwareAspectJAutoProxyCreator + * 3)、AnnotationAwareAspectJAutoProxyCreator是一个后置处理器(InstantiationAwareBeanPostProcessor) + * 4)、容器的创建流程: + * 1)、registerBeanPostProcessors()注册后置处理器,创建AnnotationAwareAspectJAutoProxyCreator + * 2)、finishBeanFactoryInitialization()初始化剩下的单实例Bean + * 1)、创建业务逻辑组件和切面组件 + * 2)、resolveBeforeInstantiation->wrapIfNecessary + * 给业务组件创建代理类,将通知方法包装成增强器(Advisor) + * 5)、执行目标方法 + * 1)、代理类执行目标方法 + * 2)、CglibAopProxy.intercept()拦截方法的执行 + * 1)、将目标方法的增强器(Advice),包装成截器链(MethodInterceptor) + * 2)、利用拦截器的链式机制,依次进入每个拦截器执行 + * 3)、效果: + * 正常执行:前置通知-》目标方法-》后置通知-》返回通知 + * 异常执行:前置通知-》目标方法-》后置通知-》异常通知 + * + * + * + * @author lastwhisper + */ +@EnableAspectJAutoProxy // 开启基于注解的aop模式 +@Configuration +public class MainConfigOfAop { + + @Bean + public MathCalculator mathCalculator() { + return new MathCalculator(); + } + + @Bean + public LogAspects logAspects() { + return new LogAspects(); + } +} diff --git a/spring-annotation/aop/src/main/resources/Bean.xml b/spring-annotation/aop-@Aspect/src/main/resources/Bean.xml similarity index 100% rename from spring-annotation/aop/src/main/resources/Bean.xml rename to spring-annotation/aop-@Aspect/src/main/resources/Bean.xml diff --git a/spring-annotation/aop-interface/README.md b/spring-annotation/aop-interface/README.md new file mode 100644 index 00000000..f48ba1ab --- /dev/null +++ b/spring-annotation/aop-interface/README.md @@ -0,0 +1 @@ +1111 diff --git a/spring-annotation/aop-interface/pom.xml b/spring-annotation/aop-interface/pom.xml new file mode 100644 index 00000000..cf5a5702 --- /dev/null +++ b/spring-annotation/aop-interface/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + cn.lastwhisper + aop-interface + 0.0.1-SNAPSHOT + + + 8 + 8 + + + + + + org.springframework + spring-aspects + 4.3.12.RELEASE + + + + org.springframework + spring-context + 4.3.12.RELEASE + + + + junit + junit + 4.12 + test + + + + + \ No newline at end of file diff --git a/spring-annotation/aop-interface/src/main/java/cn/cunchang/Calculate.java b/spring-annotation/aop-interface/src/main/java/cn/cunchang/Calculate.java new file mode 100644 index 00000000..e775328a --- /dev/null +++ b/spring-annotation/aop-interface/src/main/java/cn/cunchang/Calculate.java @@ -0,0 +1,45 @@ +package cn.cunchang; + +/** + * 计算类接口 + */ +public interface Calculate { + + /** + * 加法 + * + * @param numA + * @param numB + * @return + */ + int add(int numA, int numB); + + /** + * 减法 + * + * @param numA + * @param numB + * @return + */ + int sub(int numA, int numB); + + /** + * 除法 + * + * @param numA + * @param numB + * @return + */ + int div(int numA, int numB); + + /** + * 乘法 + * + * @param numA + * @param numB + * @return + */ + int multi(int numA, int numB); + + int mod(int numA, int numB); +} \ No newline at end of file diff --git a/spring-annotation/aop-interface/src/main/java/cn/cunchang/TestClient.java b/spring-annotation/aop-interface/src/main/java/cn/cunchang/TestClient.java new file mode 100644 index 00000000..85e88091 --- /dev/null +++ b/spring-annotation/aop-interface/src/main/java/cn/cunchang/TestClient.java @@ -0,0 +1,21 @@ +package cn.cunchang; + +import cn.cunchang.aop.EalyAopMainConfig; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +/** + * @author cunchang + * @date 2022/7/2 10:11 PM + */ +public class TestClient { + public static void main(String[] args) { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(EalyAopMainConfig.class); + // 1、ProxyFactoryBean方式 +// Calculate calculateProxy = ctx.getBean("calculateProxy", Calculate.class); +// calculateProxy.div(1, 1); + + // 2、AutoProxyCreator 后置处理器方式 + Calculate calculateProxy = ctx.getBean(Calculate.class); + calculateProxy.div(1, 1); + } +} diff --git a/spring-annotation/aop-interface/src/main/java/cn/cunchang/TulingCalculate.java b/spring-annotation/aop-interface/src/main/java/cn/cunchang/TulingCalculate.java new file mode 100644 index 00000000..3463a205 --- /dev/null +++ b/spring-annotation/aop-interface/src/main/java/cn/cunchang/TulingCalculate.java @@ -0,0 +1,47 @@ +package cn.cunchang; + +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Component; + +@Component +public class TulingCalculate implements Calculate { + + @Override + public int add(int numA, int numB) { + + System.out.println("执行目标方法:add"); + System.out.println(1 / 0); + return numA + numB; + } + + @Override + public int sub(int numA, int numB) { + System.out.println("执行目标方法:reduce"); + return numA - numB; + } + + @Override + public int div(int numA, int numB) { + System.out.println("执行目标方法:div"); + return numA / numB; + } + + @Override + public int multi(int numA, int numB) { + System.out.println("执行目标方法:multi"); + + return numA * numB; + } + + @Override + public int mod(int numA, int numB) { + System.out.println("执行目标方法:mod"); + + int retVal = ((Calculate) AopContext.currentProxy()).add(numA, numB); + //int retVal = this.add(numA,numB); + + return retVal % numA; + + //return numA%numB; + } +} \ No newline at end of file diff --git a/spring-annotation/aop-interface/src/main/java/cn/cunchang/aop/EalyAopMainConfig.java b/spring-annotation/aop-interface/src/main/java/cn/cunchang/aop/EalyAopMainConfig.java new file mode 100644 index 00000000..d1c0c776 --- /dev/null +++ b/spring-annotation/aop-interface/src/main/java/cn/cunchang/aop/EalyAopMainConfig.java @@ -0,0 +1,146 @@ +package cn.cunchang.aop; + +import cn.cunchang.Calculate; +import cn.cunchang.TulingCalculate; +import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator; +import org.springframework.aop.support.NameMatchMethodPointcutAdvisor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * * Spring常见代理创建方式 + * * FactoryBean方式,创建单个动态代理: ProxyFactoryBean 1.指定续增强的接口:proxyInterfaces 2.指定需增强的实现类target 3.指定Advice、Advisor、Interceptor都行 + * * autoProxy方式:批量根据advisor自动创建 + * * BeanPostProcessor手动指定Advice方式 BeanNameAutoProxyCreator 1.指定Advice 2.可以使用正则来匹配 bean 的名字 + * * BeanPostProcessor自动扫描Advisor方式 DefaultAdvisorAutoProxyCreator (不支持注解)、 + * * AnnotationAwareAspectJAutoProxyCreator(注解)、 + * * AspectJAwareAdvisorAutoProxyCreator(XML) + * + * @author cunchang + * @date 2022/7/2 10:10 PM + */ +@Configuration +public class EalyAopMainConfig { + + // 被代理对象 + @Bean + public Calculate tulingCalculate() { + return new TulingCalculate(); + } + + // Advice 方式 + @Bean + public TulingLogAdvice tulingLogAdvice() { + return new TulingLogAdvice(); + } + + // Interceptor方式 , 类似环绕通知 + @Bean + public TulingLogInterceptor tulingLogInterceptor() { + return new TulingLogInterceptor(); + } + + /**************************1、ProxyFactoryBean******************************/ + + /** + * FactoryBean方式单个: ProxyFactoryBean + *

+ * 此中方法有个致命的问题,如果我们只能指定单一的Bean的AOP, + * 如果多个Bean需要创建多个ProxyFactoryBean 。 + * 而且,我们看到,我们的拦截器的粒度只控制到了类级别,类中所有的方法都进行了拦截。 + * 接下来,我们看看怎么样只拦截特定的方法。 + */ +// @Bean +// public ProxyFactoryBean calculateProxy() { +// ProxyFactoryBean userService = new ProxyFactoryBean(); +// userService.setInterceptorNames("tulingLogAdvice", "tulingLogInterceptor"); // 根据指定的顺序执行 +// userService.setTarget(tulingCalculate()); +// return userService; +// } + + /**************************1、ProxyFactoryBean******************************/ + + + /**************************2、ProxyFactoryBean+Advisor******************************/ + /** + * Advisor 种类很多: + * RegexpMethodPointcutAdvisor 按正则匹配类 + * NameMatchMethodPointcutAdvisor 按方法名匹配 + * DefaultBeanFactoryPointcutAdvisor xml解析的Advisor ,入参" + Arrays.asList(args)); + } +} \ No newline at end of file diff --git a/spring-annotation/aop-interface/src/main/java/cn/cunchang/aop/TulingLogInterceptor.java b/spring-annotation/aop-interface/src/main/java/cn/cunchang/aop/TulingLogInterceptor.java new file mode 100644 index 00000000..5c31d665 --- /dev/null +++ b/spring-annotation/aop-interface/src/main/java/cn/cunchang/aop/TulingLogInterceptor.java @@ -0,0 +1,19 @@ +package cn.cunchang.aop; + +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; + +import java.util.Arrays; + +public class TulingLogInterceptor implements MethodInterceptor { + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { +// System.out.println(getClass() + "调用方法前"); + System.out.println("执行目标方法【" + invocation.getMethod().getName() + "】的<环绕通知-前>,入参" + Arrays.asList(invocation.getArguments())); + Object ret = invocation.proceed(); +// System.out.println(getClass() + "调用方法后"); + System.out.println("执行目标方法【" + invocation.getMethod().getName() + "】的<环绕通知-后>,入参" + Arrays.asList(invocation.getArguments())); + return ret; + } + +} \ No newline at end of file diff --git a/spring-annotation/aop-schema-based/README.md b/spring-annotation/aop-schema-based/README.md new file mode 100644 index 00000000..32ecb215 --- /dev/null +++ b/spring-annotation/aop-schema-based/README.md @@ -0,0 +1,3 @@ +参考 +https://www.cnblogs.com/HigginCui/p/6323131.html + diff --git a/spring-annotation/aop-schema-based/pom.xml b/spring-annotation/aop-schema-based/pom.xml new file mode 100644 index 00000000..21717038 --- /dev/null +++ b/spring-annotation/aop-schema-based/pom.xml @@ -0,0 +1,37 @@ + + + + 4.0.0 + + cn.lastwhisper + aop-schema-based + 1.0-SNAPSHOT + jar + spring aop低级api xml配置 + + + + + org.springframework + spring-aspects + 4.3.12.RELEASE + + + + org.springframework + spring-context + 4.3.12.RELEASE + + + + junit + junit + 4.12 + test + + + + + \ No newline at end of file diff --git a/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/aop/CarAdvisor.java b/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/aop/CarAdvisor.java new file mode 100644 index 00000000..4c5a4229 --- /dev/null +++ b/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/aop/CarAdvisor.java @@ -0,0 +1,44 @@ +package cn.cunchang.aop; + +import java.lang.reflect.Method; + +import cn.cunchang.domain.BenzCar; +import org.springframework.aop.ClassFilter; +import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor; + +/** + * 汽车类的切面CarAdvisor类 + * 实现接口:StaticMethodMatcherPointcutAdvisor + * 实现StaticMethodMatcherPointcutAdvisor接口唯一需要定义的是matches()方法, + * + */ +public class CarAdvisor extends StaticMethodMatcherPointcutAdvisor{ + + /** + * 切点方法 匹配 + * 匹配规则:方法名为driving + * 默认情况下,匹配所有的类 + */ + @Override + public boolean matches(Method method, Class clazz) { + return "driving".equals(method.getName()); + } + + /** + * 通过覆盖getClassFilter()方法,让它仅匹配BenzCar类及其子类 + */ + @Override + public ClassFilter getClassFilter(){ + return new ClassFilter() { + /** + * 切点类 匹配 + * 匹配规则:为BenzCar类或其子类 + */ + @Override + public boolean matches(Class clazz) { + return BenzCar.class.isAssignableFrom(clazz); + } + }; + } + +} \ No newline at end of file diff --git a/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/aop/CarAdvisor2.java b/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/aop/CarAdvisor2.java new file mode 100644 index 00000000..4510a4b8 --- /dev/null +++ b/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/aop/CarAdvisor2.java @@ -0,0 +1,45 @@ +package cn.cunchang.aop; + +import cn.cunchang.domain.BenzCar; +import cn.cunchang.domain.Car; +import org.springframework.aop.ClassFilter; +import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor; + +import java.lang.reflect.Method; + +/** + * 汽车类的切面CarAdvisor类 + * 实现接口:StaticMethodMatcherPointcutAdvisor + * 实现StaticMethodMatcherPointcutAdvisor接口唯一需要定义的是matches()方法, + * + */ +public class CarAdvisor2 extends StaticMethodMatcherPointcutAdvisor{ + + /** + * 切点方法 匹配 + * 匹配规则:方法名为driving + * 默认情况下,匹配所有的类 + */ + @Override + public boolean matches(Method method, Class clazz) { + return "driving".equals(method.getName()); + } + + /** + * 通过覆盖getClassFilter()方法,让它仅匹配BenzCar类及其子类 + */ + @Override + public ClassFilter getClassFilter(){ + return new ClassFilter() { + /** + * 切点类 匹配 + * 匹配规则:为BenzCar类或其子类 + */ + @Override + public boolean matches(Class clazz) { + return Car.class.isAssignableFrom(clazz); + } + }; + } + +} \ No newline at end of file diff --git a/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/aop/DrivingBeforeAdvice.java b/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/aop/DrivingBeforeAdvice.java new file mode 100644 index 00000000..a84f044c --- /dev/null +++ b/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/aop/DrivingBeforeAdvice.java @@ -0,0 +1,18 @@ +package cn.cunchang.aop; + +import java.lang.reflect.Method; +import org.springframework.aop.MethodBeforeAdvice; + +/** + * Driving的前置增强类 + */ +public class DrivingBeforeAdvice implements MethodBeforeAdvice{ + + @Override + public void before(Method method, Object[] args, Object obj) throws Throwable { + //得到切点的信息 + System.out.println("要增强的是:"+obj.getClass()+"类 ---"+method.getName()+"方法"); + System.out.println("【前置增强】做好行驶前的准备工作..."); + } + +} \ No newline at end of file diff --git a/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/aop/DrivingInterceptor.java b/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/aop/DrivingInterceptor.java new file mode 100644 index 00000000..05614d36 --- /dev/null +++ b/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/aop/DrivingInterceptor.java @@ -0,0 +1,30 @@ +package cn.cunchang.aop; + +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +import org.springframework.aop.MethodBeforeAdvice; +import org.springframework.aop.aspectj.AspectJAroundAdvice; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +import java.lang.reflect.Method; + +/** + * Driving的方法拦截器 + */ + +public class DrivingInterceptor implements MethodInterceptor{ + + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { + Object result = null; + + System.out.println("车辆放行前..."); + result= invocation.proceed(); + System.out.println("车辆放行后..."); + + return result; + } + +} \ No newline at end of file diff --git a/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/domain/BenzCar.java b/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/domain/BenzCar.java new file mode 100644 index 00000000..a3c361e1 --- /dev/null +++ b/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/domain/BenzCar.java @@ -0,0 +1,10 @@ +package cn.cunchang.domain; + +public class BenzCar implements Car{ + + @Override + public void driving() { + System.out.println("奔驰车在行驶..."); + } + +} \ No newline at end of file diff --git a/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/domain/BmwCar.java b/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/domain/BmwCar.java new file mode 100644 index 00000000..f6af10e7 --- /dev/null +++ b/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/domain/BmwCar.java @@ -0,0 +1,10 @@ +package cn.cunchang.domain; + +public class BmwCar implements Car{ + + @Override + public void driving(){ + System.out.println("五菱宏光在行驶..."); + } + +} \ No newline at end of file diff --git a/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/domain/Car.java b/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/domain/Car.java new file mode 100644 index 00000000..6bf57ea2 --- /dev/null +++ b/spring-annotation/aop-schema-based/src/main/java/cn/cunchang/domain/Car.java @@ -0,0 +1,11 @@ +package cn.cunchang.domain; + +/** + * @author cunchang + * @date 2021/8/29 11:21 上午 + */ +public interface Car { + + public void driving(); + +} diff --git a/spring-annotation/aop-schema-based/src/main/resources/aop-low-api.xml b/spring-annotation/aop-schema-based/src/main/resources/aop-low-api.xml new file mode 100644 index 00000000..c0abd1fe --- /dev/null +++ b/spring-annotation/aop-schema-based/src/main/resources/aop-low-api.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-annotation/aop-schema-based/src/test/java/cn/lastwhisper/aop/test/AOP_LowApiTest.java b/spring-annotation/aop-schema-based/src/test/java/cn/lastwhisper/aop/test/AOP_LowApiTest.java new file mode 100644 index 00000000..aba84379 --- /dev/null +++ b/spring-annotation/aop-schema-based/src/test/java/cn/lastwhisper/aop/test/AOP_LowApiTest.java @@ -0,0 +1,26 @@ +package cn.lastwhisper.aop.test; + +import cn.cunchang.domain.BmwCar; +import cn.cunchang.domain.BenzCar; +import org.junit.Test; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @author lastwhisper + */ +public class AOP_LowApiTest { + + @Test + public void test01() { + ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("aop-low-api.xml"); + + BenzCar benz = (BenzCar) applicationContext.getBean("benz"); + BmwCar bmw = (BmwCar) applicationContext.getBean("bmw"); + + benz.driving(); //奔驰车的driving方法 + System.out.println("==========================="); + bmw.driving(); //宝马车的driving方法 + + } + +} diff --git a/spring-annotation/aop/pom.xml b/spring-annotation/aop/pom.xml deleted file mode 100644 index 8441c70c..00000000 --- a/spring-annotation/aop/pom.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - spring-annotation - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - aop - - - - - org.springframework - spring-aspects - 4.3.12.RELEASE - - - - \ No newline at end of file diff --git a/spring-annotation/aop/src/main/java/cn/lastwhisper/aop/config/MainConfigOfAop.java b/spring-annotation/aop/src/main/java/cn/lastwhisper/aop/config/MainConfigOfAop.java deleted file mode 100644 index b24eaf7a..00000000 --- a/spring-annotation/aop/src/main/java/cn/lastwhisper/aop/config/MainConfigOfAop.java +++ /dev/null @@ -1,171 +0,0 @@ -package cn.lastwhisper.aop.config; - -import cn.lastwhisper.aop.LogAspects; -import cn.lastwhisper.aop.MathCalculator; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.EnableAspectJAutoProxy; - -/** - * AOP:面向切面编程,指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式。 - * - * 1)导入AOP依赖:spring-aspects - * 2)准备一个业务处理类(MathCalculator):在业务处理时将日志进行打印(方法执行前、方法执行后、方法出现异常时...) - * 3)准备一个日志切面类(LogAspects):在业务处理类运行的不同时期执行不同的通知 - * 通知方法: - * (1)前置通知(@Before):logStart,在目标方法(div)执行之前运行 - * (2)后置通知(@After):logEnd,在目标方法(div)执行之后运行 - * (3)返回通知(@AfterReturning):logReturn,在目标方法(div)执行返回之后运行 - * (4)异常通知(@AfterThrowing):logException,在目标方法(div)执行时出现异常之后运行 - * (5)环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced()) - * 4)通知注解:给切面类的方法标注何时运行(@Before、@After...) - * 5)将业务处理类和日志切面类都加入到容器中,并告诉Spring那个是切面类(@Aspect) - * 6)给配置类中加 @EnableAspectJAutoProxy(开启基于注解的aop模式) - * - * AOP原理:看给容器中注册了什么组件,这个组件什么时候工作,这个组件的功能是什么? - * 1)@EnableAspectJAutoProxy注解的功能 - * 导入组件@Import(AspectJAutoProxyRegistrar.class) - * AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口 - * 利用AspectJAutoProxyRegistrar自定义给容器注册bean - * internalAutoProxyCreator=AnnotationAwareAspectJAutoProxyCreator - * 给容器中注册了一个AnnotationAwareAspectJAutoProxyCreator组件 - * - * 2)AnnotationAwareAspectJAutoProxyCreator - * AnnotationAwareAspectJAutoProxyCreator - * ——》父类 AspectJAwareAdvisorAutoProxyCreator - * ——》父类 AbstractAdvisorAutoProxyCreator - * ——》父类 AbstractAutoProxyCreator - * ——》implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware - * 关注后置处理器(在bean初始化完成前后做事情)、自动装配BeanFactory - * - * 设置断点 - * AbstractAutoProxyCreator.setBeanFactory(BeanFactoryAware) - * AbstractAutoProxyCreator.postProcessAfterInitialization、postProcessBeforeInstantiation等有后置处理器的逻辑 - * - * AbstractAdvisorAutoProxyCreator.setBeanFactory()——》initBeanFactory - * - * AnnotationAwareAspectJAutoProxyCreator.initBeanFactory - * - * 3)AnnotationAwareAspectJAutoProxyCreator创建和注册的过程 - * 1)传入配置类,创建IOC容器 - * 2)注册配置类,AbstractApplicationContext.refresh()刷新容器 - * 3)PostProcessorRegistrationDelegate.registerBeanPostProcessors:注册bean的后置处理器来方便拦截bean的创建 - * *注册bean的后置处理器的流程: - * 1)获取IOC容器中已经定义的需要创建对象的所有BeanPostProcessor - * 2)给容器中加入别的BeanPostProcessor - * 3)分离BeanPostProcessor,分别注册BeanPostProcessor - * 1.First, register the BeanPostProcessors that implement PriorityOrdered - * 2.Next, register the BeanPostProcessors that implement Ordered. - * 3.Now, register all regular BeanPostProcessors. - * 4)注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,保存在容器中——————————————创建 - * 由于AnnotationAwareAspectJAutoProxyCreator实现了Ordered与xxxBeanPostProcessor接口在(3)的2步骤开始注册 - * *AnnotationAwareAspectJAutoProxyCreator注册流程(AbstractAutowireCapableBeanFactory.doCreateBean()) - * 1.创建internalAutoProxyCreator的BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)实例 - * internalAutoProxyCreator——》instanceWrapper = createBeanInstance(beanName, mbd, args) - * AnnotationAwareAspectJAutoProxyCreator——》final Object bean = instanceWrapper.getWrappedInstance() - * 2.populateBean:给bean的属性赋值 - * 3.initializeBean:初始化bean - * *初始化bean的流程: - * 1.invokeAwareMethods:处理Aware接口的回调 - * 2.applyBeanPostProcessorsBeforeInitialization:后置处理器的Before调用 - * 3.invokeInitMethods:执行初始化方法 - * 4.applyBeanPostProcessorsAfterInitialization:后置处理器的After调用 - * 4. BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功 - * AnnotationAwareAspectJAutoProxyCreator调用父类的setBeanFactory(AbstractAdvisorAutoProxyCreator.setBeanFactory) - * 父类的setBeanFactory调用自身的initBeanFactory - * 5)把BeanPostProcessor注册到BeanFactory中(beanFactory.addBeanPostProcessor(postProcessor))——————————————注册 - * =======以上是创建和注册AnnotationAwareAspectJAutoProxyCreator的过程======== - * - * AnnotationAwareAspectJAutoProxyCreator的后置处理器类型:InstantiationAwareBeanPostProcessor - * 4)finishBeanFactoryInitialization(beanFactory):完成BeanFactory初始化,创建剩下的单实例bean - * 1)遍历获取容器中的所有的Bean,依次创建对象getBean(beanName); - * getBean——》doGetBean——》getSingleton - * 2)创建bean - * 1)先从缓存中检查手动注册的单例对象 - * AbstractBeanFactory.doGetBean——》Object sharedInstance = getSingleton(beanName); - * 2)createBean创建Bean - * [BeanPostProcessor在Bean实例创建前后调用] - * [InstantiationAwareBeanPostProcessor在Bean实例创建前先获取代理对象]//AnnotationAwareAspectJAutoProxyCreator - * 1)、resolveBeforeInstantiation解析BeforeInstantiation,创建代理对象 - * bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);//InstantiationAwareBeanPostProcessor - * if (bean != null) { - * bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); - * } - * 2)、doCreateBean(3.4流程),创建普通对象 - * - * 5)AnnotationAwareAspectJAutoProxyCreator[InstantiationAwareBeanPostProcessor]的作用: - * 1)Bean创建之前,调用postProcessBeforeInstantiation() - * 关注mathCalculator、LogAspects创建 - * 1)判断当前Bean是否在advisedBeans(保存了所有需要增强的Bean)中 - * 2)判断当前Bean是否是基础类(Advice、Pointcut、Advisor、AopInfrastructureBean)或者是切面(Aspect) - * 3)是否需要跳过 - * 1)拿到候选的增强器[List candidateAdvisors],InstantiationModelAwarePointcutAdvisorImpl - * 如果是AspectJPointcutAdvisor返回true - * 2)返回false - * 2)、Bean创建之后,调用postProcessAfterInitialization() - * wrapIfNecessary方法会创建代理对象,返回给spring: - * 1)、getAdvicesAndAdvisorsForBean获取当前Bean可应用的通知方法 - * 关注findEligibleAdvisors - * 1)、找到候选的所有通知方法 - * 2)、获取当前Bean可应用的通知方法 - * 3)、对通知方法进行排序 - * 2)、保存当前Bean到advisedBeans中 - * 3)、createProxy如果当前Bean需要增强,创建当前Bean的代理对象 - * 1)、将通知方法保存到proxyFactory - * 2)、创建代理对象 - * JdkDynamicAopProxy - * ObjenesisCglibAopProxy - * 3)、以后从容器中获取到的就是这个Bean的代理对象,执行目标方法的时候,代理对象会执行通知方法 - * - * 6)目标方法执行时的拦截器链(将每一个通知方法包装成拦截器) - * 1)、CglibAopProxy.intercept()拦截目标方法执行 - * 2)、根据ProxyFactory获取将要执行的目标方法拦截器链 - * this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass) - * 1)、创建interceptorList保存拦截器链 - * 2)、遍历所有通知方法,转成Interceptor - * registry.getInterceptors(advisor)的逻辑 - * 如果是MethodInterceptor直接加入集合 - * 如果不是,使用AdvisorAdapter将通知方法转为MethodInterceptor加入集合 - * 3)、没有拦截器链,执行目标方法 - * 4)、有拦截器链,CglibMethodInvocation.proceed()执行拦截器链 - * 5)、拦截器链的触发过程 - * 1)、如果没有拦截器执行目标方法,或者拦截器的索引等于拦截器数组-1(执行到最后一个拦截器) - * currentInterceptorIndex=-1 - * - * 总结: - * 1)、@EnableAspectJAutoProxy 开启AOP功能 - * 2)、@EnableAspectJAutoProxy 会给容器中注册一个组件AnnotationAwareAspectJAutoProxyCreator - * 3)、AnnotationAwareAspectJAutoProxyCreator是一个后置处理器(InstantiationAwareBeanPostProcessor) - * 4)、容器的创建流程: - * 1)、registerBeanPostProcessors()注册后置处理器,创建AnnotationAwareAspectJAutoProxyCreator - * 2)、finishBeanFactoryInitialization()初始化剩下的单实例Bean - * 1)、创建业务逻辑组件和切面组件 - * 2)、resolveBeforeInstantiation->wrapIfNecessary - * 给业务组件创建代理类,将通知方法包装成增强器(Advisor) - * 5)、执行目标方法 - * 1)、代理类执行目标方法 - * 2)、CglibAopProxy.intercept()拦截方法的执行 - * 1)、将目标方法的增强器拦(Advisor),包装成截器链(MethodInterceptor) - * 2)、利用拦截器的链式机制,依次进入每个拦截器执行 - * 3)、效果: - * 正常执行:前置通知-》目标方法-》后置通知-》返回通知 - * 异常执行:前置通知-》目标方法-》后置通知-》异常通知 - * - * - * - * @author lastwhisper - */ -@EnableAspectJAutoProxy // 开启基于注解的aop模式 -@Configuration -public class MainConfigOfAop { - - @Bean - public MathCalculator mathCalculator() { - return new MathCalculator(); - } - - @Bean - public LogAspects logAspects() { - return new LogAspects(); - } -} diff --git a/spring-annotation/aop/src/test/java/cn/lastwhisper/aop/test/IOCTest_AOP.java b/spring-annotation/aop/src/test/java/cn/lastwhisper/aop/test/IOCTest_AOP.java deleted file mode 100644 index 89bfc753..00000000 --- a/spring-annotation/aop/src/test/java/cn/lastwhisper/aop/test/IOCTest_AOP.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.lastwhisper.aop.test; - -import cn.lastwhisper.aop.MathCalculator; -import cn.lastwhisper.aop.config.MainConfigOfAop; -import org.junit.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; - -/** - * @author lastwhisper - */ -public class IOCTest_AOP { - - @Test - public void test01() { - AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAop.class); - - MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class); - mathCalculator.div(2, 1); - - - } - -} diff --git a/spring-annotation/autowired/pom.xml b/spring-annotation/autowired/pom.xml index da57b039..38f3d623 100644 --- a/spring-annotation/autowired/pom.xml +++ b/spring-annotation/autowired/pom.xml @@ -2,22 +2,34 @@ - - spring-annotation - cn.lastwhisper - 1.0-SNAPSHOT - + 4.0.0 cn.lastwhisper autowired + 1.0-SNAPSHOT + + + org.springframework + spring-context + 4.3.12.RELEASE + + + + junit + junit + 4.12 + test + + javax.inject javax.inject 1 + \ No newline at end of file diff --git a/spring-annotation/componentregister/pom.xml b/spring-annotation/componentregister/pom.xml index dd88a86d..6a75993c 100644 --- a/spring-annotation/componentregister/pom.xml +++ b/spring-annotation/componentregister/pom.xml @@ -2,15 +2,26 @@ - - spring-annotation - cn.lastwhisper - 1.0-SNAPSHOT - + 4.0.0 cn.lastwhisper componentregister + 1.0-SNAPSHOT + + + + + org.springframework + spring-context + 4.3.12.RELEASE + + + junit + junit + 4.12 + + \ No newline at end of file diff --git a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/MainTest.java b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/MainTest.java index 2bfa5024..4ab18524 100644 --- a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/MainTest.java +++ b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/MainTest.java @@ -1,25 +1,40 @@ package cn.lastwhisper.componentregister; import cn.lastwhisper.componentregister.bean.Person; -import cn.lastwhisper.componentregister.config.MainConfig; +import cn.lastwhisper.componentregister.config.MainConfigScan; +import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainTest { - public static void main(String[] args) { - // 1.读取xml - //ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Bean.xml"); - //Person person = (Person) applicationContext.getBean("person"); - //System.out.println(person); + + /** + * 测试读取配置类 + */ + @Test + public void test2(){ // 2.读取配置类 - ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class); + ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigScan.class); Person person = applicationContext.getBean(Person.class); System.out.println(person); + // 找到Person Bean组件的名字 String[] namesForType = applicationContext.getBeanNamesForType(Person.class); - for (int i = 0; i < namesForType.length; i++) { - String s = namesForType[i]; + for (String s : namesForType) { System.out.println(s); } } + + /** + * 测试读取配置文件 + */ + @Test + public void test1(){ + // 1.读取xml + ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Bean.xml"); + Person person = (Person) applicationContext.getBean("person"); + System.out.println(person); + } + } \ No newline at end of file diff --git a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/bean/ColorFactoryBean.java b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/bean/ColorFactoryBean.java index 4375c3b2..9c12b143 100644 --- a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/bean/ColorFactoryBean.java +++ b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/bean/ColorFactoryBean.java @@ -3,6 +3,10 @@ import org.springframework.beans.factory.FactoryBean; /** + * FactoryBean有啥用? + * 与其他框架进行整合 + * + * * @author lastwhisper */ public class ColorFactoryBean implements FactoryBean { @@ -11,7 +15,7 @@ public class ColorFactoryBean implements FactoryBean { */ @Override public Color getObject() throws Exception { - System.out.println("ColorFactoryBean.getObject"); + System.out.println("ColorFactoryBean.getObject方法执行"); return new Color(); } diff --git a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/condition/MacCondition.java b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/condition/MacCondition.java new file mode 100644 index 00000000..0da1f4a6 --- /dev/null +++ b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/condition/MacCondition.java @@ -0,0 +1,49 @@ +package cn.lastwhisper.componentregister.condition; + +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.env.Environment; +import org.springframework.core.type.AnnotatedTypeMetadata; + +/** + * bean加载条件 + * @author lastwhisper + */ +public class MacCondition implements Condition { + /** + * 匹配mac操作系统 + * + * @param context 上下文 + * @param metadata 注解信息 + * @return boolean + */ + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + // 获取到的是app classLoader,跟this获取的一样啊,好奇怪,有什么用呢? + ClassLoader appClassLoader = context.getClassLoader(); + ClassLoader classLoader = this.getClass().getClassLoader(); + + // ioc BeanFactory + ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); + // BeanDefinitionRegistry增删改查Bean注册信息 + BeanDefinitionRegistry registry = context.getRegistry(); + + // 获取运行时环境 + Environment environment = context.getEnvironment(); + // 获取操作系统 + String property = environment.getProperty("os.name"); + + if (property.toLowerCase().contains("mac os x")) { + return true; + } + return false; + } + + + public static void main(String[] args) { + System.out.println(System.getProperty("os.name").toLowerCase()); + } + +} diff --git a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/condition/WindowsCondition.java b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/condition/WindowsCondition.java index e99779cd..60df75ef 100644 --- a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/condition/WindowsCondition.java +++ b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/condition/WindowsCondition.java @@ -32,4 +32,6 @@ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) } return false; } + + } diff --git a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/config/MainConfig.java b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/config/MainConfig.java deleted file mode 100644 index 76a8a7f4..00000000 --- a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/config/MainConfig.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.lastwhisper.componentregister.config; - -import cn.lastwhisper.componentregister.bean.Person; -import cn.lastwhisper.componentregister.filter.MyTypeFilter; -import cn.lastwhisper.componentregister.service.BookService; -import org.springframework.context.annotation.*; -import org.springframework.stereotype.Controller; - -/** - * 配置类相当于是配置文件 - * @author lastwhisper - */ -//@Configuration // 告诉Spring这是一个配置类 -/* - * 注解@ComponentScan对应 - * - * excludeFilters = Filter[];指定在扫描的时候按照什么规则来排除脑哪些组件 - * includeFilters = Filter[];指定在扫描的时候,只需要包含哪些组件 - * 想让包扫描的filter生效,必须声明useDefaultFilters = false - */ -@ComponentScans(value = { - @ComponentScan(value = "cn.lastwhisper", includeFilters = { - // 这里面是一个@Filter注解数组,FilterType.ANNOTATION表示的排除的规则 :按照注解来进行匹配 - // classes = {Controller.class}表示的是标有这些注解的类给纳入到IOC容器中 - @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}), - // FilterType.ASSIGNABLE_TYPE 按照给定类型进行匹配 - //@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {BookService.class}), - // FilterType.ASPECTJ 表达式 - // FilterType.REGEX 正则表达式 - // FilterType.CUSTOM 自定义过滤规则 - @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class}) - }, useDefaultFilters = false), - @ComponentScan(value = "cn.lastwhisper", excludeFilters = { - // FilterType.ASSIGNABLE_TYPE 按照给定类型进行匹配 - @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {BookService.class}), - }, useDefaultFilters = false) -}) -public class MainConfig { - /** - * 在Spring的IOC容器中,默认名称为:person222,如果设置Bean的value值,则按value值 - * 给容器中注册一个Bean - */ - @Bean("personName") - public Person person222() { - return new Person("lastwhisper", 21); - } -} diff --git a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/config/MainConfig2.java b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/config/MainConfig2.java deleted file mode 100644 index e84641c0..00000000 --- a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/config/MainConfig2.java +++ /dev/null @@ -1,85 +0,0 @@ -package cn.lastwhisper.componentregister.config; - -import cn.lastwhisper.componentregister.bean.Color; -import cn.lastwhisper.componentregister.bean.ColorFactoryBean; -import cn.lastwhisper.componentregister.bean.Person; -import cn.lastwhisper.componentregister.bean.Red; -import cn.lastwhisper.componentregister.condition.LinuxCondition; -import cn.lastwhisper.componentregister.condition.WindowsCondition; -import cn.lastwhisper.componentregister.filter.MyTypeFilter; -import cn.lastwhisper.componentregister.register.MyImportBeanDefinitionRegistrar; -import cn.lastwhisper.componentregister.selector.MyImportSelector; -import org.springframework.context.annotation.*; - -/** - * @author lastwhisper - */ - -@Configuration -@ComponentScan(excludeFilters = { - @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class}) -}) -//@Conditional({WindowsCondition.class}) -@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class}) -public class MainConfig2 { - /** - * Scope取值:prototype、singleton、request、session。默认是singleton - * prototype:多实例,IOC容器启动时并不会创建对象,只有获取时才会创建。懒加载 - * singleton:单实例,IOC容器启动时创建对象放入IOC容器中。 - * request:一次请求创建一个实例 - * session:一个session创建一个实例 - * - * 懒加载:当IOC容器启动时不创建对象,第一次使用时才创建。 - * singleton默认不是懒加载,加上@Lazy变成懒加载。 - */ - @Scope("singleton") - //@Scope("prototype") - //@Lazy - @Bean("person") - public Person person() { - System.out.println("Person对象创建完毕"); - return new Person("tom", 22); - } - - /** - * 注解@Conditional({Condition.class}): 按条件判断,满足条件给容器注册bean - * - * 现在下面的两个bean注册到IOC容器是要条件的: - * 1.如果系统是windows,给容器注册("bill") - * 2.如果系统是linux,给容器注册("linus") - */ - @Conditional({WindowsCondition.class}) - @Bean("bill") - public Person windows() { - return new Person("Bill Gates", 66); - } - - /** - * -Dos.name 变成linux - */ - @Conditional({LinuxCondition.class}) - @Bean("linus") - public Person linux() { - return new Person("linus", 45); - } - - /** - * 给容器中注册组件的几种方式: - * 1)、组件扫描+组件注册注解 @Controller、@Service、@Repository、@Component(自己写的类) - * - * 2)、@Bean(注册第三方包里面的组件,如连接池等) - * 3)、@Import(快速给容器中注册一个组件) - * (1)、@Import(要注册到容器的组件):容器会自动注册这个组件,id是全限定名 - * (2)、ImportSelector:返回需要注册的组件的全限定名 - * (3)、ImportBeanDefinitionRegistrar:手动注册bean到容器 - * - * 4)、使用Spring提供的FactoryBean(工厂bean) - * (1)、默认获取的是getObject返回的对象 - * (2)、要获取FactoryBean本身,我们需要给id前面加上一个“&”符号:&colorFactoryBean - */ - @Bean - public ColorFactoryBean colorFactoryBean() { - return new ColorFactoryBean(); - } - -} diff --git a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/config/MainConfigRegister.java b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/config/MainConfigRegister.java new file mode 100644 index 00000000..f3fd1040 --- /dev/null +++ b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/config/MainConfigRegister.java @@ -0,0 +1,102 @@ +package cn.lastwhisper.componentregister.config; + +import cn.lastwhisper.componentregister.bean.Color; +import cn.lastwhisper.componentregister.bean.ColorFactoryBean; +import cn.lastwhisper.componentregister.bean.Person; +import cn.lastwhisper.componentregister.bean.Red; +import cn.lastwhisper.componentregister.condition.LinuxCondition; +import cn.lastwhisper.componentregister.condition.MacCondition; +import cn.lastwhisper.componentregister.condition.WindowsCondition; +import cn.lastwhisper.componentregister.filter.MyTypeFilter; +import cn.lastwhisper.componentregister.register.MyImportBeanDefinitionRegistrar; +import cn.lastwhisper.componentregister.selector.MyImportSelector; +import org.springframework.context.annotation.*; + +/** + * @author lastwhisper + */ + +//@Configuration +//@ComponentScan(excludeFilters = { +// @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class}) +//}) +@ComponentScan(value = "cn.lastwhisper") +//@Conditional({WindowsCondition.class}) +@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class}) +public class MainConfigRegister { + /** + * Scope取值:prototype、singleton、request、session。默认是singleton + * prototype:多实例,IOC容器启动时并不会创建对象,只有获取时才会创建。懒加载 + * singleton:单实例,IOC容器启动时创建对象放入IOC容器中。 + * request:一次请求创建一个实例(需要web环境) + * session:一个session创建一个实例(需要web环境) + * + * 懒加载:当IOC容器启动时不创建对象,第一次使用时才创建。 + * singleton默认不是懒加载,加上@Lazy变成懒加载。 + * prototype是懒加载 + */ + @Scope("singleton") +// @Scope("prototype") +// @Lazy // 通过初始化容器,查看是否输出"Person对象创建完毕" + @Bean("person") + public Person person() { +// System.out.println("Person对象创建完毕"); + return new Person("tom", 22); + } + + /** + * 注解@Conditional({Condition.class}): 按条件判断,满足条件给容器注册bean + * + * System.out.println(System.getProperty("os.name").toLowerCase()); + * + * 现在下面的两个bean注册到IOC容器是要条件的: + * 1.如果系统是windows,给容器注册("bill") + * 2.如果系统是linux,给容器注册("linus") + * 3.如果系统是mac,给容器注册("jobs") + */ + @Conditional({WindowsCondition.class}) + @Bean("bill") + public Person windows() { + return new Person("Bill Gates", 66); + } + + /** + * -Dos.name 变成linux + */ + @Conditional({LinuxCondition.class}) + @Bean("linus") + public Person linux() { + return new Person("linus", 45); + } + + + @Conditional({MacCondition.class}) + @Bean("jobs") + public Person jobs() { + return new Person("Steve Jobs", 45); + } + + /** + * 给容器中注册组件的几种方式: + * 1)、组件扫描+组件注册注解 @Controller、@Service、@Repository、@Component(自己写的类) + * + * 2)、@Bean(应用场景:注册第三方包里面的组件,如连接池等) + * + * 3)、@Import(快速给容器中注册一个组件;应用场景:注册第三方包里面的组件,如连接池等) + * (1)、@Import(要注册到容器的组件):容器会自动注册这个组件,id是全限定名 + * (2)、ImportSelector:返回需要注册的组件的全限定名 + * (3)、ImportBeanDefinitionRegistrar:手动注册bean到容器 + * + * 4)、使用Spring提供的FactoryBean(应用场景:与其他框架整合使用,比如mybatis的SqlSessionFactoryBean) + * Spring 中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean 即 FactoryBean + * (1)、默认获取的是getObject返回的对象 + * (2)、要获取FactoryBean本身,我们需要给id前面加上一个“&”符号:&colorFactoryBean + * + * + */ + @Bean + public ColorFactoryBean colorFactoryBean() { + return new ColorFactoryBean(); + } + +} diff --git a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/config/MainConfigScan.java b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/config/MainConfigScan.java new file mode 100644 index 00000000..b56ef71c --- /dev/null +++ b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/config/MainConfigScan.java @@ -0,0 +1,55 @@ +package cn.lastwhisper.componentregister.config; + +import cn.lastwhisper.componentregister.bean.Person; +import cn.lastwhisper.componentregister.filter.MyTypeFilter; +import cn.lastwhisper.componentregister.service.BookService; +import org.springframework.context.annotation.*; +import org.springframework.stereotype.Controller; + +/** + * 配置类相当于是配置文件 + * @author lastwhisper + */ +@Configuration // 告诉Spring这是一个配置类 +@ComponentScans(value = { + @ComponentScan( + value = "cn.lastwhisper", + includeFilters = { + // 这里面是一个@Filter注解数组,FilterType.ANNOTATION表示的排除的规则 :按照注解来进行匹配 + // classes = {Controller.class}表示的是标有这些注解的类给纳入到IOC容器中 + @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}), + // FilterType.ASSIGNABLE_TYPE 按照给定类型进行匹配 +// @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {BookService.class}), + // FilterType.ASPECTJ 表达式 + // FilterType.REGEX 正则表达式 + // FilterType.CUSTOM 自定义过滤规则 +// @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class}) + }, + // useDefaultFilters = true默认include @Controller、@Service、@Repository、@Component + useDefaultFilters = false), + @ComponentScan( + value = "cn.lastwhisper", + excludeFilters = { + // FilterType.ASSIGNABLE_TYPE 按照给定类型进行匹配 +// @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {BookService.class}), + }, + useDefaultFilters = false) +}) +/* + * 注解@ComponentScan对应 + * + * excludeFilters = Filter[];指定在扫描的时候按照什么规则来排除脑哪些组件 + * includeFilters = Filter[];指定在扫描的时候,只需要包含哪些组件,想让包扫描的includeFilters生效,必须声明useDefaultFilters = false + * + * @ComponentScan在jdk8是可重复声明注解,不是jdk8,可以使用@ComponentScans进行重复声明 + */ +public class MainConfigScan { + /** + * 在Spring的IOC容器中,默认名称为:person222,如果设置Bean的value值,则按value值 + * 给容器中注册一个Bean + */ + @Bean("personName") + public Person person222() { + return new Person("lastwhisper", 21); + } +} diff --git a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/controller/BookController.java b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/controller/BookController.java index 2bd334cd..5b079626 100644 --- a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/controller/BookController.java +++ b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/controller/BookController.java @@ -1,7 +1,15 @@ package cn.lastwhisper.componentregister.controller; +import cn.lastwhisper.componentregister.bean.Red; +import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Controller; @Controller public class BookController { + + @Bean("myRed") + public Red red(){ + return new Red(); + } + } diff --git a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/filter/MyTypeFilter.java b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/filter/MyTypeFilter.java index 84253aa5..b8576fd9 100644 --- a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/filter/MyTypeFilter.java +++ b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/filter/MyTypeFilter.java @@ -1,6 +1,5 @@ package cn.lastwhisper.componentregister.filter; -import org.springframework.context.annotation.Conditional; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.ClassMetadata; import org.springframework.core.type.classreading.MetadataReader; @@ -8,7 +7,6 @@ import org.springframework.core.type.filter.TypeFilter; import java.io.IOException; -import java.lang.annotation.Annotation; /** * 自定义ComponentScan过滤器 @@ -31,7 +29,7 @@ public boolean match(MetadataReader metadataReader, MetadataReaderFactory metada ClassMetadata classMetadata = metadataReader.getClassMetadata(); // 获取类名 String className = classMetadata.getClassName(); - System.out.println("扫描的类——》" + className); + System.out.println(this.getClass().getSimpleName()+ " 扫描的类——》" + className); // 根据类名进行过滤 if (className.contains("Book")) { return true; diff --git a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/register/MyImportBeanDefinitionRegistrar.java b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/register/MyImportBeanDefinitionRegistrar.java index 73903e4e..31a66b4e 100644 --- a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/register/MyImportBeanDefinitionRegistrar.java +++ b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/register/MyImportBeanDefinitionRegistrar.java @@ -10,10 +10,11 @@ * @author lastwhisper */ public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { + /** - * 把所有需要添加到容器中的bean通过BeanDefinitionRegistry里面的registerBeanDefinition方法来手动的进行注册 + * 把所有需要添加到容器中的bean,通过BeanDefinitionRegistry来手动的进行注册 * - * @param importingClassMetadata 当前类的注解信息 + * @param importingClassMetadata 使用MyImportSelector类的所有注解(MainConfigRegister类的注解) * @param registry BeanDefinition注册类 * @return void */ diff --git a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/selector/MyImportSelector.java b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/selector/MyImportSelector.java index 760f6c85..61d23def 100644 --- a/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/selector/MyImportSelector.java +++ b/spring-annotation/componentregister/src/main/java/cn/lastwhisper/componentregister/selector/MyImportSelector.java @@ -8,13 +8,15 @@ * @author lastwhisper */ public class MyImportSelector implements ImportSelector { + /** * - * @param importingClassMetadata 使用MyImportSelector类的所有注解 + * @param importingClassMetadata 使用MyImportSelector类的所有注解(MainConfigRegister类的注解) * @return java.lang.String[] 导入组件的全类名 */ @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{"cn.lastwhisper.componentregister.bean.Blue", "cn.lastwhisper.componentregister.bean.Yellow"}; } + } diff --git a/spring-annotation/componentregister/src/main/resources/Bean.xml b/spring-annotation/componentregister/src/main/resources/Bean.xml index 22ed7326..094df6b9 100644 --- a/spring-annotation/componentregister/src/main/resources/Bean.xml +++ b/spring-annotation/componentregister/src/main/resources/Bean.xml @@ -5,17 +5,19 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> - - - - - + + + + + + + diff --git a/spring-annotation/componentregister/src/test/java/cn/lastwhisper/componentregister/test/IOCTest.java b/spring-annotation/componentregister/src/test/java/cn/lastwhisper/componentregister/test/IOCTest.java index 9f2c669d..76ead8aa 100644 --- a/spring-annotation/componentregister/src/test/java/cn/lastwhisper/componentregister/test/IOCTest.java +++ b/spring-annotation/componentregister/src/test/java/cn/lastwhisper/componentregister/test/IOCTest.java @@ -1,11 +1,17 @@ package cn.lastwhisper.componentregister.test; -import cn.lastwhisper.componentregister.config.MainConfig; -import cn.lastwhisper.componentregister.config.MainConfig2; +import cn.lastwhisper.componentregister.bean.Blue; +import cn.lastwhisper.componentregister.bean.Person; +import cn.lastwhisper.componentregister.bean.RainBow; +import cn.lastwhisper.componentregister.config.MainConfigScan; +import cn.lastwhisper.componentregister.config.MainConfigRegister; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import java.nio.Buffer; +import java.util.Map; + /** * @author lastwhisper */ @@ -19,8 +25,8 @@ public class IOCTest { */ @Test public void test05() { - ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class); - + ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigRegister.class); + // 获取的是FactoryBean.getObject创建的对象 Object factoryBean = applicationContext.getBean("colorFactoryBean"); Object factoryBean2 = applicationContext.getBean("colorFactoryBean"); System.out.println("bean的类型:" + factoryBean.getClass()); @@ -35,11 +41,12 @@ public void test05() { */ @Test public void test04() { - ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class); + ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigRegister.class); String[] definitionNames = applicationContext.getBeanDefinitionNames(); for (String name : definitionNames) { System.out.println(name); } + System.out.println(applicationContext.getBean(RainBow.class)); } /** @@ -50,10 +57,14 @@ public void test04() { */ @Test public void test03() { - ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class); - String[] definitionNames = applicationContext.getBeanDefinitionNames(); - for (String name : definitionNames) { - System.out.println(name); + AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigRegister.class); +// String[] definitionNames = applicationContext.getBeanDefinitionNames(); +// for (String name : definitionNames) { +// System.out.println(name); +// } + Map personMap = applicationContext.getBeansOfType(Person.class); + for (Map.Entry entry : personMap.entrySet()) { + System.out.println(entry); } } @@ -62,11 +73,11 @@ public void test03() { */ @Test public void test02() { - ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class); + ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigRegister.class); System.out.println("IOC容器启动完毕"); - Object person = applicationContext.getBean("person"); - Object person2 = applicationContext.getBean("person"); - System.out.println(person == person2 ? "单实例" : "多实例"); +// Object person = applicationContext.getBean("person"); +// Object person2 = applicationContext.getBean("person"); +// System.out.println(person == person2 ? "单实例" : "多实例"); } /** @@ -77,10 +88,10 @@ public void test02() { */ @Test public void test01() { - ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class); + ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigScan.class); String[] definitionNames = applicationContext.getBeanDefinitionNames(); for (String name : definitionNames) { - System.out.println(name); + System.out.printf("definitionName:%s\n",name); } } diff --git a/spring-annotation/event/pom.xml b/spring-annotation/event/pom.xml new file mode 100644 index 00000000..07ff4095 --- /dev/null +++ b/spring-annotation/event/pom.xml @@ -0,0 +1,28 @@ + + + + 4.0.0 + + event + cn.lastwhisper + 1.0-SNAPSHOT + + + + + org.springframework + spring-context + 4.3.12.RELEASE + + + + junit + junit + 4.12 + test + + + + \ No newline at end of file diff --git a/spring-annotation/event/src/main/java/cn/lastwhisper/spring/event/BlackListEvent.java b/spring-annotation/event/src/main/java/cn/lastwhisper/spring/event/BlackListEvent.java new file mode 100644 index 00000000..45b4660c --- /dev/null +++ b/spring-annotation/event/src/main/java/cn/lastwhisper/spring/event/BlackListEvent.java @@ -0,0 +1,36 @@ +package cn.lastwhisper.spring.event; + +import org.springframework.context.ApplicationEvent; + +/** + * 事件体 + */ +public class BlackListEvent extends ApplicationEvent { + + private final String address; + private final String content; + + public BlackListEvent(Object source, String address, String content) { + super(source); + this.address = address; + this.content = content; + } + + // accessor and other methods... + + public String getAddress() { + return address; + } + + public String getContent() { + return content; + } + + @Override + public String toString() { + return "BlackListEvent{" + + "address='" + address + '\'' + + ", content='" + content + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/spring-annotation/event/src/main/java/cn/lastwhisper/spring/event/BlackListNotifier.java b/spring-annotation/event/src/main/java/cn/lastwhisper/spring/event/BlackListNotifier.java new file mode 100644 index 00000000..5ec70e19 --- /dev/null +++ b/spring-annotation/event/src/main/java/cn/lastwhisper/spring/event/BlackListNotifier.java @@ -0,0 +1,21 @@ +package cn.lastwhisper.spring.event; + +import org.springframework.context.event.EventListener; + +/** + * 事件接收者 + */ +public class BlackListNotifier { + + private String notificationAddress; + + public void setNotificationAddress(String notificationAddress) { + this.notificationAddress = notificationAddress; + } + + @EventListener + public void processBlackListEvent(BlackListEvent event) { + System.out.println("接收到消息:" + event); + // notify appropriate parties via notificationAddress... + } +} \ No newline at end of file diff --git a/spring-annotation/event/src/main/java/cn/lastwhisper/spring/event/EmailService.java b/spring-annotation/event/src/main/java/cn/lastwhisper/spring/event/EmailService.java new file mode 100644 index 00000000..9954611c --- /dev/null +++ b/spring-annotation/event/src/main/java/cn/lastwhisper/spring/event/EmailService.java @@ -0,0 +1,32 @@ +package cn.lastwhisper.spring.event; + +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.ApplicationEventPublisherAware; + +import java.util.List; + +/** + * 事件发送者 + */ +public class EmailService implements ApplicationEventPublisherAware { + + private List blackList; + + private ApplicationEventPublisher publisher; + + public void setBlackList(List blackList) { + this.blackList = blackList; + } + + public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { + this.publisher = publisher; + } + + public void sendEmail(String address, String content) { + if (blackList.contains(address)) { + publisher.publishEvent(new BlackListEvent(this, address, content)); + return; + } + // send email... + } +} \ No newline at end of file diff --git a/spring-annotation/event/src/main/java/cn/lastwhisper/spring/event/EventConfig.java b/spring-annotation/event/src/main/java/cn/lastwhisper/spring/event/EventConfig.java new file mode 100644 index 00000000..e3e3fe49 --- /dev/null +++ b/spring-annotation/event/src/main/java/cn/lastwhisper/spring/event/EventConfig.java @@ -0,0 +1,41 @@ +package cn.lastwhisper.spring.event; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author lastwhisper + * @date 2020/2/18 + */ +@Configuration +@ComponentScan("cn.lastwhisper.spring.event") +public class EventConfig { + + @Bean + public BlackListNotifier blackListNotifier() { + BlackListNotifier blackListNotifier = new BlackListNotifier(); + blackListNotifier.setNotificationAddress("blacklist@example.org"); + return blackListNotifier; + } + + @Bean + public EmailService emailService() { + EmailService emailService = new EmailService(); + emailService.setBlackList(blackList()); + return emailService; + } + + @Bean + public List blackList() { + List blackList = new ArrayList<>(); + blackList.add("known.spammer@example.org"); + blackList.add("known.hacker@example.org"); + blackList.add("john.doe@example.org"); + return blackList; + } + +} diff --git a/spring-annotation/event/src/test/java/cn/lastwhisper/spring/event/IOCTest_Event.java b/spring-annotation/event/src/test/java/cn/lastwhisper/spring/event/IOCTest_Event.java new file mode 100644 index 00000000..b9dd6dec --- /dev/null +++ b/spring-annotation/event/src/test/java/cn/lastwhisper/spring/event/IOCTest_Event.java @@ -0,0 +1,26 @@ +package cn.lastwhisper.spring.event; + +import org.junit.Test; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +/** + * @author lastwhisper + */ +public class IOCTest_Event { + + /** + * 测试Spring事件 + */ + @Test + public void test01() { + AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(EventConfig.class); + System.out.println("容器初始化..."); + EmailService emailService = applicationContext.getBean(EmailService.class); + emailService.sendEmail("john.doe@example.org","hello world"); + emailService.sendEmail("blacklist@example.org","hello world"); + + applicationContext.close(); + } + +} diff --git a/spring-annotation/ext/README.md b/spring-annotation/ext/README.md new file mode 100644 index 00000000..3cc07379 --- /dev/null +++ b/spring-annotation/ext/README.md @@ -0,0 +1,3 @@ +1. event +2. BeanDefinitionRegistryPostProcessor +3. BeanFactoryPostProcessor \ No newline at end of file diff --git a/spring-annotation/ext/pom.xml b/spring-annotation/ext/pom.xml index 8c53710b..a382dcfd 100644 --- a/spring-annotation/ext/pom.xml +++ b/spring-annotation/ext/pom.xml @@ -2,14 +2,26 @@ - - spring-annotation - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 + 4.0.0 + cn.lastwhisper ext + 1.0-SNAPSHOT + + + + + org.springframework + spring-context + 4.3.12.RELEASE + + + junit + junit + 4.12 + test + + \ No newline at end of file diff --git a/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/ExtConfig.java b/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/ExtConfig.java index 44ad37b6..9a8bdbfe 100644 --- a/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/ExtConfig.java +++ b/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/ExtConfig.java @@ -13,12 +13,12 @@ * 在BeanFactory标准初始化之后调用,来定制和修改BeanFactory的内容; * 所有的bean定义(BeanDefinition)已经保存加载到beanFactory,但是bean的实例还未创建 * - * BeanFactoryPostProcessor原理: + * BeanFactoryPostProcessor原理: 先根据BeanFactory找到当前Class的组件id,然后排序,然后根据组件id找到组件对象,然后进行回调 * 1)、ioc容器创建对象 * 2)、invokeBeanFactoryPostProcessors(beanFactory); * 如何找到所有的BeanFactoryPostProcessor并执行他们的方法; * 1)、直接在BeanFactory中找到所有类型是BeanFactoryPostProcessor的组件,并执行他们的方法 - * 2)、在初始化创建其他组件前面执行 + * 2)、在onRefresh() 初始化创建其他组件前面执行 * * 2、BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor * postProcessBeanDefinitionRegistry(); @@ -27,7 +27,7 @@ * 优先于BeanFactoryPostProcessor执行; * 利用BeanDefinitionRegistryPostProcessor给容器中再额外添加一些组件; * - * 原理: + * 原理: 先根据BeanFactory找到当前Class的组件id,然后排序,然后根据组件id找到组件对象,然后进行回调 * 1)、ioc创建对象 * 2)、refresh()-》invokeBeanFactoryPostProcessors(beanFactory); * 3)、从容器中获取到所有的BeanDefinitionRegistryPostProcessor组件。 @@ -53,29 +53,29 @@ * applicationContext.publishEvent(); * * 4、ApplicationListener原理: - * ContextRefreshedEvent、IOCTest_Ext$1[source=我发布的时间]、ContextClosedEvent; + * ContextRefreshedEvent、IOCTest_Ext$1[source=我发布的事件]、ContextClosedEvent; * 1)、ContextRefreshedEvent事件: * 1)、容器创建对象:refresh(); * 2)、finishRefresh();容器刷新完成会发布ContextRefreshedEvent事件 * 3)、publishEvent【事件发布流程】 + * 【事件发布流程】: + * 1)、publishEvent(new ContextRefreshedEvent(this)); + * 1)、获取事件的多播器(派发器):getApplicationEventMulticaster() + * 2)、multicastEvent()派发事件: + * 3)、获取到所有的ApplicationListener; + * for (final ApplicationListener listener : getApplicationListeners(event, type)) { + * 1)、如果有Executor,可以支持使用Executor进行异步派发; + * Executor executor = getTaskExecutor(); + * 2)、否则,同步的方式直接执行listener方法;invokeListener(listener, event); + * 拿到listener回调onApplicationEvent方法; * 2)、自己发布事件; * 3)、容器关闭会发布ContextClosedEvent事件 * - * 【事件发布流程】: - * 3)、publishEvent(new ContextRefreshedEvent(this)); - * 1)、获取事件的多播器(派发器):getApplicationEventMulticaster() - * 2)、multicastEvent派发事件: - * 3)、获取到所有的ApplicationListener; - * for (final ApplicationListener listener : getApplicationListeners(event, type)) { - * 1)、如果有Executor,可以支持使用Executor进行异步派发; - * Executor executor = getTaskExecutor(); - * 2)、否则,同步的方式直接执行listener方法;invokeListener(listener, event); - * 拿到listener回调onApplicationEvent方法; - * - * 【事件多播器(派发器)】: + * + * 【事件多播器(派发器)怎么拿到的?】: * getApplicationEventMulticaster() * 1)、容器创建对象:refresh(); - * 2)、initApplicationEventMulticaster();初始化ApplicationEventMulticaster; + * 2)、初始化派发器:initApplicationEventMulticaster();初始化ApplicationEventMulticaster; * 1)、先去容器中找有没有id=“applicationEventMulticaster”的组件; * 2)、如果没有this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); * 并且加入到容器中,我们就可以在其他组件要派发事件,自动注入这个applicationEventMulticaster; @@ -88,6 +88,10 @@ * //将listener注册到ApplicationEventMulticaster中 * getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); * + * 为什么加上@EventListener注解就可以监听到事件?看注解里面的注释 + * 主要是EventListenerMethodProcessor搞事,在afterSingletonsInstantiated()里面会将支持直接监听的方法, + * 转成ApplicationListenerMethodAdapter,并且adapter记录了监听类(UserService)和方法(listen) + * 事件推送时,会先掉ApplicationListenerMethodAdapter,再反射调用监听类的方法 * 5)、SmartInitializingSingleton 原理:->afterSingletonsInstantiated(); * 1)、ioc容器创建对象并refresh(); * 2)、finishBeanFactoryInitialization(beanFactory);初始化剩下的单实例bean; @@ -95,6 +99,8 @@ * 2)、获取所有创建好的单实例bean,判断是否是SmartInitializingSingleton类型的; * 如果是就调用afterSingletonsInstantiated(); * + * + * * @author lastwhisper * @date 2020/2/18 */ diff --git a/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/MyApplicationListener.java b/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/MyApplicationListener.java index 6dc24e86..f25bf024 100644 --- a/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/MyApplicationListener.java +++ b/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/MyApplicationListener.java @@ -16,4 +16,5 @@ public void onApplicationEvent(ApplicationEvent event) { // TODO Auto-generated method stub System.out.println("收到事件:"+event); } + } \ No newline at end of file diff --git a/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/MyBeanDefinitionRegistryPostProcessor.java b/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/MyBeanDefinitionRegistryPostProcessor.java index cd33bd0c..022e91c9 100644 --- a/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/MyBeanDefinitionRegistryPostProcessor.java +++ b/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/MyBeanDefinitionRegistryPostProcessor.java @@ -2,19 +2,20 @@ import cn.lastwhisper.spring.ext.bean.Blue; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; +import org.springframework.beans.factory.support.*; import org.springframework.stereotype.Component; +import static org.springframework.beans.factory.config.AutowireCapableBeanFactory.AUTOWIRE_BY_NAME; + + @Component public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - // TODO Auto-generated method stub + System.out.println("MyBeanDefinitionRegistryPostProcessor...bean的数量:" + beanFactory.getBeanDefinitionCount()); } @@ -23,11 +24,24 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) */ @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { - // TODO Auto-generated method stub + System.out.println("postProcessBeanDefinitionRegistry...bean的数量:" + registry.getBeanDefinitionCount()); //RootBeanDefinition beanDefinition = new RootBeanDefinition(Blue.class); - AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Blue.class).getBeanDefinition(); - registry.registerBeanDefinition("hello", beanDefinition); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Blue.class); + + //设置属性值 + builder.addPropertyValue("name","i am blue"); + //设置可通过@Autowire注解引用 + builder.setAutowireMode(AUTOWIRE_BY_NAME); + + AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); + +// registry.registerBeanDefinition("hello", beanDefinition); + + // 看springcloud openfeign源码,feign接口怎么在容器中声明的 + BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, Blue.class.getName(), + new String[] { "hello" }); + BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry); } } \ No newline at end of file diff --git a/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/MyBeanFactoryPostProcessor.java b/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/MyBeanFactoryPostProcessor.java index 52306412..4b166bc0 100644 --- a/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/MyBeanFactoryPostProcessor.java +++ b/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/MyBeanFactoryPostProcessor.java @@ -8,7 +8,6 @@ import java.util.Arrays; /** - * * @author lastwhisper * @date 2020/2/18 */ @@ -20,8 +19,9 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) System.out.println("MyBeanFactoryPostProcessor...postProcessBeanFactory..."); int count = beanFactory.getBeanDefinitionCount(); String[] names = beanFactory.getBeanDefinitionNames(); - System.out.println("当前BeanFactory中有" + count + " 个Bean"); - System.out.println(Arrays.asList(names)); + System.out.println("当前BeanFactory中有" + count + " 个Bean。" + " Names:" + Arrays.asList(names)); + + } } \ No newline at end of file diff --git a/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/UserService.java b/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/UserService.java index dc2ff6b0..ca009639 100644 --- a/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/UserService.java +++ b/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/UserService.java @@ -11,9 +11,11 @@ public class UserService { * https://docs.spring.io/spring/docs/5.1.8.RELEASE/spring-framework-reference/core.html#context-functionality-events * 使用@EventListener注解ApplicationListener实现 * + * */ @EventListener(classes = {ApplicationEvent.class}) public void listen(ApplicationEvent event) { System.out.println("UserService。。监听到的事件:" + event); } + } \ No newline at end of file diff --git a/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/bean/Blue.java b/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/bean/Blue.java index 2ed920e1..5e897338 100644 --- a/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/bean/Blue.java +++ b/spring-annotation/ext/src/main/java/cn/lastwhisper/spring/ext/bean/Blue.java @@ -2,7 +2,17 @@ public class Blue { + private String name; + public Blue() { System.out.println("blue...constructor"); } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } } \ No newline at end of file diff --git a/spring-annotation/ext/src/main/resources/note.txt b/spring-annotation/ext/src/main/resources/note.txt index ff45c64d..4f8874ed 100644 --- a/spring-annotation/ext/src/main/resources/note.txt +++ b/spring-annotation/ext/src/main/resources/note.txt @@ -3,26 +3,27 @@ Spring容器的refresh()【创建刷新】; 1)、initPropertySources()初始化一些属性设置;子容器(子类)自定义个性化的属性设置方法; 2)、getEnvironment().validateRequiredProperties();检验属性的合法等 3)、earlyApplicationEvents= new LinkedHashSet();保存容器中的一些早期的事件; -2、obtainFreshBeanFactory();获取BeanFactory; +2、obtainFreshBeanFactory();获取一个初始化的BeanFactory; 1)、refreshBeanFactory();刷新【创建】BeanFactory; 创建了一个this.beanFactory = new DefaultListableBeanFactory(); 设置SerializationId; 2)、getBeanFactory();返回刚才refreshBeanFactory()(GenericApplicationContext)创建的BeanFactory对象; 3)、将创建的BeanFactory【DefaultListableBeanFactory】返回; -3、prepareBeanFactory(beanFactory);BeanFactory的预准备工作(BeanFactory进行一些设置); - 1)、设置BeanFactory的类加载器、支持表达式解析器... +3、prepareBeanFactory(beanFactory);BeanFactory的预准备工作(对BeanFactory进行一些默认设置); + 1)、设置BeanFactory的类加载器、表达式解析器... 2)、添加部分BeanPostProcessor【ApplicationContextAwareProcessor】 - 3)、设置忽略的自动装配的接口EnvironmentAware、EmbeddedValueResolverAware、xxx; ?????????????????????????????????? + 3)、设置忽略的自动装配的接口EnvironmentAware、EmbeddedValueResolverAware; + 接口ASrv,Aimpl实现ASrv,Aimpl忽略自动注入和ASrv中的setter方法入参相同的类 4)、注册可以解析的自动装配;我们能直接在任何组件中自动注入: BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext - 5)、添加部分BeanPostProcessor【ApplicationListenerDetector】 - 6)、添加编译时的AspectJ; - 7)、给BeanFactory中注册一些能用的组件; + 5)、添加ApplicationListener检测后置处理器【ApplicationListenerDetector】, + 6)、添加类加载时期织入后置处理器【LoadTimeWeaverAwareProcessor】, + 7)、给BeanFactory中注册一些默认的组件; environment【ConfigurableEnvironment】、 systemProperties【Map】、 systemEnvironment【Map】 4、postProcessBeanFactory(beanFactory);BeanFactory准备工作完成后进行的后置处理工作; - 1)、子类通过重写这个方法来在BeanFactory创建并预准备完成以后做进一步的设置 + 1)、允许AbstractApplicationContext的子类通过重写这个方法来在BeanFactory创建并预准备完成以后做进一步的设置 ======================以上是BeanFactory的创建及预准备工作================================== 5、invokeBeanFactoryPostProcessors(beanFactory);执行BeanFactoryPostProcessor及其接口的方法; BeanFactoryPostProcessor:BeanFactory的后置处理器。在BeanFactory标准初始化之后执行的; @@ -45,7 +46,7 @@ Spring容器的refresh()【创建刷新】; postProcessor.postProcessBeanFactory() 4)、最后执行没有实现任何优先级或者是顺序接口的BeanFactoryPostProcessor; postProcessor.postProcessBeanFactory() -6、registerBeanPostProcessors(beanFactory);注册BeanPostProcessor(Bean的后置处理器)【 intercept bean creation】 +6、registerBeanPostProcessors(beanFactory);注册BeanPostProcessor拦截bean的创建过程 不同接口类型的BeanPostProcessor;在Bean创建前后的执行时机是不一样的 BeanPostProcessor、 DestructionAwareBeanPostProcessor、 @@ -61,6 +62,10 @@ Spring容器的refresh()【创建刷新】; 5)、最终注册MergedBeanDefinitionPostProcessor; 6)、注册一个ApplicationListenerDetector;来在Bean创建完成后检查是否是ApplicationListener,如果是 applicationContext.addApplicationListener((ApplicationListener) bean); + + 疑惑点 + int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; + 7、initMessageSource();初始化MessageSource组件(做国际化功能,消息绑定,消息解析); 1)、获取BeanFactory 2)、看容器中是否有id为messageSource的,类型是MessageSource的组件 @@ -75,7 +80,7 @@ Spring容器的refresh()【创建刷新】; 3)、如果上一步没有配置;创建一个SimpleApplicationEventMulticaster 4)、将创建的ApplicationEventMulticaster添加到BeanFactory中,以后其他组件直接自动注入 9、onRefresh();留给子容器(子类) - 1、子类重写这个方法,在容器刷新的时候可以自定义逻辑; + 1、bstractApplicationContext的子类重写这个方法,在容器刷新的时候可以自定义逻辑; 10、registerListeners();给容器中将所有项目里面的ApplicationListener注册进来; 1、从容器中拿到所有的ApplicationListener 2、将每个监听器添加到事件派发器中; @@ -87,20 +92,21 @@ Spring容器的refresh()【创建刷新】; // Trigger initialization of all non-lazy singleton beans... 1)、获取容器中的所有Bean,依次进行初始化和创建对象 2)、获取Bean的定义信息;RootBeanDefinition - 3)、Bean不是抽象的,是单实例的,是懒加载; + 3)、Bean不是抽象的,是单实例的,不是懒加载; 1)、判断是否实现FactoryBean接口,利用getObject创建对象 2)、不是FactoryBean,利用getBean(beanName)创建对象 + 使用条件断点beanName.equals("blue") 0、getBean(beanName); ioc.getBean(); 1、doGetBean(name, null, null, false); 2、先获取缓存中保存的单实例Bean。如果能获取到说明这个Bean之前被创建过(所有创建过的单实例Bean都会被缓存起来) 从private final Map singletonObjects = new ConcurrentHashMap(256);获取的 3、缓存中获取不到,开始Bean的创建对象流程; - 4、标记当前bean已经被创建(markBeanAsCreated(beanName)) + 4、标记当前bean已经被创建(markBeanAsCreated(beanName)),帮助BeanFactory优化其缓存,以重复创建指定的Bean 5、获取Bean的定义信息(getMergedLocalBeanDefinition(beanName)) - 6、【获取当前Bean依赖的其他Bean(mbd.getDependsOn());如果有按照getBean()把依赖的Bean先创建出来;】 + 6、循环依赖的解决应该就在这里————【获取当前Bean依赖的其他Bean(mbd.getDependsOn());如果有按照getBean()把依赖的Bean先创建出来;】 7、启动单实例Bean的创建流程; 1)、createBean(beanName, mbd, args); - 2)、Object bean = resolveBeforeInstantiation(beanName, mbdToUse);让BeanPostProcessor先拦截Bean创建,返回代理对象; + 2)、Object bean = resolveBeforeInstantiation(beanName, mbdToUse);给BeanPostProcessor返回代理对象的机会; 【InstantiationAwareBeanPostProcessor】:提前执行,在Bean创建之前执行; 先触发:postProcessBeforeInstantiation(); 如果有返回值:触发postProcessAfterInitialization(); @@ -126,13 +132,13 @@ Spring容器的refresh()【创建刷新】; BeanPostProcessor.postProcessBeforeInitialization(); 3)、【执行初始化方法】invokeInitMethods(beanName, wrappedBean, mbd); 1)、是否是InitializingBean接口的实现;执行接口规定的初始化; - 2)、是否自定义初始化方法; + 2)、是否有自定义初始化方法; 4)、【执行后置处理器初始化之后】applyBeanPostProcessorsAfterInitialization BeanPostProcessor.postProcessAfterInitialization(); 5)、注册Bean的销毁方法; registerDisposableBeanIfNecessary(beanName, bean, mbd); 5)、将创建的Bean添加到缓存中(addSingleton(String beanName, Object singletonObject)) - ioc容器就是这些Map;很多的Map里面保存了单实例Bean,环境信息。。。。; + ioc容器就是这些Map;很多的Map里面保存了单实例Bean,环境信息。。。。; 2、第二个for循环 所有Bean都利用getBean创建完成以后; 检查所有的Bean是否是SmartInitializingSingleton接口的;如果是;就执行afterSingletonsInstantiated(); diff --git a/spring-annotation/ext/src/test/java/cn/lastwhisper/spring/ext/test/IOCTest_EXT.java b/spring-annotation/ext/src/test/java/cn/lastwhisper/spring/ext/test/IOCTest_EXT.java index a2c524bd..af4b6bfc 100644 --- a/spring-annotation/ext/src/test/java/cn/lastwhisper/spring/ext/test/IOCTest_EXT.java +++ b/spring-annotation/ext/src/test/java/cn/lastwhisper/spring/ext/test/IOCTest_EXT.java @@ -1,9 +1,8 @@ package cn.lastwhisper.spring.ext.test; import cn.lastwhisper.spring.ext.ExtConfig; -import com.sun.org.apache.xpath.internal.operations.String; +import cn.lastwhisper.spring.ext.bean.Blue; import org.junit.Test; -import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationEvent; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @@ -12,9 +11,9 @@ */ public class IOCTest_EXT { - /** * 测试Spring事件 + * 查询Spring容器启动流程 * * @param * @return void @@ -26,6 +25,9 @@ public void test01() { applicationContext.publishEvent(new ApplicationEvent("发布事件"){}); + Blue blue = (Blue) applicationContext.getBean("hello"); + System.out.println("blue:"+blue); + applicationContext.close(); } diff --git a/spring-annotation/lifecycle/pom.xml b/spring-annotation/lifecycle/pom.xml deleted file mode 100644 index e6fb7f03..00000000 --- a/spring-annotation/lifecycle/pom.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - spring-annotation - cn.lastwhisper - 1.0-SNAPSHOT - - 4.0.0 - - cn.lastwhisper - lifecycle - - - \ No newline at end of file diff --git a/spring-annotation/lifecycle/src/main/java/cn/lastwhisper/lifecycle/bean/Car.java b/spring-annotation/lifecycle/src/main/java/cn/lastwhisper/lifecycle/bean/Car.java deleted file mode 100644 index fd8b4712..00000000 --- a/spring-annotation/lifecycle/src/main/java/cn/lastwhisper/lifecycle/bean/Car.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.lastwhisper.lifecycle.bean; - -/** - * @author lastwhisper - */ -public class Car { - - public Car() { - System.out.println("car constructor..."); - } - // 初始化资源线程池、连接池等 - public void init() { - System.out.println("car init..."); - } - // 释放资源 - public void destroy() { - System.out.println("car destroy..."); - } -} diff --git a/spring-annotation/lifecycle/src/main/java/cn/lastwhisper/lifecycle/bean/Cat.java b/spring-annotation/lifecycle/src/main/java/cn/lastwhisper/lifecycle/bean/Cat.java deleted file mode 100644 index 5bb3f4cf..00000000 --- a/spring-annotation/lifecycle/src/main/java/cn/lastwhisper/lifecycle/bean/Cat.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.lastwhisper.lifecycle.bean; - -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.stereotype.Component; - -/** - * @author lastwhisper - */ -//@Component -public class Cat implements InitializingBean, DisposableBean { - - public Cat() { - System.out.println("cat constructor..."); - } - // 对象创建完成,并赋值之后调用 - @Override - public void afterPropertiesSet() throws Exception { - System.out.println("cat afterPropertiesSet..."); - } - // 容器销毁bean时调用 - @Override - public void destroy() throws Exception { - System.out.println("cat destroy..."); - } - - -} diff --git a/spring-annotation/lifecycle/src/main/java/cn/lastwhisper/lifecycle/bean/Dog.java b/spring-annotation/lifecycle/src/main/java/cn/lastwhisper/lifecycle/bean/Dog.java deleted file mode 100644 index 43a7ae57..00000000 --- a/spring-annotation/lifecycle/src/main/java/cn/lastwhisper/lifecycle/bean/Dog.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.lastwhisper.lifecycle.bean; - -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - -/** - * @author lastwhisper - * implements ApplicationContextAware - */ -@Component -public class Dog implements ApplicationContextAware { - ApplicationContext applicationContext; - - public Dog() { - System.out.println("dog constructor..."); - } - - // 对象创建完成,并赋值之后调用 - @PostConstruct - public void init() throws Exception { - System.out.println("dog @PostConstruct..."); - } - - // 容器销毁bean时调用 - @PreDestroy - public void destroy() throws Exception { - System.out.println("dog @PreDestroy..."); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - -} diff --git a/spring-annotation/lifecycle/src/main/java/cn/lastwhisper/lifecycle/bean/MyBeanPostProcessor.java b/spring-annotation/lifecycle/src/main/java/cn/lastwhisper/lifecycle/bean/MyBeanPostProcessor.java deleted file mode 100644 index 1e3a5296..00000000 --- a/spring-annotation/lifecycle/src/main/java/cn/lastwhisper/lifecycle/bean/MyBeanPostProcessor.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.lastwhisper.lifecycle.bean; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.stereotype.Component; - -/** - * @author lastwhisper - */ -//@Component -public class MyBeanPostProcessor implements BeanPostProcessor { - /** - * 在对象任何初始化之前调用 - * - * @param bean - * @param beanName - * @return java.lang.Object - */ - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - System.out.println("postProcessBeforeInitialization..." + beanName + "..." + bean); - return bean; - } - - /** - * 在对象初始化之后调用 - * - * @param bean - * @param beanName - * @return java.lang.Object - */ - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - System.out.println("postProcessAfterInitialization..." + beanName + "..." + bean); - return bean; - } -} diff --git a/spring-annotation/lifecycle/src/test/java/cn/lastwhisper/lifecycle/test/IOCTest_LifeCycle.java b/spring-annotation/lifecycle/src/test/java/cn/lastwhisper/lifecycle/test/IOCTest_LifeCycle.java deleted file mode 100644 index ac07e9ae..00000000 --- a/spring-annotation/lifecycle/src/test/java/cn/lastwhisper/lifecycle/test/IOCTest_LifeCycle.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.lastwhisper.lifecycle.test; - -import cn.lastwhisper.lifecycle.config.MainConfigOfLifeCycle; -import org.junit.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; - -/** - * @author lastwhisper - */ -public class IOCTest_LifeCycle { - @Test - public void test01() { - // 初始化容器 - AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class); - System.out.println("bean容器初始化..."); - //applicationContext.getBean("car"); - //applicationContext.getBean("cat"); - //applicationContext.getBean("dog"); - // 关闭容器 - applicationContext.close(); - } -} diff --git a/spring-annotation/liftcycle/pom.xml b/spring-annotation/liftcycle/pom.xml new file mode 100644 index 00000000..b75828be --- /dev/null +++ b/spring-annotation/liftcycle/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + liftcycle + cn.lastwhisper + 0.0.1-SNAPSHOT + + + 8 + 8 + + + + + + org.springframework + spring-context + 4.3.12.RELEASE + + + + junit + junit + 4.12 + test + + + + + \ No newline at end of file diff --git a/spring-annotation/liftcycle/src/main/java/cn/cunchang/LifeCycleBean.java b/spring-annotation/liftcycle/src/main/java/cn/cunchang/LifeCycleBean.java new file mode 100644 index 00000000..c516a783 --- /dev/null +++ b/spring-annotation/liftcycle/src/main/java/cn/cunchang/LifeCycleBean.java @@ -0,0 +1,72 @@ +package cn.cunchang; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; + +/** + * @author cunchang + * @date 2022/5/23 11:25 AM + */ +public class LifeCycleBean implements BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean { + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + System.out.println("==== 1.BeanFactoryAware.setBeanFactory: " + beanFactory); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + System.out.println("==== 2.ApplicationContextAware.setApplicationContext: " + applicationContext); + } + + // ==== 4.BeanPostProcessor.postProcessBeforeInitialization + + /** + * 对象创建完成,并赋值之后调用 + * 由CommonAnnotationBeanPostProcessor处理, 相当于xml中的init-method配置 + */ + @PostConstruct + public void initBean() { + System.out.println("==== 4.CommonAnnotationBeanPostProcessor.postConstruct"); + } + + // 对象创建完成,并赋值之后调用 + @Override + public void afterPropertiesSet() throws Exception { + System.out.println("==== 5.InitializingBean.afterPropertiesSet"); + } + + public void initMethod() { + System.out.println("==== 6.init-method"); + } + + // ==== 8.BeanPostProcessor.postProcessAfterInitialization + + /** + * 容器销毁bean时调用 + * 由CommonAnnotationBeanPostProcessor处理, 相当于xml中的destroy-method配置 + */ + @PreDestroy + public void destroyBean() { + System.out.println("==== 8.CommonAnnotationBeanPostProcessor.preDestroy"); + } + + // 容器销毁bean时调用 + @Override + public void destroy() throws Exception { + System.out.println("==== 9.DisposableBean.destroy"); + } + + public void destroyMethod() { + System.out.println("==== 10.destroy-method"); + } + +} \ No newline at end of file diff --git a/spring-annotation/liftcycle/src/main/java/cn/cunchang/MyBeanPostProcessor.java b/spring-annotation/liftcycle/src/main/java/cn/cunchang/MyBeanPostProcessor.java new file mode 100644 index 00000000..49b8605e --- /dev/null +++ b/spring-annotation/liftcycle/src/main/java/cn/cunchang/MyBeanPostProcessor.java @@ -0,0 +1,44 @@ +package cn.cunchang; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.stereotype.Service; + +/** + * @author cunchang + * @date 2022/5/23 11:25 AM + */ +@Service +public class MyBeanPostProcessor implements BeanPostProcessor { + + /** + * 在对象任何初始化之前调用 + * @param bean ioc容器中的每一个Bean对象 + * @param beanName Bean对象对应的name + * @return java.lang.Object + * @throws BeansException + */ + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + if (bean instanceof LifeCycleBean) { + System.out.println("==== 3.BeanPostProcessor.postProcessBeforeInitialization: " + beanName); + } + return bean; + } + + /** + * 在对象初始化之后调用 + * + * @param bean ioc容器中的每一个Bean对象 + * @param beanName Bean对象对应的name + * @return java.lang.Object + */ + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if (bean instanceof LifeCycleBean) { + System.out.println("==== 7.BeanPostProcessor.postProcessAfterInitialization: " + beanName); + } + return bean; + } + +} \ No newline at end of file diff --git a/spring-annotation/lifecycle/src/main/java/cn/lastwhisper/lifecycle/config/MainConfigOfLifeCycle.java b/spring-annotation/liftcycle/src/main/java/cn/cunchang/config/MainConfigOfLifeCycle.java similarity index 79% rename from spring-annotation/lifecycle/src/main/java/cn/lastwhisper/lifecycle/config/MainConfigOfLifeCycle.java rename to spring-annotation/liftcycle/src/main/java/cn/cunchang/config/MainConfigOfLifeCycle.java index 12f3fe30..c8e39afa 100644 --- a/spring-annotation/lifecycle/src/main/java/cn/lastwhisper/lifecycle/config/MainConfigOfLifeCycle.java +++ b/spring-annotation/liftcycle/src/main/java/cn/cunchang/config/MainConfigOfLifeCycle.java @@ -1,6 +1,6 @@ -package cn.lastwhisper.lifecycle.config; +package cn.cunchang.config; -import cn.lastwhisper.lifecycle.bean.Car; +import cn.cunchang.LifeCycleBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @@ -24,21 +24,21 @@ * 相当于xml中的配置:init-method="init" destroy-method="destroy" * 2)通过bean实现InitializingBean(定义初始化逻辑)、DisposableBean(定义销毁逻辑) * - * 3)JSR250规范 + * 3)JSR250规 * *@PostConstruct:在bean创建完成并且属性赋值完成,来执行初始化方法 * *@PreDestroy:在容器销毁bean之前调用 * 4)BeanPostProcessor:对所有bean的后置处理器,在bean初始化前后进行处理 * 该接口有两个方法: - * postProcessBeforeInitialization:在对象任何初始化(initMethod、afterPropertiesSet)之前调用 + * postProcessBeforeInitialization:在对象创建之后,任何初始化(initMethod、afterPropertiesSet)之前调用 * postProcessAfterInitialization:在对象初始化之后调用 * * BeanPostProcessor原理: * AbstractAutowireCapableBeanFactory.doCreateBean{ - * populateBean(beanName, mbd, instanceWrapper); // 给对象中的字段赋值 + * populateBean(beanName, mbd, instanceWrapper); // 给Bean对象中的成员变量赋值 * initializeBean{ - * applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);// 调用postProcessBeforeInitialization处理器 + * applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);// 调用postProcessBeforeInitialization处理器,一旦返回null就结束 * invokeInitMethods(beanName, wrappedBean, mbd); // 调用对象的初始化方法 - * applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);//调用postProcessAfterInitialization处理器 + * applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);//调用postProcessAfterInitialization处理器,一旦返回null就结束 * } * } * @@ -47,18 +47,21 @@ * ApplicationContextAwareProcessor 处理实现ApplicationContextAware的类 * BeanValidationPostProcessor 处理JSR-303数据校验 * InitDestroyAnnotationBeanPostProcessor 处理@PostConstruct和@PreDestroy注解 + * CommonAnnotationBeanPostProcessor 初始化时,设置@PostConstruct和@PreDestroy为初始化和销毁注解 * AutowiredAnnotationBeanPostProcessor 处理@Autowire注解 * * @author lastwhisper */ -@ComponentScan("cn.lastwhisper.lifecycle.bean") +@ComponentScan("cn.cunchang") @Configuration public class MainConfigOfLifeCycle { - //@Scope("singleton") - ////@Scope("prototype") - //@Bean(initMethod = "init", destroyMethod = "destroy") - //public Car car() { - // return new Car(); - //} + + //@Scope("prototype") + @Scope("singleton") + @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod") + public LifeCycleBean lifeCycleBean() { + return new LifeCycleBean(); + } + } diff --git a/spring-annotation/liftcycle/src/test/java/cn/cunchang/IOCTest_LifeCycle2.java b/spring-annotation/liftcycle/src/test/java/cn/cunchang/IOCTest_LifeCycle2.java new file mode 100644 index 00000000..416b9891 --- /dev/null +++ b/spring-annotation/liftcycle/src/test/java/cn/cunchang/IOCTest_LifeCycle2.java @@ -0,0 +1,23 @@ +package cn.cunchang; + +import cn.cunchang.config.MainConfigOfLifeCycle; +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +/** + * @author lastwhisper + */ +public class IOCTest_LifeCycle2 { + + @Test + public void test01() { + // 初始化容器 + AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class); + System.out.println("bean容器初始化..."); + LifeCycleBean lifeCycleBean = applicationContext.getBean(LifeCycleBean.class); + + // 关闭容器 + applicationContext.close(); + } + +} diff --git a/spring-annotation/pom.xml b/spring-annotation/pom.xml index 739ce201..4534f311 100644 --- a/spring-annotation/pom.xml +++ b/spring-annotation/pom.xml @@ -1,52 +1,25 @@ - + 4.0.0 - cn.lastwhisper spring-annotation pom - 1.0-SNAPSHOT + 0.0.1-SNAPSHOT - propertyvalue - lifecycle - componentregister - autowired - profile - aop - transaction - ext + aop-interface + spring-annotation + Spring Annotation - - - - org.springframework - spring-context - 4.3.12.RELEASE - - - - junit - junit - 4.12 - test - + + 1.8 + + - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 8 - 8 - - - - \ No newline at end of file + + diff --git a/spring-annotation/profile/pom.xml b/spring-annotation/profile/pom.xml index 629d5c7d..63986ebd 100644 --- a/spring-annotation/profile/pom.xml +++ b/spring-annotation/profile/pom.xml @@ -2,15 +2,12 @@ - - spring-annotation - cn.lastwhisper - 1.0-SNAPSHOT - + 4.0.0 cn.lastwhisper profile + 1.0-SNAPSHOT @@ -25,5 +22,19 @@ mysql-connector-java 5.1.38 + + + + org.springframework + spring-context + 4.3.12.RELEASE + + + + junit + junit + 4.12 + test + \ No newline at end of file diff --git a/spring-annotation/propertyvalue/pom.xml b/spring-annotation/propertyvalue/pom.xml index b8ba5b6d..982b21e7 100644 --- a/spring-annotation/propertyvalue/pom.xml +++ b/spring-annotation/propertyvalue/pom.xml @@ -2,14 +2,27 @@ - - spring-annotation - cn.lastwhisper - 1.0-SNAPSHOT - + 4.0.0 propertyvalue + cn.lastwhisper + 1.0-SNAPSHOT + + + + + org.springframework + spring-context + 4.3.12.RELEASE + + + junit + junit + 4.12 + test + + \ No newline at end of file diff --git a/spring-annotation/propertyvalue/src/main/java/cn/lastwhisper/propertyvalue/bean/Person.java b/spring-annotation/propertyvalue/src/main/java/cn/lastwhisper/propertyvalue/bean/Person.java index 886ee0ba..3051fd2c 100644 --- a/spring-annotation/propertyvalue/src/main/java/cn/lastwhisper/propertyvalue/bean/Person.java +++ b/spring-annotation/propertyvalue/src/main/java/cn/lastwhisper/propertyvalue/bean/Person.java @@ -3,6 +3,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import java.util.List; +import java.util.Set; + /** * @author lastwhisper */ @@ -20,12 +23,15 @@ public class Person { @Value("${person.nickname}") private String nickname; - public Person() { - } + // 支付宝、微信、银行卡各有多少钱 + @Value("#{'${person.moneyList}'.split(',')}") + private List moneyList; - public Person(String name, Integer age) { - this.name = name; - this.age = age; + @Value("#{'${person.moneyList}'.split(',')}") + private Set moneySet; + + + public Person() { } public String getName() { @@ -52,12 +58,30 @@ public void setNickname(String nickname) { this.nickname = nickname; } + public List getMoneyList() { + return moneyList; + } + + public void setMoneyList(List moneyList) { + this.moneyList = moneyList; + } + + public Set getMoneySet() { + return moneySet; + } + + public void setMoneySet(Set moneySet) { + this.moneySet = moneySet; + } + @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", nickname='" + nickname + '\'' + + ", moneyList=" + moneyList + + ", moneySet=" + moneySet + '}'; } } diff --git a/spring-annotation/propertyvalue/src/main/resources/person.properties b/spring-annotation/propertyvalue/src/main/resources/person.properties index cb56670a..1a40a850 100644 --- a/spring-annotation/propertyvalue/src/main/resources/person.properties +++ b/spring-annotation/propertyvalue/src/main/resources/person.properties @@ -1 +1,2 @@ -person.nickname=nike \ No newline at end of file +person.nickname=nike +person.moneyList=100,200,300 \ No newline at end of file diff --git a/spring-annotation/propertyvalue/src/test/java/cn/lastwhisper/propertyvalue/test/IOCTest_PropertyValue.java b/spring-annotation/propertyvalue/src/test/java/cn/lastwhisper/propertyvalue/test/IOCTest_PropertyValue.java index 6700aa6a..0deb59ef 100644 --- a/spring-annotation/propertyvalue/src/test/java/cn/lastwhisper/propertyvalue/test/IOCTest_PropertyValue.java +++ b/spring-annotation/propertyvalue/src/test/java/cn/lastwhisper/propertyvalue/test/IOCTest_PropertyValue.java @@ -1,4 +1,4 @@ -package cn.lastwhisper.lifecycle.test; +package cn.lastwhisper.propertyvalue.test; import cn.lastwhisper.propertyvalue.bean.Person; import cn.lastwhisper.propertyvalue.config.MainConfigOfPropertyValues; @@ -18,14 +18,16 @@ public void test01() { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfPropertyValues.class); System.out.println("容器初始化..."); +// printBeans(applicationContext); + + Person person = (Person) applicationContext.getBean("person"); System.out.println(person); - Environment environment = applicationContext.getEnvironment(); - String property = environment.getProperty("person.nickname"); - System.out.println(property); +// Environment environment = applicationContext.getEnvironment(); +// String property = environment.getProperty("person.nickname"); +// System.out.println(property); - //printBeans(applicationContext); } private void printBeans(ApplicationContext applicationContext) { diff --git a/spring-annotation/transaction/README.md b/spring-annotation/transaction/README.md new file mode 100644 index 00000000..8c6c4fd3 --- /dev/null +++ b/spring-annotation/transaction/README.md @@ -0,0 +1,4 @@ +注解事务实现原理 + + + diff --git a/spring-annotation/transaction/pom.xml b/spring-annotation/transaction/pom.xml index 9a94be10..46b1beaa 100644 --- a/spring-annotation/transaction/pom.xml +++ b/spring-annotation/transaction/pom.xml @@ -2,14 +2,12 @@ - - spring-annotation - cn.lastwhisper - 1.0-SNAPSHOT - + 4.0.0 transaction + cn.lastwhisper + 1.0-SNAPSHOT @@ -18,10 +16,24 @@ 4.3.12.RELEASE + + + org.springframework + spring-context + 4.3.12.RELEASE + + + + junit + junit + 4.12 + test + + mysql mysql-connector-java - 5.1.44 + 8.0.25 diff --git a/spring-annotation/transaction/src/main/java/cn/lastwhisper/tx/TxConfig.java b/spring-annotation/transaction/src/main/java/cn/lastwhisper/tx/TxConfig.java index 21a14d91..963bf9d9 100644 --- a/spring-annotation/transaction/src/main/java/cn/lastwhisper/tx/TxConfig.java +++ b/spring-annotation/transaction/src/main/java/cn/lastwhisper/tx/TxConfig.java @@ -47,7 +47,7 @@ * 在目标方法执行的时候; * 执行拦截器链; * 事务拦截器: - * 看invokeWithinTransaction方法 + * 看(MethodInterceptor.invoke(this)里面的invokeWithinTransaction方法 * 1)、先获取事务相关的属性 * 2)、再获取PlatformTransactionManager,如果事先没有添加指定任何transactionmanger * 最终会从容器中按照类型获取一个PlatformTransactionManager; @@ -71,9 +71,9 @@ public class TxConfig { public DataSource dataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser("root"); - dataSource.setPassword("root"); - dataSource.setDriverClass("com.mysql.jdbc.Driver"); - dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test"); + dataSource.setPassword("123456"); + dataSource.setDriverClass("com.mysql.cj.jdbc.Driver"); + dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test?useSSL=false"); return dataSource; } diff --git a/spring-annotation/transaction/src/main/resources/test.sql b/spring-annotation/transaction/src/main/resources/test.sql index a482ef0c..ac93d122 100644 --- a/spring-annotation/transaction/src/main/resources/test.sql +++ b/spring-annotation/transaction/src/main/resources/test.sql @@ -26,7 +26,7 @@ CREATE TABLE `tbl_user` ( `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `age` int(11) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of tbl_user diff --git a/spring-annotation/transaction/src/test/java/cn/lastwhisper/tx/test/IOCTest_TX.java b/spring-annotation/transaction/src/test/java/cn/lastwhisper/tx/test/IOCTest_TX.java index 6fed9822..8c1f28df 100644 --- a/spring-annotation/transaction/src/test/java/cn/lastwhisper/tx/test/IOCTest_TX.java +++ b/spring-annotation/transaction/src/test/java/cn/lastwhisper/tx/test/IOCTest_TX.java @@ -20,13 +20,13 @@ public class IOCTest_TX { */ @Test public void test01() { - ApplicationContext applicationContext = new AnnotationConfigApplicationContext(TxConfig.class); + AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TxConfig.class); System.out.println("容器初始化..."); UserService userService = applicationContext.getBean(UserService.class); userService.insertUser(); - //applicationContext.close(); + applicationContext.close(); //printBeans(applicationContext); } diff --git a/spring-batch/spring-batch/pom.xml b/spring-batch/spring-batch/pom.xml new file mode 100644 index 00000000..3dd045d5 --- /dev/null +++ b/spring-batch/spring-batch/pom.xml @@ -0,0 +1,99 @@ + + + 4.0.0 + cn.cunchang + spring-batch + 0.0.1-SNAPSHOT + spring-batch + spring-batch + + + 1.8 + 1.8 + 2.2.4.RELEASE + Hoxton.SR1 + 2.2.0.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-batch + + + org.springframework.batch + spring-batch-integration + + + + + com.alibaba.cloud + spring-cloud-starter-stream-rocketmq + + + + org.hsqldb + hsqldb + runtime + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.batch + spring-batch-test + test + + + + + + + + org.springframework.boot + spring-boot-starter-parent + ${spring.boot.version} + pom + import + + + org.springframework.cloud + spring-cloud-dependencies + ${spring.cloud.version} + pom + import + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + ${spring.cloud.alibaba.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-batch/spring-batch/src/main/java/cn/cunchang/SpringBatchApplication.java b/spring-batch/spring-batch/src/main/java/cn/cunchang/SpringBatchApplication.java new file mode 100644 index 00000000..905f278d --- /dev/null +++ b/spring-batch/spring-batch/src/main/java/cn/cunchang/SpringBatchApplication.java @@ -0,0 +1,14 @@ +package cn.cunchang; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringBatchApplication { + + public static void main(String[] args) { +// System.exit(SpringApplication.exit(SpringApplication.run(SpringBatchApplication.class, args))); + SpringApplication.run(SpringBatchApplication.class, args); + } + +} diff --git a/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/BatchConfiguration.java b/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/BatchConfiguration.java new file mode 100644 index 00000000..e3ffd39f --- /dev/null +++ b/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/BatchConfiguration.java @@ -0,0 +1,21 @@ +package cn.cunchang.batch; + +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.integration.config.annotation.EnableBatchIntegration; +import org.springframework.cloud.stream.annotation.EnableBinding; +import org.springframework.context.annotation.Configuration; + +/** + * @EnableBatchProcessing 自动注册springbatch的关键组件 + * 比如 JobBuilderFactory、StepBuilderFactory + * + */ +@Configuration +@EnableBatchProcessing +@EnableBatchIntegration +@EnableBinding(BatchMessageChannel.class) +public class BatchConfiguration { + + + +} \ No newline at end of file diff --git a/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/BatchMessageChannel.java b/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/BatchMessageChannel.java new file mode 100644 index 00000000..2341a625 --- /dev/null +++ b/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/BatchMessageChannel.java @@ -0,0 +1,46 @@ +package cn.cunchang.batch; + +import org.springframework.cloud.stream.annotation.Input; +import org.springframework.cloud.stream.annotation.Output; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.SubscribableChannel; + +/** + * BatchMessageChannel + * + * @author jianzhu + * @date 2021/3/19 18:47 + */ +public interface BatchMessageChannel { + + /** + * ================================================== Manager + */ + + // 输出型消息通道,发送消息:Manager -> Workers + String DAILY_ORDER_MANAGER_OUTPUT = "daily-order-manager-output"; + + @Output(DAILY_ORDER_MANAGER_OUTPUT) + MessageChannel dailyOrderOutgoingRequestsToWorkers(); + + String CHECK_MANAGER_OUTPUT = "check-manager-output"; + + @Output(CHECK_MANAGER_OUTPUT) + MessageChannel checkOutgoingRequestsToWorkers(); + + /** + * ================================================== Worker + */ + + // 输入型消息通道,接收 Manager 消息 + String DAILY_ORDER_WORKER_INPUT = "daily-order-worker-input"; + + @Input(DAILY_ORDER_WORKER_INPUT) + SubscribableChannel dailyOrderIncomingRequestsFromManager(); + + String CHECK_WORKER_INPUT = "check-worker-input"; + + @Input(CHECK_WORKER_INPUT) + SubscribableChannel checkIncomingRequestsFromManager(); + +} diff --git a/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/job/BatchConfiguration.java b/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/job/BatchConfiguration.java new file mode 100644 index 00000000..43b96687 --- /dev/null +++ b/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/job/BatchConfiguration.java @@ -0,0 +1,112 @@ +package cn.cunchang.batch.job; + +import cn.cunchang.batch.listener.JobCompletionNotificationListener; +import cn.cunchang.pojo.Person; +import cn.cunchang.batch.processor.PersonItemProcessor; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; +import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; +import org.springframework.batch.core.launch.support.RunIdIncrementer; +import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider; +import org.springframework.batch.item.database.JdbcBatchItemWriter; +import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder; +import org.springframework.batch.item.file.FlatFileItemReader; +import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder; +import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; + +import javax.sql.DataSource; + +/** + * @EnableBatchProcessing 自动注册springbatch的关键组件 + * 比如 JobBuilderFactory、StepBuilderFactory + * + */ +@Configuration +@EnableBatchProcessing +public class BatchConfiguration { + + @Autowired + public JobBuilderFactory jobBuilderFactory; + + @Autowired + public StepBuilderFactory stepBuilderFactory; + + /** + * 输入 + * + * @return + */ + @Bean + public FlatFileItemReader reader() { + return new FlatFileItemReaderBuilder() + .name("personItemReader") + .resource(new ClassPathResource("sample-data.csv")) + .delimited() + .names(new String[]{"firstName", "lastName"}) + .fieldSetMapper(new BeanWrapperFieldSetMapper() {{ + setTargetType(Person.class); + }}) + .build(); + } + + /** + * 处理器 + * + * @return + */ + @Bean + public PersonItemProcessor processor() { + return new PersonItemProcessor(); + } + + /** + * 输出 + * + * @param dataSource + * @return + */ + @Bean + public JdbcBatchItemWriter writer(DataSource dataSource) { + return new JdbcBatchItemWriterBuilder() + .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>()) + .sql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)") + .dataSource(dataSource) + .build(); + } + + /** + * 定义作业 + * + * 作业由步骤构建而成,其中每个步骤都可能涉及读取器、处理器和写入器。 + * + * @param listener + * @param step1 + * @return + */ + @Bean + public Job importUserJob(JobCompletionNotificationListener listener, Step step1) { + return jobBuilderFactory.get("importUserJob") + .incrementer(new RunIdIncrementer()) + .listener(listener) + .flow(step1) + .end() + .build(); + } + + @Bean + public Step step1(JdbcBatchItemWriter writer) { + return stepBuilderFactory.get("step1") + . chunk(10) + .reader(reader()) + .processor(processor()) + .writer(writer) + .build(); + } + +} \ No newline at end of file diff --git a/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/listener/JobCompletionNotificationListener.java b/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/listener/JobCompletionNotificationListener.java new file mode 100644 index 00000000..b2877075 --- /dev/null +++ b/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/listener/JobCompletionNotificationListener.java @@ -0,0 +1,45 @@ +package cn.cunchang.batch.listener; + +import cn.cunchang.pojo.Person; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.batch.core.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Component; + +@Component +public class JobCompletionNotificationListener implements JobExecutionListener { + + private static final Logger log = LoggerFactory.getLogger(JobCompletionNotificationListener.class); + + @Autowired + private JdbcTemplate jdbcTemplate; + + @Override + public void beforeJob(JobExecution jobExecution) { + log.info("Job 执行开始. jobName={}, jobId={}, jobExecutionId={}, jobParameters={}", + jobExecution.getJobInstance().getJobName(), jobExecution.getJobId(), jobExecution.getId(), + jobExecution.getJobParameters()); + } + + @Override + public void afterJob(JobExecution jobExecution) { + if (jobExecution.getStatus() == BatchStatus.COMPLETED) { + String jobName = jobExecution.getJobInstance().getJobName(); + Long jobExecutionId = jobExecution.getId(); + BatchStatus batchStatus = jobExecution.getStatus(); + ExitStatus exitStatus = jobExecution.getExitStatus(); + JobParameters jobParameters = jobExecution.getJobParameters(); + log.info("Job 执行结束. jobName={}, jobId={}, jobExecutionId={}, status={}, exitStatus={}, jobParameters={}", + jobName, jobExecution.getJobId(), jobExecutionId, batchStatus, exitStatus, jobParameters); + + jdbcTemplate.query("SELECT first_name, last_name FROM people", + (rs, row) -> new Person( + rs.getString(1), + rs.getString(2)) + ).forEach(person -> log.info("jobName:{},Found <" + person + "> in the database.", jobName)); + } + } + +} \ No newline at end of file diff --git a/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/listener/StepCompletionNotificationListener.java b/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/listener/StepCompletionNotificationListener.java new file mode 100644 index 00000000..3ca81598 --- /dev/null +++ b/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/listener/StepCompletionNotificationListener.java @@ -0,0 +1,41 @@ +package cn.cunchang.batch.listener; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.StepExecutionListener; +import org.springframework.stereotype.Component; + +/** + * @author cunchang + * @date 2021/9/17 6:54 下午 + */ +@Component +public class StepCompletionNotificationListener implements StepExecutionListener { + + private static final Logger log = LoggerFactory.getLogger(JobCompletionNotificationListener.class); + + @Override + public void beforeStep(StepExecution stepExecution) { + log.info("BEFORE_STEP stepId={}, stepName={}, status={}, exitStatus={}, executionContext={}", + stepExecution.getId(), stepExecution.getStepName(), stepExecution.getStatus(), + stepExecution.getExitStatus(), stepExecution.getExecutionContext()); + } + + @Override + public ExitStatus afterStep(StepExecution stepExecution) { + String jobName = stepExecution.getJobExecution().getJobInstance().getJobName(); + Long jobExecutionId = stepExecution.getJobExecutionId(); + String stepName = stepExecution.getStepName(); + Long stepExecutionId = stepExecution.getId(); + BatchStatus batchStatus = stepExecution.getStatus(); + ExitStatus exitStatus = stepExecution.getExitStatus(); + log.info("AFTER_STEP jobName={}, jobExecutionId={}, stepId={}, stepName={}, status={}, exitStatus={}, executionContext={}", + jobName, jobExecutionId, stepExecutionId, stepName, batchStatus, exitStatus, stepExecution.getExecutionContext()); + + return null; + } + +} diff --git a/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/processor/PersonItemProcessor.java b/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/processor/PersonItemProcessor.java new file mode 100644 index 00000000..540d51ea --- /dev/null +++ b/spring-batch/spring-batch/src/main/java/cn/cunchang/batch/processor/PersonItemProcessor.java @@ -0,0 +1,25 @@ +package cn.cunchang.batch.processor; + +import cn.cunchang.pojo.Person; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.batch.item.ItemProcessor; + +public class PersonItemProcessor implements ItemProcessor { + + private static final Logger log = LoggerFactory.getLogger(PersonItemProcessor.class); + + @Override + public Person process(final Person person) throws Exception { + final String firstName = person.getFirstName().toUpperCase(); + final String lastName = person.getLastName().toUpperCase(); + + final Person transformedPerson = new Person(firstName, lastName); + + log.info("Converting (" + person + ") into (" + transformedPerson + ")"); + + return transformedPerson; + } + +} \ No newline at end of file diff --git a/spring-batch/spring-batch/src/main/java/cn/cunchang/pojo/Person.java b/spring-batch/spring-batch/src/main/java/cn/cunchang/pojo/Person.java new file mode 100644 index 00000000..c7e15245 --- /dev/null +++ b/spring-batch/spring-batch/src/main/java/cn/cunchang/pojo/Person.java @@ -0,0 +1,37 @@ +package cn.cunchang.pojo; + +public class Person { + + private String lastName; + private String firstName; + + public Person() { + } + + public Person(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @Override + public String toString() { + return "firstName: " + firstName + ", lastName: " + lastName; + } + +} \ No newline at end of file diff --git a/spring-batch/spring-batch/src/main/java/cn/cunchang/schedule/EntryXxljob.java b/spring-batch/spring-batch/src/main/java/cn/cunchang/schedule/EntryXxljob.java new file mode 100644 index 00000000..6f5067d3 --- /dev/null +++ b/spring-batch/spring-batch/src/main/java/cn/cunchang/schedule/EntryXxljob.java @@ -0,0 +1,21 @@ +package cn.cunchang.schedule; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 定时任务触发spring batch job + * @author cunchang + * @date 2021/9/16 3:33 下午 + */ +@RestController +public class EntryXxljob { + + @GetMapping("/test") + public String test() { + + + return "success"; + } + +} diff --git a/spring-batch/spring-batch/src/main/resources/application.properties b/spring-batch/spring-batch/src/main/resources/application.properties new file mode 100644 index 00000000..fbcd88e0 --- /dev/null +++ b/spring-batch/spring-batch/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.batch.job.enabled=false diff --git a/spring-batch/spring-batch/src/main/resources/sample-data.csv b/spring-batch/spring-batch/src/main/resources/sample-data.csv new file mode 100644 index 00000000..77a4babe --- /dev/null +++ b/spring-batch/spring-batch/src/main/resources/sample-data.csv @@ -0,0 +1,11 @@ +Jill,Doe +Joe,Doe +Justin,Doe +Jane,Doe +John,Doe +Tom,Doe +Cat,Doe +Zhang,San +Li,Si +Li,Doe +Zhang,Doe \ No newline at end of file diff --git a/spring-batch/spring-batch/src/main/resources/schema-all.sql b/spring-batch/spring-batch/src/main/resources/schema-all.sql new file mode 100644 index 00000000..011297df --- /dev/null +++ b/spring-batch/spring-batch/src/main/resources/schema-all.sql @@ -0,0 +1,8 @@ +DROP TABLE people IF EXISTS; + +CREATE TABLE people +( + person_id BIGINT IDENTITY NOT NULL PRIMARY KEY, + first_name VARCHAR(20), + last_name VARCHAR(20) +); \ No newline at end of file diff --git a/spring-batch/spring-batch/src/test/java/cn/cunchang/SpringBatchApplicationTests.java b/spring-batch/spring-batch/src/test/java/cn/cunchang/SpringBatchApplicationTests.java new file mode 100644 index 00000000..96ac9af5 --- /dev/null +++ b/spring-batch/spring-batch/src/test/java/cn/cunchang/SpringBatchApplicationTests.java @@ -0,0 +1,13 @@ +package cn.cunchang; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class SpringBatchApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/springboot-aop/principle/README.md b/springboot-aop/principle/README.md new file mode 100644 index 00000000..3c1d7d5f --- /dev/null +++ b/springboot-aop/principle/README.md @@ -0,0 +1,7 @@ +- AOP 底层设计模式 + - 动态代理 + - 责任链 + +动态代理代码,迁移到proxy +责任链代码,迁移到design-pattern + diff --git a/springboot-aop/principle/pom.xml b/springboot-aop/principle/pom.xml deleted file mode 100644 index 87f46a5a..00000000 --- a/springboot-aop/principle/pom.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.7.RELEASE - - - cn.lastwhisper.springboot - principle - 0.0.1-SNAPSHOT - principle - Spring AOP 底层设计模式 - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - - cglib - cglib - 3.2.4 - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/ProxyDemoApplication.java b/springboot-aop/principle/src/main/java/cn/lastwhisper/ProxyDemoApplication.java deleted file mode 100644 index 370447c9..00000000 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/ProxyDemoApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class ProxyDemoApplication { - - public static void main(String[] args) { - SpringApplication.run(ProxyDemoApplication.class, args); - } - -} diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v1/Client.java b/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v1/Client.java deleted file mode 100644 index 7b9b17fc..00000000 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v1/Client.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.lastwhisper.chain.v1; - -/** - * @author lastwhisper - */ -public class Client { - static class HandlerA extends Handler{ - @Override - protected void handleProcess() { - System.out.println("handle by a"); - } - } - - static class HandlerB extends Handler{ - @Override - protected void handleProcess() { - System.out.println("handle by b"); - } - } - - static class HandlerC extends Handler{ - @Override - protected void handleProcess() { - System.out.println("handle by c"); - } - } - - public static void main(String[] args){ - Handler handlerA = new HandlerA(); - Handler handlerB = new HandlerB(); - Handler handlerC = new HandlerC(); - - handlerA.setSucessor(handlerB); - handlerB.setSucessor(handlerC); - - handlerA.execute(); - } - -} diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v2/Chain.java b/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v2/Chain.java deleted file mode 100644 index 65ec7597..00000000 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v2/Chain.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.lastwhisper.chain.v2; - -import java.util.List; - -/** - * 使用chain进行包装 - * @author lastwhisper - */ -public class Chain { - private List handlers; - private int index = 0; - - public Chain(List handlers) { - this.handlers = handlers; - } - - //将顺序关系封装 - public void proceed() { - if (index >= handlers.size()) { - return; - } - handlers.get(index++).execute(this); - } -} diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v2/ChainClient.java b/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v2/ChainClient.java deleted file mode 100644 index b7cf9447..00000000 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v2/ChainClient.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.lastwhisper.chain.v2; - -import java.util.Arrays; -import java.util.List; - -/** - * Created by cat on 2017-02-28. - */ -public class ChainClient { - static class ChainHandlerA extends ChainHandler{ - @Override - protected void handleProcess() { - System.out.println("handle by chain a"); - } - } - static class ChainHandlerB extends ChainHandler{ - @Override - protected void handleProcess() { - System.out.println("handle by chain b"); - } - } - static class ChainHandlerC extends ChainHandler{ - @Override - protected void handleProcess() { - System.out.println("handle by chain c"); - } - } - - public static void main(String[] args){ - List handlers = Arrays.asList( - new ChainHandlerA(), - new ChainHandlerB(), - new ChainHandlerC() - ); - Chain chain = new Chain(handlers); - chain.proceed(); - } -} diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v2/ChainHandler.java b/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v2/ChainHandler.java deleted file mode 100644 index 976ae24b..00000000 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v2/ChainHandler.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.lastwhisper.chain.v2; - -/** - * Created by cat on 2017-02-28. - */ -public abstract class ChainHandler { - - public void execute(Chain chain){ - handleProcess(); - chain.proceed(); - - } - - protected abstract void handleProcess(); -} diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v3/Chain.java b/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v3/Chain.java deleted file mode 100644 index dea28e06..00000000 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v3/Chain.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.lastwhisper.chain.v3; - -import java.util.List; - -/** - * 使用chain进行包装 - * @author lastwhisper - */ -public class Chain { - private List handlers; - private int index = 0; - - public Chain(List handlers) { - this.handlers = handlers; - } - - //将顺序关系封装 - public void proceed() { - if (index >= handlers.size()) { - return; - } - handlers.get(index++).execute(this); - } -} diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v3/ChainClient.java b/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v3/ChainClient.java deleted file mode 100644 index 32ec33d3..00000000 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v3/ChainClient.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.lastwhisper.chain.v3; - -import java.util.Arrays; -import java.util.List; - -/** - * Created by cat on 2017-02-28. - */ -public class ChainClient { - static class ChainHandlerA extends ChainHandler { - @Override - protected void handlePreProcess() { - System.out.println("ChainHandlerA handlePreProcess"); - } - - @Override - protected void handlePostProcess() { - System.out.println("ChainHandlerA handlePostProcess"); - } - } - - static class ChainHandlerB extends ChainHandler { - @Override - protected void handlePreProcess() { - System.out.println("ChainHandlerB handlePreProcess"); - } - - @Override - protected void handlePostProcess() { - System.out.println("ChainHandlerB handlePostProcess"); - } - } - - static class ChainHandlerC extends ChainHandler { - @Override - protected void handlePreProcess() { - System.out.println("ChainHandlerC handlePreProcess"); - } - - @Override - protected void handlePostProcess() { - System.out.println("ChainHandlerC handlePostProcess"); - } - } - - public static void main(String[] args) { - List handlers = Arrays.asList( - new ChainHandlerA(), - new ChainHandlerB(), - new ChainHandlerC() - ); - Chain chain = new Chain(handlers); - chain.proceed(); - - - } -} diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v3/ChainHandler.java b/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v3/ChainHandler.java deleted file mode 100644 index 5d5318a5..00000000 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/chain/v3/ChainHandler.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.lastwhisper.chain.v3; - -/** - * Created by cat on 2017-02-28. - */ -public abstract class ChainHandler { - - // 模板方法 - public void execute(Chain chain){ - handlePreProcess(); - chain.proceed(); - handlePostProcess(); - } - - protected abstract void handlePreProcess(); - protected abstract void handlePostProcess(); -} diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/cglibproxy/Client.java b/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/cglibproxy/Client.java deleted file mode 100644 index 1b34e2ca..00000000 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/cglibproxy/Client.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.lastwhisper.proxy.cglibproxy; - -import cn.lastwhisper.proxy.staticproxy.RealSubject; -import cn.lastwhisper.proxy.staticproxy.Subject; -import net.sf.cglib.proxy.Enhancer; - -/** - * @author lastwhisper - */ -public class Client { - public static void main(String[] args) { - Enhancer enhancer = new Enhancer(); - enhancer.setSuperclass(RealSubject.class); - enhancer.setCallback(new DemoMethodInterceptor()); - Subject subject = (Subject) enhancer.create(); - subject.request(); - } -} diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/cglibproxy/DemoMethodInterceptor.java b/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/cglibproxy/DemoMethodInterceptor.java deleted file mode 100644 index 52370306..00000000 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/cglibproxy/DemoMethodInterceptor.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.lastwhisper.proxy.cglibproxy; - -import net.sf.cglib.proxy.MethodInterceptor; -import net.sf.cglib.proxy.MethodProxy; - -import java.lang.reflect.Method; - -/** - * @author lastwhisper - */ -public class DemoMethodInterceptor implements MethodInterceptor { - - @Override - public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { - System.out.println("before method"); - Object result =null; - try { - result = methodProxy.invokeSuper(o, objects); - }catch (Exception e){ - System.out.println("ex:"+e.getMessage()); - throw e; - }finally { - System.out.println("after method"); - } - return result; - } - -} diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/dynamicproxy/Client.java b/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/dynamicproxy/Client.java deleted file mode 100644 index cc50278f..00000000 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/dynamicproxy/Client.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.lastwhisper.proxy.dynamicproxy; - -import cn.lastwhisper.proxy.staticproxy.RealSubject; -import cn.lastwhisper.proxy.staticproxy.Subject; - -/** - * Created by cat on 2017-02-27. - */ -public class Client { - - public static void main(String[] args) { - // 查看生成的代理类 - System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); - Subject proxy = (Subject) new JdkProxySubject(new RealSubject()).getProxy(); - //proxy.request(); - proxy.response(); - } -} diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/dynamicproxy/JdkProxySubject.java b/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/dynamicproxy/JdkProxySubject.java deleted file mode 100644 index 86de6a80..00000000 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/dynamicproxy/JdkProxySubject.java +++ /dev/null @@ -1,59 +0,0 @@ -package cn.lastwhisper.proxy.dynamicproxy; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - -/** - * aspect - * @author lastwhisper - */ -public class JdkProxySubject implements InvocationHandler { - // 目标类 - private Object target; - - public JdkProxySubject(Object target) { - this.target = target; - } - - /** - * newProxyInstance - * |-- getProxyClass0 - * |--proxyClassCache.get(loader, interfaces); - * |--ProxyClassFactory - * |--apply - * |--代理类的名称 String proxyName = proxyPkg + proxyClassNamePrefix + num; - * |--生成字节码 byte[] proxyClassFile = ProxyGenerator.generateProxyClass( - * proxyName, interfaces, accessFlags);通过类加载器defineClass0加载 - * |--生成符合Java规范的代码 generateProxyClass - * 在动态生成的对象中,使用h.invoke(this, m3, (Object[])null)这种形式执行方法 - * 这个h就是Proxy的InvocationHandler成员变量,而这个成员变量是在 - * Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this)传入this时赋值的 - */ - public Object getProxy() { - Class clazz = target.getClass(); - return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this); - } - - /** - * target:目标类 - * proxy:代理类 - * method:目标方法 - * args:目标方法参数 - */ - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - System.out.println("before method"); - Object result = null; - try { - result = method.invoke(target, args); - } catch (Exception e) { - System.out.println("ex:" + e.getMessage()); - throw e;//代理类不要生吞异常 - } finally { - System.out.println("after method"); - } - return result; - } - -} diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/staticproxy/Client.java b/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/staticproxy/Client.java deleted file mode 100644 index 190477e5..00000000 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/staticproxy/Client.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.lastwhisper.proxy.staticproxy; - -/** - * Created by cat on 2017-02-27. - */ -public class Client { - - public static void main(String[] args){ - Proxy subject = new Proxy(new RealSubject()); - subject.request(); - } -} diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/staticproxy/Proxy.java b/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/staticproxy/Proxy.java deleted file mode 100644 index 17717bb0..00000000 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/staticproxy/Proxy.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.lastwhisper.proxy.staticproxy; - -/** - * @author lastwhisper - */ -public class Proxy { - private Subject target; - - public Proxy(Subject target) { - this.target = target; - } - - public void request() { - System.out.println("before method"); - target.request(); - System.out.println("after method"); - } - - public void response() { - System.out.println("before method"); - target.response(); - System.out.println("after method"); - } -} diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/staticproxy/RealSubject.java b/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/staticproxy/RealSubject.java deleted file mode 100644 index 0b69fa8d..00000000 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/staticproxy/RealSubject.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.proxy.staticproxy; - -/** - * @author lastwhisper - */ -public class RealSubject implements Subject { - @Override - public void request() { - System.out.println("RealSubject request to do"); - } - - @Override - public void response() { - System.out.println("RealSubject response to do"); - } -} diff --git a/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/staticproxy/Subject.java b/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/staticproxy/Subject.java deleted file mode 100644 index b6a1746e..00000000 --- a/springboot-aop/principle/src/main/java/cn/lastwhisper/proxy/staticproxy/Subject.java +++ /dev/null @@ -1,10 +0,0 @@ -package cn.lastwhisper.proxy.staticproxy; - -/** - * @author lastwhisper - */ -public interface Subject { - public void request(); - // 新增接口,静态代理需要重新编写代理的代码,而动态代理不用 - public void response(); -} diff --git a/springboot-aop/principle/src/test/java/cn/lastwhisper/ProxyDemoApplicationTests.java b/springboot-aop/principle/src/test/java/cn/lastwhisper/ProxyDemoApplicationTests.java deleted file mode 100644 index d7b2c11f..00000000 --- a/springboot-aop/principle/src/test/java/cn/lastwhisper/ProxyDemoApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class ProxyDemoApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/springboot-integration-examples/README.md b/springboot-integration-examples/README.md deleted file mode 100644 index ba940299..00000000 --- a/springboot-integration-examples/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# springboot-integration-examples - -``` -├─springboot-banner banner -│ -├─springboot-aoplog aop日志 -│ -├─springboot-dubbo-tcc-instance dubbot与tcc实例 -│ -├─springboot-dubbo-tcc-rt dubbot与tcc实例 -│ -├─springboot-duboo dubbo实例 -│ -├─springboot-duboo-filter dubbo过滤器实例 -│ -├─springboot-flyway flyway -│ -├─springboot-flyway-old -│ -├─springboot-mybatisplus mybatisplus -│ -├─springboot-oss oss -│ -├─springboot-simple-websocket 原生websocket -│ -├─springboot-websocket spring封装原生websocket -│ -├─springboot-websocket-stomp websocket结合stomp -│ -├─springboot-websocket-stomp-chat-cluster 聊天室集群 -│ -├─springboot-websocket-stomp-chat-single 聊天室单机 -│ -├─springboot-wx 微信小程序 -│ -├─spring-dubbo -│ -├─spring-springsecurity -│ -├─spring-thymeleaf -│ -└─spring-validated - -``` - diff --git a/springboot-integration-examples/spring-dubbo/consumer/pom.xml b/springboot-integration-examples/spring-dubbo/consumer/pom.xml deleted file mode 100644 index dd983887..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/pom.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - spring-dubbo - cn.lastwhisper.dubbo - 1.0-SNAPSHOT - - 4.0.0 - - cn.lastwhisper.dubbo - consumer - - consumer - - http://www.example.com - - - UTF-8 - 1.7 - 1.7 - - - - - junit - junit - 4.11 - test - - - - - - - - - maven-clean-plugin - 3.1.0 - - - - maven-resources-plugin - 3.0.2 - - - maven-compiler-plugin - 3.8.0 - - - maven-surefire-plugin - 2.22.1 - - - maven-jar-plugin - 3.0.2 - - - maven-install-plugin - 2.5.2 - - - maven-deploy-plugin - 2.8.2 - - - - maven-site-plugin - 3.7.1 - - - maven-project-info-reports-plugin - 3.0.0 - - - - - diff --git a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/ConsumerClient.java b/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/ConsumerClient.java deleted file mode 100644 index 8764ae2b..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/ConsumerClient.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.lastwhisper.dubbo; - -import com.alibaba.dubbo.rpc.RpcContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.time.Duration; -import java.time.Instant; -import java.util.Scanner; -import java.util.concurrent.Future; - -public class ConsumerClient { - public static void main(String[] args) throws Exception { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-consumer.xml"); - context.start(); - while (true){ - Scanner scanner = new Scanner(System.in); - String message = scanner.next(); - DemoService demoService = (DemoService) context.getBean("consumerService"); // 获取远程服务代理 - // 测试负载均衡 - //for (int i = 0; i < 10; i++) { - // String hello = demoService.sayHello(message+i); // 执行远程方法 - // System.out.println(hello); // 显示调用结果 - //} - - // 测试同步调用 //关闭超时时间 - //Instant start = Instant.now(); - //demoService.sayHello(message);//业务3秒 - //Instant end = Instant.now(); - //demoService.sayHello2(message);//业务4秒 - //Instant end2 = Instant.now(); - ////sayHello执行完成耗时3127 - ////ayHello2执行完成耗时7129 - //System.out.println("sayHello执行完成耗时"+ Duration.between(start,end).toMillis()); - //System.out.println("sayHello2执行完成耗时"+ Duration.between(start,end2).toMillis()); - // 测试异步调用 - Instant start = Instant.now(); - demoService.sayHello(message);//业务3秒 - Future sendFuture = RpcContext.getContext().getFuture(); - Instant end = Instant.now(); - demoService.sayHello2(message);//业务4秒 - Future sendFuture2 = RpcContext.getContext().getFuture(); - Instant end2 = Instant.now(); - //sayHello执行完成耗时37 - //sayHello2执行完成耗时38 - System.out.println(sendFuture.get()+" sayHello执行完成耗时"+ Duration.between(start,end).toMillis()); - System.out.println(sendFuture2.get()+" sayHello2执行完成耗时"+ Duration.between(start,end2).toMillis()); - - } - } -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/DemoService.java b/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/DemoService.java deleted file mode 100644 index 6bea534a..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/DemoService.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.dubbo; - -import java.util.List; - -/** - * @author lastwhisper - */ -public interface DemoService { - String sayHello(String name); - String sayHello2(String name); - - List mergerTest(String message); -} diff --git a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/FilterConsumerClient.java b/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/FilterConsumerClient.java deleted file mode 100644 index f812e5ee..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/FilterConsumerClient.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.lastwhisper.dubbo; - -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.util.Scanner; - -public class FilterConsumerClient { - public static void main(String[] args) throws Exception { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-consumer.xml"); - context.start(); - while (true) { - Scanner scanner = new Scanner(System.in); - String message = scanner.next(); - DemoService demoService = (DemoService) context.getBean("consumerService"); // 获取远程服务代理 - System.out.println(demoService.sayHello(message)); - } - } -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/MyMock.java b/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/MyMock.java deleted file mode 100644 index 75d50110..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/MyMock.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.lastwhisper.dubbo; - -import java.util.List; - -/** - * @author lastwhisper - */ -public class MyMock implements DemoService { - - @Override - public String sayHello(String name) { - return "抱歉,订单人数过多,请稍后重试"; - } - - @Override - public String sayHello2(String name) { - return "抱歉,订单人数过多,请稍后重试"; - } - - @Override - public List mergerTest(String message) { - return null; - } -} diff --git a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/MyStub.java b/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/MyStub.java deleted file mode 100644 index f62ef57e..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/MyStub.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.lastwhisper.dubbo; - -import java.util.List; - -/** - * @author lastwhisper - */ -public class MyStub implements DemoService { - - // 注入Proxy的构造函数 - private final DemoService demoService; - - public MyStub(DemoService demoService) { - this.demoService = demoService; - } - - @Override - public String sayHello(String name) { - System.out.println("sayHello ");//被调用直接打印 - if ("123".equals(name)) { - return "抱歉该值无法接受";//返回 - } else { - name = "sayHello " + name; - return this.demoService.sayHello(name);//返回 - } - } - - @Override - public String sayHello2(String name) { - System.out.println("sayHello2"); - return this.sayHello2(name); - } - - @Override - public List mergerTest(String message) { - System.out.println("mergerTest"); - return this.mergerTest(message); - } - - -} diff --git a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/ZipkinConsumerClient.java b/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/ZipkinConsumerClient.java deleted file mode 100644 index 2a0d0274..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/ZipkinConsumerClient.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.lastwhisper.dubbo; - -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.util.Scanner; - -public class ZipkinConsumerClient { - public static void main(String[] args) throws Exception { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-consumer.xml"); - context.start(); - while (true) { - Scanner scanner = new Scanner(System.in); - String message = scanner.next(); - DemoService demoService = (DemoService) context.getBean("consumerService"); // 获取远程服务代理 - System.out.println(demoService.sayHello(message)); - } - } -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/controller/ConsumerControllerClient.java b/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/controller/ConsumerControllerClient.java deleted file mode 100644 index 268d69e0..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/controller/ConsumerControllerClient.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.lastwhisper.dubbo.controller; - -import cn.lastwhisper.dubbo.DemoService; -import com.alibaba.dubbo.rpc.RpcContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.time.Duration; -import java.time.Instant; -import java.util.Scanner; -import java.util.concurrent.Future; - -public class ConsumerControllerClient { - public static void main(String[] args) throws Exception { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-consumer.xml"); - context.start(); - while (true){ - Scanner scanner = new Scanner(System.in); - String message = scanner.next(); - DemoService demoService = (DemoService) context.getBean("consumerService"); // 获取远程服务代理 - - for (int i = 0; i < 10; i++) { - demoService.sayHello(message+i); - } - } - } -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/controller/ConsumerControllerClient2.java b/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/controller/ConsumerControllerClient2.java deleted file mode 100644 index 6f8376f2..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/controller/ConsumerControllerClient2.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.lastwhisper.dubbo.controller; - -import cn.lastwhisper.dubbo.DemoService; -import com.alibaba.dubbo.rpc.RpcContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.time.Duration; -import java.time.Instant; -import java.util.Scanner; -import java.util.concurrent.Future; - -public class ConsumerControllerClient2 { - public static void main(String[] args) throws Exception { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-consumer.xml"); - context.start(); - while (true){ - Scanner scanner = new Scanner(System.in); - String message = scanner.next(); - DemoService demoService = (DemoService) context.getBean("consumerService"); // 获取远程服务代理 - for (int i = 0; i < 10; i++) { - demoService.sayHello(message+i); - } - } - } -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/group/GroupConsumerClient.java b/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/group/GroupConsumerClient.java deleted file mode 100644 index 06c67fe9..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/group/GroupConsumerClient.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.lastwhisper.dubbo.group; - -import cn.lastwhisper.dubbo.DemoService; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.util.List; -import java.util.Scanner; - -public class GroupConsumerClient { - public static void main(String[] args) throws Exception { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-group-consumer.xml"); - context.start(); - while (true) { - Scanner scanner = new Scanner(System.in); - String message = scanner.next(); - DemoService demoService = (DemoService) context.getBean("consumerService"); // 获取远程服务代理 - - String hello = demoService.sayHello(message ); // 执行远程方法 - List strings = demoService.mergerTest(message); - for (String str : strings) { - System.out.println(str); - } - //System.out.println(hello); // 显示调用结果 - } - } -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/stub/StubConsumerClient.java b/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/stub/StubConsumerClient.java deleted file mode 100644 index dbcc6619..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/stub/StubConsumerClient.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.lastwhisper.dubbo.stub; - -import cn.lastwhisper.dubbo.DemoService; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.util.Scanner; - -public class StubConsumerClient { - public static void main(String[] args) throws Exception { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-stub-consumer.xml"); - context.start(); - while (true) { - Scanner scanner = new Scanner(System.in); - String message = scanner.next(); - DemoService demoService = (DemoService) context.getBean("consumerService"); // 获取远程服务代理 - - String hello = demoService.sayHello(message); // 执行远程方法 - System.out.println(hello); // 显示调用结果 - } - } -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/version/VersionConsumerClient.java b/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/version/VersionConsumerClient.java deleted file mode 100644 index ef31de78..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/src/main/java/cn/lastwhisper/dubbo/version/VersionConsumerClient.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.lastwhisper.dubbo.version; - -import cn.lastwhisper.dubbo.DemoService; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.util.List; -import java.util.Scanner; - -public class VersionConsumerClient { - public static void main(String[] args) throws Exception { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-version-consumer.xml"); - context.start(); - while (true) { - Scanner scanner = new Scanner(System.in); - String message = scanner.next(); - DemoService demoService = (DemoService) context.getBean("consumerService"); // 获取远程服务代理 - - String hello = demoService.sayHello(message ); // 执行远程方法 - System.out.println(hello); // 显示调用结果 - } - } -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-dubbo/consumer/src/main/resources/applicationContext-consumer.xml b/springboot-integration-examples/spring-dubbo/consumer/src/main/resources/applicationContext-consumer.xml deleted file mode 100644 index 4958732e..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/src/main/resources/applicationContext-consumer.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - diff --git a/springboot-integration-examples/spring-dubbo/consumer/src/main/resources/applicationContext-group-consumer.xml b/springboot-integration-examples/spring-dubbo/consumer/src/main/resources/applicationContext-group-consumer.xml deleted file mode 100644 index ea7ad486..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/src/main/resources/applicationContext-group-consumer.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - diff --git a/springboot-integration-examples/spring-dubbo/consumer/src/main/resources/applicationContext-stub-consumer.xml b/springboot-integration-examples/spring-dubbo/consumer/src/main/resources/applicationContext-stub-consumer.xml deleted file mode 100644 index 6a21555c..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/src/main/resources/applicationContext-stub-consumer.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - diff --git a/springboot-integration-examples/spring-dubbo/consumer/src/main/resources/applicationContext-version-consumer.xml b/springboot-integration-examples/spring-dubbo/consumer/src/main/resources/applicationContext-version-consumer.xml deleted file mode 100644 index c63d5ec5..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/src/main/resources/applicationContext-version-consumer.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - diff --git a/springboot-integration-examples/spring-dubbo/consumer/src/test/java/cn/lastwhisper/dubbo/AppTest.java b/springboot-integration-examples/spring-dubbo/consumer/src/test/java/cn/lastwhisper/dubbo/AppTest.java deleted file mode 100644 index 7fb1dee2..00000000 --- a/springboot-integration-examples/spring-dubbo/consumer/src/test/java/cn/lastwhisper/dubbo/AppTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.lastwhisper.dubbo; - -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -/** - * Unit test for simple App. - */ -public class AppTest -{ - /** - * Rigorous Test :-) - */ - @Test - public void shouldAnswerWithTrue() - { - assertTrue( true ); - } -} diff --git a/springboot-integration-examples/spring-dubbo/pom.xml b/springboot-integration-examples/spring-dubbo/pom.xml deleted file mode 100644 index eb49d00f..00000000 --- a/springboot-integration-examples/spring-dubbo/pom.xml +++ /dev/null @@ -1,146 +0,0 @@ - - - 4.0.0 - - cn.lastwhisper.dubbo - spring-dubbo - pom - 1.0-SNAPSHOT - - provider - consumer - - - UTF-8 - 1.7 - 1.7 - - - - - - - io.zipkin.brave - brave-bom - 5.5.0 - pom - import - - - - io.zipkin.reporter2 - zipkin-reporter-bom - 2.7.10 - pom - import - - - - - - - - - io.zipkin.brave - brave-instrumentation-dubbo-rpc - - - - io.zipkin.brave - brave-spring-beans - - - - io.zipkin.brave - brave-context-slf4j - - - - io.zipkin.reporter2 - zipkin-sender-okhttp3 - - - - com.101tec - zkclient - 0.9 - - - org.apache.zookeeper - zookeeper - 3.4.7 - pom - - - com.alibaba - dubbo - 2.5.3 - - - io.netty - netty-all - 4.1.25.Final - - - commons-logging - commons-logging - 1.2 - - - org.javassist - javassist - 3.21.0-GA - - - log4j - log4j - 1.2.17 - - - - org.springframework - spring-context - 4.3.18.RELEASE - - - org.springframework - spring-context-support - 4.3.18.RELEASE - - - org.springframework - spring-core - 4.3.18.RELEASE - - - org.springframework - spring-beans - 4.3.18.RELEASE - - - org.springframework - spring-aop - 4.3.18.RELEASE - - - org.springframework - spring-aspects - 4.3.18.RELEASE - - - org.springframework - spring-expression - 4.3.18.RELEASE - - - junit - junit - 4.12 - test - - - - - \ No newline at end of file diff --git a/springboot-integration-examples/spring-dubbo/provider/pom.xml b/springboot-integration-examples/spring-dubbo/provider/pom.xml deleted file mode 100644 index 4562d095..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/pom.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - spring-dubbo - cn.lastwhisper.dubbo - 1.0-SNAPSHOT - - 4.0.0 - - cn.lastwhisper.dubbo - provider - - provider - - http://www.example.com - - - UTF-8 - 1.7 - 1.7 - - - - - junit - junit - 4.11 - test - - - - - - - - - maven-clean-plugin - 3.1.0 - - - - maven-resources-plugin - 3.0.2 - - - maven-compiler-plugin - 3.8.0 - - - maven-surefire-plugin - 2.22.1 - - - maven-jar-plugin - 3.0.2 - - - maven-install-plugin - 2.5.2 - - - maven-deploy-plugin - 2.8.2 - - - - maven-site-plugin - 3.7.1 - - - maven-project-info-reports-plugin - 3.0.0 - - - - - diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/DemoService.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/DemoService.java deleted file mode 100644 index 16db169e..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/DemoService.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.lastwhisper.dubbo; - -import java.util.List; - -/** - * @author lastwhisper - */ -public interface DemoService { - String sayHello(String name); - - String sayHello2(String name); - - List mergerTest(String message); -} diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/DemoServiceImpl.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/DemoServiceImpl.java deleted file mode 100644 index 9a331739..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/DemoServiceImpl.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.lastwhisper.dubbo; - -import java.util.List; - -public class DemoServiceImpl implements DemoService { - public String sayHello(String name) { - System.out.println("Hello " + name); - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return "Hello " + name; - } - - @Override - public String sayHello2(String name) { - try { - Thread.sleep(4000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public List mergerTest(String message) { - return null; - } -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/MyMock.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/MyMock.java deleted file mode 100644 index 75d50110..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/MyMock.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.lastwhisper.dubbo; - -import java.util.List; - -/** - * @author lastwhisper - */ -public class MyMock implements DemoService { - - @Override - public String sayHello(String name) { - return "抱歉,订单人数过多,请稍后重试"; - } - - @Override - public String sayHello2(String name) { - return "抱歉,订单人数过多,请稍后重试"; - } - - @Override - public List mergerTest(String message) { - return null; - } -} diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/MyStub.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/MyStub.java deleted file mode 100644 index f62ef57e..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/MyStub.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.lastwhisper.dubbo; - -import java.util.List; - -/** - * @author lastwhisper - */ -public class MyStub implements DemoService { - - // 注入Proxy的构造函数 - private final DemoService demoService; - - public MyStub(DemoService demoService) { - this.demoService = demoService; - } - - @Override - public String sayHello(String name) { - System.out.println("sayHello ");//被调用直接打印 - if ("123".equals(name)) { - return "抱歉该值无法接受";//返回 - } else { - name = "sayHello " + name; - return this.demoService.sayHello(name);//返回 - } - } - - @Override - public String sayHello2(String name) { - System.out.println("sayHello2"); - return this.sayHello2(name); - } - - @Override - public List mergerTest(String message) { - System.out.println("mergerTest"); - return this.mergerTest(message); - } - - -} diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/ProviderClient.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/ProviderClient.java deleted file mode 100644 index 137eedd6..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/ProviderClient.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.lastwhisper.dubbo; - -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.io.IOException; - -/** - * @author lastwhisper - */ -public class ProviderClient { - public static void main(String[] args) { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-provider.xml"); - context.start(); - - try { - System.in.read(); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/controller/ProviderControllerClient.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/controller/ProviderControllerClient.java deleted file mode 100644 index 9df33d87..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/controller/ProviderControllerClient.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.lastwhisper.dubbo.controller; - -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.io.IOException; - -/** - * 连接控制 - * @author lastwhisper - */ -public class ProviderControllerClient { - public static void main(String[] args) { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-controller-provider.xml"); - context.start(); - - try { - System.in.read(); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/filter/MyFilter.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/filter/MyFilter.java deleted file mode 100644 index 548bac54..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/filter/MyFilter.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.lastwhisper.dubbo.filter; - -import com.alibaba.dubbo.rpc.*; - -/** - * @author lastwhisper - */ -public class MyFilter implements Filter { - @Override - public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { - - System.out.println("服务调用之前,方法名:" + invocation.getMethodName()); - //调用后续服务 - Result invoke = invoker.invoke(invocation); - - System.out.println("服务调用之后"); - - return invoke; - } -} diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/group/GroupProviderClient.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/group/GroupProviderClient.java deleted file mode 100644 index 71c95070..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/group/GroupProviderClient.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.lastwhisper.dubbo.group; - -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.io.IOException; - -/** - * @author lastwhisper - */ -public class GroupProviderClient { - public static void main(String[] args) { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-group-provider.xml"); - context.start(); - - try { - System.in.read(); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/group/GroupServiceImplA.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/group/GroupServiceImplA.java deleted file mode 100644 index 6a44ffba..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/group/GroupServiceImplA.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.lastwhisper.dubbo.group; - -import cn.lastwhisper.dubbo.DemoService; - -import java.util.Arrays; -import java.util.List; - -public class GroupServiceImplA implements DemoService { - public String sayHello(String name) { - System.out.println("Hello group A " + name); - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return "Hello group A " + name; - } - - @Override - public String sayHello2(String name) { - try { - Thread.sleep(4000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public List mergerTest(String message) { - String str = "Group A =" + message; - return Arrays.asList(str); - } -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/group/GroupServiceImplB.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/group/GroupServiceImplB.java deleted file mode 100644 index 8986b4be..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/group/GroupServiceImplB.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.lastwhisper.dubbo.group; - -import cn.lastwhisper.dubbo.DemoService; - -import java.util.Arrays; -import java.util.List; - -public class GroupServiceImplB implements DemoService { - public String sayHello(String name) { - System.out.println("Hello group B " + name); - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return "Hello group B " + name; - } - - @Override - public String sayHello2(String name) { - try { - Thread.sleep(4000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public List mergerTest(String message) { - String str = "Group B =" + message; - return Arrays.asList(str); - } -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/loadbalance/LoadBalanceProviderClient_1.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/loadbalance/LoadBalanceProviderClient_1.java deleted file mode 100644 index ac015ffd..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/loadbalance/LoadBalanceProviderClient_1.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.lastwhisper.dubbo.loadbalance; - -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.io.IOException; - -/** - * @author lastwhisper - */ -public class LoadBalanceProviderClient_1 { - public static void main(String[] args) { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-loadbalance-provider-1.xml"); - context.start(); - - try { - System.in.read(); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/loadbalance/LoadBalanceProviderClient_2.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/loadbalance/LoadBalanceProviderClient_2.java deleted file mode 100644 index c31200b5..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/loadbalance/LoadBalanceProviderClient_2.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.lastwhisper.dubbo.loadbalance; - -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.io.IOException; - -/** - * @author lastwhisper - */ -public class LoadBalanceProviderClient_2 { - public static void main(String[] args) { - ClassPathXmlApplicationContext context = - new ClassPathXmlApplicationContext("applicationContext-loadbalance-provider-2.xml"); - context.start(); - - try { - System.in.read(); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/loadbalance/LoadBalanceProviderClient_3.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/loadbalance/LoadBalanceProviderClient_3.java deleted file mode 100644 index aa2bae8e..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/loadbalance/LoadBalanceProviderClient_3.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.lastwhisper.dubbo.loadbalance; - -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.io.IOException; - -/** - * @author lastwhisper - */ -public class LoadBalanceProviderClient_3 { - public static void main(String[] args) { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-loadbalance-provider-3.xml"); - context.start(); - - try { - System.in.read(); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/stub/StubProviderClient.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/stub/StubProviderClient.java deleted file mode 100644 index 5a299979..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/stub/StubProviderClient.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.lastwhisper.dubbo.stub; - -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.io.IOException; - -/** - * @author lastwhisper - */ -public class StubProviderClient { - // 测试本地存根和本地伪装 - public static void main(String[] args) { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-stub-provider.xml"); - context.start(); - - try { - System.in.read(); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/stub/StubServiceImpl.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/stub/StubServiceImpl.java deleted file mode 100644 index 8b00315a..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/stub/StubServiceImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.lastwhisper.dubbo.stub; - -import cn.lastwhisper.dubbo.DemoService; - -import java.util.Arrays; -import java.util.List; - -public class StubServiceImpl implements DemoService { - public String sayHello(String name) { - System.out.println("Hello stub " + name); - try { - Thread.sleep(4000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return "Hello-provider-stub " + name; - } - - @Override - public String sayHello2(String name) { - try { - Thread.sleep(4000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public List mergerTest(String message) { - String str = "Group A =" + message; - return Arrays.asList(str); - } -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/version/VersionProviderClient.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/version/VersionProviderClient.java deleted file mode 100644 index b3583c6b..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/version/VersionProviderClient.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.lastwhisper.dubbo.version; - -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.io.IOException; - -/** - * @author lastwhisper - */ -public class VersionProviderClient { - public static void main(String[] args) { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-Version-provider.xml"); - context.start(); - - try { - System.in.read(); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/version/VersionServiceImplA.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/version/VersionServiceImplA.java deleted file mode 100644 index bb567384..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/version/VersionServiceImplA.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.lastwhisper.dubbo.version; - -import cn.lastwhisper.dubbo.DemoService; - -import java.util.Arrays; -import java.util.List; - -public class VersionServiceImplA implements DemoService { - public String sayHello(String name) { - System.out.println("Hello group A version 1.0.0 " + name); - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return "Hello group A version 1.0.0" + name; - } - - @Override - public String sayHello2(String name) { - try { - Thread.sleep(4000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public List mergerTest(String message) { - String str = "Group A =" + message; - return Arrays.asList(str); - } -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/version/VersionServiceImplB.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/version/VersionServiceImplB.java deleted file mode 100644 index e49a321b..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/version/VersionServiceImplB.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.lastwhisper.dubbo.version; - -import cn.lastwhisper.dubbo.DemoService; - -import java.util.Arrays; -import java.util.List; - -public class VersionServiceImplB implements DemoService { - public String sayHello(String name) { - System.out.println("Hello group A version 2.0.0 " + name); - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return "Hello group A version 2.0.0" + name; - } - - @Override - public String sayHello2(String name) { - try { - Thread.sleep(4000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public List mergerTest(String message) { - String str = "Group B =" + message; - return Arrays.asList(str); - } -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/zipkin/ZipkinProviderClient.java b/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/zipkin/ZipkinProviderClient.java deleted file mode 100644 index a2353d43..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/java/cn/lastwhisper/dubbo/zipkin/ZipkinProviderClient.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.lastwhisper.dubbo.zipkin; - -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.io.IOException; - -/** - * @author lastwhisper - */ -public class ZipkinProviderClient { - public static void main(String[] args) { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-zipkin-provider.xml"); - context.start(); - - try { - System.in.read(); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter b/springboot-integration-examples/spring-dubbo/provider/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter deleted file mode 100644 index 05b928bf..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter +++ /dev/null @@ -1 +0,0 @@ -MyFilterExt=cn.lastwhisper.dubbo.filter.MyFilter \ No newline at end of file diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-Version-provider.xml b/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-Version-provider.xml deleted file mode 100644 index 4ccc5016..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-Version-provider.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-controller-provider.xml b/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-controller-provider.xml deleted file mode 100644 index 495033d6..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-controller-provider.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-group-provider.xml b/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-group-provider.xml deleted file mode 100644 index c1f65b8c..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-group-provider.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-loadbalance-provider-1.xml b/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-loadbalance-provider-1.xml deleted file mode 100644 index a907aa8e..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-loadbalance-provider-1.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-loadbalance-provider-2.xml b/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-loadbalance-provider-2.xml deleted file mode 100644 index c4f922de..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-loadbalance-provider-2.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-loadbalance-provider-3.xml b/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-loadbalance-provider-3.xml deleted file mode 100644 index ec6dce9f..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-loadbalance-provider-3.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-provider.xml b/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-provider.xml deleted file mode 100644 index 268b912d..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-provider.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-stub-provider.xml b/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-stub-provider.xml deleted file mode 100644 index 8c1c30fd..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-stub-provider.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-zipkin-provider.xml b/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-zipkin-provider.xml deleted file mode 100644 index 893c22b6..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/main/resources/applicationContext-zipkin-provider.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/springboot-integration-examples/spring-dubbo/provider/src/test/java/cn/lastwhisper/dubbo/AppTest.java b/springboot-integration-examples/spring-dubbo/provider/src/test/java/cn/lastwhisper/dubbo/AppTest.java deleted file mode 100644 index 7fb1dee2..00000000 --- a/springboot-integration-examples/spring-dubbo/provider/src/test/java/cn/lastwhisper/dubbo/AppTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.lastwhisper.dubbo; - -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -/** - * Unit test for simple App. - */ -public class AppTest -{ - /** - * Rigorous Test :-) - */ - @Test - public void shouldAnswerWithTrue() - { - assertTrue( true ); - } -} diff --git a/springboot-integration-examples/spring-springsecurity/pom.xml b/springboot-integration-examples/spring-springsecurity/pom.xml deleted file mode 100644 index 17cdc158..00000000 --- a/springboot-integration-examples/spring-springsecurity/pom.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - 4.0.0 - - cn.lastwhisper - springsecurity - 1.0-SNAPSHOT - war - - - UTF-8 - 5.0.5.RELEASE - - - - - org.springframework.security - spring-security-web - ${spring.version} - - - org.springframework.security - spring-security-config - ${spring.version} - - - - - junit - junit - 4.11 - test - - - - - javax.servlet - servlet-api - 2.5 - provided - - - - - - org.apache.tomcat.maven - tomcat7-maven-plugin - 2.2 - - - 8080 - - / - - - - - \ No newline at end of file diff --git a/springboot-integration-examples/spring-springsecurity/src/main/java/cn/lastwhisper/springsecurity/UserDetailsServiceImpl.java b/springboot-integration-examples/spring-springsecurity/src/main/java/cn/lastwhisper/springsecurity/UserDetailsServiceImpl.java deleted file mode 100644 index 36a9725a..00000000 --- a/springboot-integration-examples/spring-springsecurity/src/main/java/cn/lastwhisper/springsecurity/UserDetailsServiceImpl.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.lastwhisper.springsecurity; - -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; - -import java.util.ArrayList; -import java.util.List; - -public class UserDetailsServiceImpl implements UserDetailsService { - @Override - public UserDetails loadUserByUsername(String s) throws - UsernameNotFoundException { - System.out.println("经过UserDetailsServiceImpl"); - //构建角色集合,项目中此处应该是根据用户名查询用户的角色列表 - List grantedAuthors = new ArrayList<>(); - grantedAuthors.add(new SimpleGrantedAuthority("ROLE_ADMIN")); - return new User(s, "$2a$10$61ogZY7EXsMDWeVGQpDq3OBF1.phaUu7.xrwLyWFTOu8woE08zMIW", - grantedAuthors); - } -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-springsecurity/src/main/resources/spring-security.xml b/springboot-integration-examples/spring-springsecurity/src/main/resources/spring-security.xml deleted file mode 100644 index 5a33719e..00000000 --- a/springboot-integration-examples/spring-springsecurity/src/main/resources/spring-security.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/springboot-integration-examples/spring-springsecurity/src/main/webapp/WEB-INF/web.xml b/springboot-integration-examples/spring-springsecurity/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 4fb5a663..00000000 --- a/springboot-integration-examples/spring-springsecurity/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - contextConfigLocation - classpath:spring-security.xml - - - - org.springframework.web.context.ContextLoaderListener - - - - springSecurityFilterChain - org.springframework.web.filter.DelegatingFilterProxy - - - springSecurityFilterChain - /* - - \ No newline at end of file diff --git a/springboot-integration-examples/spring-springsecurity/src/main/webapp/index.html b/springboot-integration-examples/spring-springsecurity/src/main/webapp/index.html deleted file mode 100644 index d69fee62..00000000 --- a/springboot-integration-examples/spring-springsecurity/src/main/webapp/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - index - - - spring security - - \ No newline at end of file diff --git a/springboot-integration-examples/spring-springsecurity/src/main/webapp/login.html b/springboot-integration-examples/spring-springsecurity/src/main/webapp/login.html deleted file mode 100644 index 77e90039..00000000 --- a/springboot-integration-examples/spring-springsecurity/src/main/webapp/login.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - login - - -

- - - - - - - - - -
username
password
- -
- - \ No newline at end of file diff --git a/springboot-integration-examples/spring-springsecurity/src/main/webapp/login_error.html b/springboot-integration-examples/spring-springsecurity/src/main/webapp/login_error.html deleted file mode 100644 index 0273fd14..00000000 --- a/springboot-integration-examples/spring-springsecurity/src/main/webapp/login_error.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - login error - - -username or password error! - - \ No newline at end of file diff --git a/springboot-integration-examples/spring-springsecurity/src/test/java/cn/lastwhisper/bcrypt/BcryptTest.java b/springboot-integration-examples/spring-springsecurity/src/test/java/cn/lastwhisper/bcrypt/BcryptTest.java deleted file mode 100644 index 80f3f3eb..00000000 --- a/springboot-integration-examples/spring-springsecurity/src/test/java/cn/lastwhisper/bcrypt/BcryptTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.lastwhisper.bcrypt; - -import org.junit.Assert; -import org.junit.Test; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; - - -/** - * - * @author lastwhisper - * @date 2019/11/19 - */ -public class BcryptTest { - - @Test - public void test(){ - // Create an encoder with strength 16 - BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); - String result = encoder.encode("123456"); - System.out.println(result); - Assert.assertTrue(encoder.matches("123456", result)); - } - -} diff --git a/springboot-integration-examples/spring-thymeleaf/pom.xml b/springboot-integration-examples/spring-thymeleaf/pom.xml deleted file mode 100644 index de1ffde7..00000000 --- a/springboot-integration-examples/spring-thymeleaf/pom.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - 4.0.0 - - cn.lastwhisper - spring-thymeleaf - 1.0-SNAPSHOT - - - - org.thymeleaf - thymeleaf - 3.0.11.RELEASE - - - \ No newline at end of file diff --git a/springboot-integration-examples/spring-thymeleaf/src/main/java/cn/lastwhisper/thymeleaf/Test.java b/springboot-integration-examples/spring-thymeleaf/src/main/java/cn/lastwhisper/thymeleaf/Test.java deleted file mode 100644 index 7065a5b5..00000000 --- a/springboot-integration-examples/spring-thymeleaf/src/main/java/cn/lastwhisper/thymeleaf/Test.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.lastwhisper.thymeleaf; - -import org.thymeleaf.TemplateEngine; -import org.thymeleaf.context.Context; -import org.thymeleaf.templatemode.TemplateMode; -import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; - -import java.io.File; -import java.io.PrintWriter; -import java.util.HashMap; -import java.util.Map; - -/** - * - * @author lastwhisper - * @date 2019/11/19 - */ -public class Test { - public static void main(String[] args) { - // 1.上下文 - Context context = new Context(); - //创建数据模型 - Map dataModel = new HashMap(1); - dataModel.put("name", "青橙电商系统"); - context.setVariables(dataModel); - // 2.准备文件 - File dest = new File("d:/test_out.html"); - // 3.生成页面 - try { - PrintWriter writer = new PrintWriter(dest, "UTF-8"); - //模板解析器 - ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver(); - //模板模型 - resolver.setTemplateMode(TemplateMode.HTML); - //后缀 - resolver.setSuffix(".html"); - //创建模板引擎 - TemplateEngine engine = new TemplateEngine(); - //设置模板解析器 - engine.setTemplateResolver(resolver); - //执行模板引擎 - engine.process("test", context, writer); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/springboot-integration-examples/spring-thymeleaf/src/main/resources/test.html b/springboot-integration-examples/spring-thymeleaf/src/main/resources/test.html deleted file mode 100644 index d919f7bf..00000000 --- a/springboot-integration-examples/spring-thymeleaf/src/main/resources/test.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - thymeleaf入门demo - - - - - \ No newline at end of file diff --git a/springboot-integration-examples/spring-validated/.mvn/wrapper/MavenWrapperDownloader.java b/springboot-integration-examples/spring-validated/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index 7f91a56e..00000000 --- a/springboot-integration-examples/spring-validated/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF 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 - - https://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. -*/ - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.Properties; - -public class MavenWrapperDownloader { - - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = - "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if (mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if (mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: : " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if (!outputFile.getParentFile().exists()) { - if (!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/springboot-integration-examples/spring-validated/.mvn/wrapper/maven-wrapper.jar b/springboot-integration-examples/spring-validated/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 01e67997..00000000 Binary files a/springboot-integration-examples/spring-validated/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/springboot-integration-examples/spring-validated/.mvn/wrapper/maven-wrapper.properties b/springboot-integration-examples/spring-validated/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index cd0d451c..00000000 --- a/springboot-integration-examples/spring-validated/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip diff --git a/springboot-integration-examples/spring-validated/pom.xml b/springboot-integration-examples/spring-validated/pom.xml deleted file mode 100644 index ce112841..00000000 --- a/springboot-integration-examples/spring-validated/pom.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.2.0.RELEASE - - - cn.lastwhisper - spring-validated - 0.0.1-SNAPSHOT - spring-validated - 验证注解Spring @Validated学习 - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.junit.vintage - junit-vintage-engine - - - - - org.springframework.boot - spring-boot-starter-web - - - org.hibernate - hibernate-validator - 6.0.17.Final - - - com.fasterxml.jackson.core - jackson-databind - - - org.projectlombok - lombok - 1.18.10 - - - junit - junit - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/spring-validated/src/main/java/cn/lastwhisper/springvalidated/SpringValidatedApplication.java b/springboot-integration-examples/spring-validated/src/main/java/cn/lastwhisper/springvalidated/SpringValidatedApplication.java deleted file mode 100644 index 0971622d..00000000 --- a/springboot-integration-examples/spring-validated/src/main/java/cn/lastwhisper/springvalidated/SpringValidatedApplication.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.lastwhisper.springvalidated; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SpringValidatedApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringValidatedApplication.class, args); - } - -} diff --git a/springboot-integration-examples/spring-validated/src/main/java/cn/lastwhisper/springvalidated/bean/Foo.java b/springboot-integration-examples/spring-validated/src/main/java/cn/lastwhisper/springvalidated/bean/Foo.java deleted file mode 100644 index 6830b9b5..00000000 --- a/springboot-integration-examples/spring-validated/src/main/java/cn/lastwhisper/springvalidated/bean/Foo.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.lastwhisper.springvalidated.bean; - -import lombok.Data; -import lombok.Getter; -import lombok.Setter; - -import javax.validation.constraints.Email; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Pattern; - -@Getter -@Setter -public class Foo { - @NotBlank - private String name; - - //@Min(value = 18) - @Min(value = 18,groups = {Adult.class}) - private Integer age; - - public interface Adult{} - - public interface Minor{} - - @Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$",message = "手机号码格式错误") - @NotBlank(message = "手机号码不能为空") - private String phone; - - @Email(message = "邮箱格式错误") - private String email; - - //... getter setter - -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-validated/src/main/java/cn/lastwhisper/springvalidated/controller/FooController.java b/springboot-integration-examples/spring-validated/src/main/java/cn/lastwhisper/springvalidated/controller/FooController.java deleted file mode 100644 index 1ec865db..00000000 --- a/springboot-integration-examples/spring-validated/src/main/java/cn/lastwhisper/springvalidated/controller/FooController.java +++ /dev/null @@ -1,46 +0,0 @@ -package cn.lastwhisper.springvalidated.controller; - -import cn.lastwhisper.springvalidated.bean.Foo; -import org.springframework.stereotype.Controller; -import org.springframework.validation.BindingResult; -import org.springframework.validation.FieldError; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestMapping; - -@Controller -public class FooController { - - @RequestMapping("/foo") - public String foo(@Validated Foo foo, BindingResult bindingResult) { - if (bindingResult.hasErrors()) { - for (FieldError fieldError : bindingResult.getFieldErrors()) { - //... - } - return "fail"; - } - return "success"; - } - - @RequestMapping("/drink") - public String drink(@Validated({Foo.Adult.class}) Foo foo, BindingResult bindingResult) { - if (bindingResult.hasErrors()) { - for (FieldError fieldError : bindingResult.getFieldErrors()) { - // fieldError - } - return "fail"; - } - return "success"; - } - - @RequestMapping("/live") - public String live(@Validated Foo foo, BindingResult bindingResult) { - if(bindingResult.hasErrors()){ - for (FieldError fieldError : bindingResult.getFieldErrors()) { - //... - } - return "fail"; - } - return "success"; - } - -} \ No newline at end of file diff --git a/springboot-integration-examples/spring-validated/src/test/java/cn/lastwhisper/springvalidated/TestSpringBean.java b/springboot-integration-examples/spring-validated/src/test/java/cn/lastwhisper/springvalidated/TestSpringBean.java deleted file mode 100644 index ca97f1bc..00000000 --- a/springboot-integration-examples/spring-validated/src/test/java/cn/lastwhisper/springvalidated/TestSpringBean.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.lastwhisper.springvalidated; - -import org.junit.jupiter.api.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class TestSpringBean { - - @Test - public void test1() { - } -} \ No newline at end of file diff --git "a/springboot-integration-examples/spring-validated/\345\217\202\350\200\203" "b/springboot-integration-examples/spring-validated/\345\217\202\350\200\203" deleted file mode 100644 index b848b3f2..00000000 --- "a/springboot-integration-examples/spring-validated/\345\217\202\350\200\203" +++ /dev/null @@ -1 +0,0 @@ -https://www.cnkirito.moe/spring-validation/ \ No newline at end of file diff --git a/springboot-integration-examples/springboot-aoplog/pom.xml b/springboot-integration-examples/springboot-aoplog/pom.xml deleted file mode 100644 index b3f0e2b5..00000000 --- a/springboot-integration-examples/springboot-aoplog/pom.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.4.RELEASE - - - cn.lastwhisper - springbootaop - 0.0.1-SNAPSHOT - springboot-aop - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - org.springframework.boot - spring-boot-starter-aop - - - - - org.projectlombok - lombok - 1.18.10 - true - - - - com.baomidou - mybatis-plus-boot-starter - 3.1.1 - - - - - mysql - mysql-connector-java - 5.1.47 - - - - com.alibaba - fastjson - 1.2.62 - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-aoplog/readme.md b/springboot-integration-examples/springboot-aoplog/readme.md deleted file mode 100644 index 9c3971b8..00000000 --- a/springboot-integration-examples/springboot-aoplog/readme.md +++ /dev/null @@ -1 +0,0 @@ -参考:https://blog.csdn.net/kingboyworld/article/details/76099105 diff --git a/springboot-integration-examples/springboot-aoplog/sql/log.sql b/springboot-integration-examples/springboot-aoplog/sql/log.sql deleted file mode 100644 index b989fe0b..00000000 --- a/springboot-integration-examples/springboot-aoplog/sql/log.sql +++ /dev/null @@ -1,39 +0,0 @@ -/* - Navicat Premium Data Transfer - - Source Server : 本地数据库-mysql5.7 - Source Server Type : MySQL - Source Server Version : 50724 - Source Host : localhost:3306 - Source Schema : wxlogin - - Target Server Type : MySQL - Target Server Version : 50724 - File Encoding : 65001 - - Date: 02/05/2019 17:15:00 -*/ - -SET NAMES utf8mb4; -SET FOREIGN_KEY_CHECKS = 0; - --- ---------------------------- --- Table structure for log --- ---------------------------- -DROP TABLE IF EXISTS `log`; -CREATE TABLE `log` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `operateor` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `operateType` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `operateDate` datetime(0) NULL DEFAULT NULL, - `operateResult` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `ip` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; - --- ---------------------------- --- Records of log --- ---------------------------- -INSERT INTO `log` VALUES (12, 'lastwhisper', '添加用户', '2019-05-02 16:16:24', '正常', '0:0:0:0:0:0:0:1'); - -SET FOREIGN_KEY_CHECKS = 1; diff --git a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/SpringbootaopApplication.java b/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/SpringbootaopApplication.java deleted file mode 100644 index d6ff0531..00000000 --- a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/SpringbootaopApplication.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.lastwhisper.springbootaop; - -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@MapperScan("cn.lastwhisper.springbootaop.mapper") //设置mapper接口的扫描包 -@SpringBootApplication -public class SpringbootaopApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringbootaopApplication.class, args); - } - -} diff --git a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/controller/UserController.java b/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/controller/UserController.java deleted file mode 100644 index 27f563f7..00000000 --- a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/controller/UserController.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.lastwhisper.springbootaop.controller; - -import cn.lastwhisper.springbootaop.core.annotation.LogOperation; -import cn.lastwhisper.springbootaop.form.LoginForm; -import cn.lastwhisper.springbootaop.service.UserService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author lastwhisper - */ -@RestController -public class UserController { - - @Autowired - private UserService userService; - - @LogOperation(value = "用户登录") - @RequestMapping(value = "/user/login") - public String add(LoginForm loginForm) { - return userService.login(loginForm.getUsername(), loginForm.getPassword()); - } - -} diff --git a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/annotation/LogOperation.java b/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/annotation/LogOperation.java deleted file mode 100644 index f2b30739..00000000 --- a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/annotation/LogOperation.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.lastwhisper.springbootaop.core.annotation; - -import org.springframework.core.annotation.Order; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 日志注解 - * @author lastwhisper - */ -@Target(ElementType.METHOD) // 方法注解 -@Retention(RetentionPolicy.RUNTIME) // 运行时可见 -public @interface LogOperation { - // 记录日志的操作类型 - String value(); -} \ No newline at end of file diff --git a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/aop/ControllerAroundLog.java b/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/aop/ControllerAroundLog.java deleted file mode 100644 index 658769b4..00000000 --- a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/aop/ControllerAroundLog.java +++ /dev/null @@ -1,62 +0,0 @@ -package cn.lastwhisper.springbootaop.core.aop; - -import cn.lastwhisper.springbootaop.core.common.JoinPointParesUtils; -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.stereotype.Component; -import org.springframework.web.bind.annotation.RequestMapping; - -import java.util.stream.Stream; - -/** - * - */ -@Slf4j -@Aspect -@Component -@ConditionalOnProperty(name = "aop.log.controller", havingValue = "true") -public class ControllerAroundLog { - - @Pointcut("execution(* cn.lastwhisper.springbootaop.controller.*Controller.*(..))") - public void controllerExecution() { - } - - /** - * 切点表达式无法注入,局限性比较大,不如使用注解灵活,同时可以在注解里面添加一些备注 - */ - @Pointcut("@annotation(cn.lastwhisper.springbootaop.core.annotation.LogOperation)") - public void controllerAnnotation() { - } - - @Around("controllerAnnotation()") - public Object controller(ProceedingJoinPoint pjp) throws Throwable { - // 前置处理 - MethodSignature signature = (MethodSignature) pjp.getSignature(); - long count = Stream.of(signature.getMethod().getDeclaredAnnotations()) - .filter(annotation -> annotation.annotationType() == RequestMapping.class) - .count(); - String requestPath = count >= 1 ? signature.getMethod().getAnnotation(RequestMapping.class).value()[0] : ""; - String info = String.format("request 请求路径:[%s] | %s", requestPath, JoinPointParesUtils.getMethodInfo(pjp)); - log.info(info); - // 方法执行 - Object result = null; - try { - result = pjp.proceed(); - } catch (Throwable throwable) { - throw new Throwable(throwable); - } - // 后置处理 - log.info("response {}", JSONObject.toJSON(result)); - - return result; - } - - -} diff --git a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/aop/DaoBeforeLog.java b/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/aop/DaoBeforeLog.java deleted file mode 100644 index 03129e6e..00000000 --- a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/aop/DaoBeforeLog.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.lastwhisper.springbootaop.core.aop; - -import cn.lastwhisper.springbootaop.core.common.JoinPointParesUtils; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; -import org.aspectj.lang.annotation.Pointcut; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.stereotype.Component; - -/** - * - */ -@Slf4j -@Aspect -@Component -@ConditionalOnProperty(name = "aop.log.dao", havingValue = "true") -public class DaoBeforeLog { - - @Pointcut("execution(* cn.lastwhisper.springbootaop.mapper.*Mapper.*(..))") - public void dao() { - } - - @Before("dao()") - public void repository(JoinPoint point) { - log.info(String.format("%s", JoinPointParesUtils.getMethodInfo(point))); - } - -} diff --git a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/aop/ServiceBeforeLog.java b/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/aop/ServiceBeforeLog.java deleted file mode 100644 index a98763a7..00000000 --- a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/aop/ServiceBeforeLog.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.lastwhisper.springbootaop.core.aop; - -import cn.lastwhisper.springbootaop.core.common.JoinPointParesUtils; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; -import org.aspectj.lang.annotation.Pointcut; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.stereotype.Component; - -/** - * - */ -@Slf4j -@Aspect -@Component -@ConditionalOnProperty(name = "aop.log.service", havingValue = "true") -public class ServiceBeforeLog { - - @Pointcut("execution(* cn.lastwhisper.springbootaop.service.*Service.*(..))") - public void service() { - } - - @Before("service()") - public void service(JoinPoint point) { - log.info(String.format("%s", JoinPointParesUtils.getMethodInfo(point))); - } - -} diff --git a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/common/HttpContextUtil.java b/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/common/HttpContextUtil.java deleted file mode 100644 index b1e0e640..00000000 --- a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/common/HttpContextUtil.java +++ /dev/null @@ -1,48 +0,0 @@ -package cn.lastwhisper.springbootaop.core.common; - -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -import javax.servlet.http.HttpServletRequest; -import java.util.Objects; - -/** - * @desc - * - * @author lastwhisper - * @email gaojun56@163.com - */ -public class HttpContextUtil { - /** - * 获取当前线程的Request对象 - * @return javax.servlet.http.HttpServletRequest - */ - public static HttpServletRequest getRequest() { - return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())) - .getRequest(); - } - - /** - * 获取IP地址的方法 - */ - public static String getIpAddress() { - HttpServletRequest request = getRequest(); - String ip = request.getHeader("x-forwarded-for"); - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { - ip = request.getHeader("Proxy-Client-IP"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { - ip = request.getHeader("WL-Proxy-Client-IP"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { - ip = request.getHeader("HTTP_CLIENT_IP"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { - ip = request.getHeader("HTTP_X_FORWARDED_FOR"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { - ip = request.getRemoteAddr(); - } - return ip; - } -} diff --git a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/common/JoinPointParesUtils.java b/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/common/JoinPointParesUtils.java deleted file mode 100644 index 829c2ee0..00000000 --- a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/core/common/JoinPointParesUtils.java +++ /dev/null @@ -1,68 +0,0 @@ -package cn.lastwhisper.springbootaop.core.common; - -import cn.lastwhisper.springbootaop.core.annotation.LogOperation; -import com.alibaba.fastjson.JSONObject; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.validation.BindingResult; - -import java.lang.reflect.Method; -import java.util.Objects; - -public class JoinPointParesUtils { - - /** - * 获取方法参数 - */ - public static String getMethodInfo(JoinPoint point) { - // 获取方法签名 - MethodSignature methodSignature = (MethodSignature) point.getSignature(); - - //全限定名 - String className = methodSignature.getDeclaringType().getName(); - //方法名 - String methodName = methodSignature.getName(); - //参数名数组 - String[] parameterNames = methodSignature.getParameterNames(); - - // 获取方法 - Method method = methodSignature.getMethod(); - // 获取方法上面的注解 - LogOperation logOperation = method.getAnnotation(LogOperation.class); - String operate = ""; - if (logOperation != null) { - operate = logOperation.value(); - } - StringBuilder sb = null; - if (Objects.nonNull(parameterNames)) { - sb = new StringBuilder(); - for (int i = 0; i < parameterNames.length; i++) { - Object arg = point.getArgs()[i];//参数值 - if (arg instanceof BindingResult) { - continue; - } - // 复杂对象 - if (arg != null && !isPrimitive(arg)) { - sb.append(parameterNames[i]).append(":").append(JSONObject.toJSON(arg)).append("; "); - } else { - // null值或者基础数据类型 - String parameterValue = arg != null ? arg.toString() : "null"; - sb.append(parameterNames[i]).append(":").append(parameterValue).append("; "); - } - } - } - sb = sb == null ? new StringBuilder() : sb; - return String.format("操作名称:[%s] | 全限定名:[%s] | 方法名:[%s] | 参数列表:[%s]", operate, className, methodName, sb.toString()); - } - - /** - * 是否是基础数据类型 - */ - public static boolean isPrimitive(Object obj) { - try { - return ((Class) obj.getClass().getField("TYPE").get(null)).isPrimitive(); - } catch (Exception e) { - return false; - } - } -} diff --git a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/form/LoginForm.java b/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/form/LoginForm.java deleted file mode 100644 index 36e6597c..00000000 --- a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/form/LoginForm.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.lastwhisper.springbootaop.form; - -import lombok.Getter; -import lombok.Setter; - -/** - * - * @author lastwhisper - * @date 2019/12/5 - */ -@Getter -@Setter -public class LoginForm { - - private String username; - private String password; - -} diff --git a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/mapper/UserMapper.java b/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/mapper/UserMapper.java deleted file mode 100644 index 45377265..00000000 --- a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/mapper/UserMapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.lastwhisper.springbootaop.mapper; - -import cn.lastwhisper.springbootaop.pojo.User; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -/** - * - * @author lastwhisper - * @date 2019/12/5 - */ -public interface UserMapper extends BaseMapper { - - @Select("SELECT * FROM `user` WHERE username = #{username}") - User findUserByName(@Param("username") String username); - -} diff --git a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/pojo/User.java b/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/pojo/User.java deleted file mode 100644 index 941313d4..00000000 --- a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/pojo/User.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.lastwhisper.springbootaop.pojo; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Getter; -import lombok.Setter; - -/** - * - * @author lastwhisper - * @date 2019/12/8 - */ -@Getter -@Setter -@TableName("user") -public class User { - @TableId(value = "id", type = IdType.AUTO) - private Integer id; - @TableField("username") - private String username; - @TableField("password") - private String password; - @TableField("other") - private String other; - -} diff --git a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/service/UserService.java b/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/service/UserService.java deleted file mode 100644 index a0083211..00000000 --- a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/service/UserService.java +++ /dev/null @@ -1,10 +0,0 @@ -package cn.lastwhisper.springbootaop.service; - -/** - * - * @author lastwhisper - * @date 2019/12/5 - */ -public interface UserService { - public String login(String username,String password); -} diff --git a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/service/impl/UserServiceImpl.java b/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/service/impl/UserServiceImpl.java deleted file mode 100644 index 80594c81..00000000 --- a/springboot-integration-examples/springboot-aoplog/src/main/java/cn/lastwhisper/springbootaop/service/impl/UserServiceImpl.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.lastwhisper.springbootaop.service.impl; - -import cn.lastwhisper.springbootaop.mapper.UserMapper; -import cn.lastwhisper.springbootaop.pojo.User; -import cn.lastwhisper.springbootaop.service.UserService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -/** - * - * @author lastwhisper - * @date 2019/12/5 - */ -@Service -public class UserServiceImpl implements UserService { - - @Autowired - private UserMapper userMapper; - - @Override - public String login(String username, String password) { - User user = userMapper.findUserByName(username); - if(user==null){ - return "用户名错误"; - } - if (password.equals(user.getPassword())) { - return "登录成功!!!"; - } - return "密码错误"; - } -} diff --git a/springboot-integration-examples/springboot-aoplog/src/main/resources/application.yml b/springboot-integration-examples/springboot-aoplog/src/main/resources/application.yml deleted file mode 100644 index d771f314..00000000 --- a/springboot-integration-examples/springboot-aoplog/src/main/resources/application.yml +++ /dev/null @@ -1,14 +0,0 @@ -spring: - application: - name: lastwhisper-aoplog - datasource: - driver-class-name: com.mysql.jdbc.Driver - url: jdbc:mysql://127.0.0.1:3306/logdb?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false - username: root - password: root -aop: - log: - controller: true - service: true - dao: true - diff --git a/springboot-integration-examples/springboot-aoplog/src/test/java/cn/lastwhisper/springbootaop/SpringbootaopApplicationTests.java b/springboot-integration-examples/springboot-aoplog/src/test/java/cn/lastwhisper/springbootaop/SpringbootaopApplicationTests.java deleted file mode 100644 index 7347dbc2..00000000 --- a/springboot-integration-examples/springboot-aoplog/src/test/java/cn/lastwhisper/springbootaop/SpringbootaopApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.springbootaop; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class SpringbootaopApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-banner/.gitignore b/springboot-integration-examples/springboot-banner/.gitignore deleted file mode 100644 index a2a3040a..00000000 --- a/springboot-integration-examples/springboot-banner/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/** -!**/src/test/** - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ - -### VS Code ### -.vscode/ diff --git a/springboot-integration-examples/springboot-banner/.mvn/wrapper/MavenWrapperDownloader.java b/springboot-integration-examples/springboot-banner/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index a45eb6ba..00000000 --- a/springboot-integration-examples/springboot-banner/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2007-present the original author or authors. - * - * Licensed 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 - * - * https://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. - */ - -import java.net.*; -import java.io.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.6"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if (mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if (mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if (!outputFile.getParentFile().exists()) { - if (!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/springboot-integration-examples/springboot-banner/.mvn/wrapper/maven-wrapper.jar b/springboot-integration-examples/springboot-banner/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 2cc7d4a5..00000000 Binary files a/springboot-integration-examples/springboot-banner/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/springboot-integration-examples/springboot-banner/.mvn/wrapper/maven-wrapper.properties b/springboot-integration-examples/springboot-banner/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 642d572c..00000000 --- a/springboot-integration-examples/springboot-banner/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/springboot-integration-examples/springboot-banner/mvnw b/springboot-integration-examples/springboot-banner/mvnw deleted file mode 100644 index a16b5431..00000000 --- a/springboot-integration-examples/springboot-banner/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF 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 -# -# https://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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/springboot-integration-examples/springboot-banner/mvnw.cmd b/springboot-integration-examples/springboot-banner/mvnw.cmd deleted file mode 100644 index c8d43372..00000000 --- a/springboot-integration-examples/springboot-banner/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/springboot-integration-examples/springboot-banner/pom.xml b/springboot-integration-examples/springboot-banner/pom.xml deleted file mode 100644 index e2f10b5c..00000000 --- a/springboot-integration-examples/springboot-banner/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.2.4.RELEASE - - - cn.lastwhisper - springboot - 0.0.1-SNAPSHOT - springboot - springboot学习 - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.junit.vintage - junit-vintage-engine - - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-banner/src/main/java/cn/lastwhisper/springboot/SpringbootApplication.java b/springboot-integration-examples/springboot-banner/src/main/java/cn/lastwhisper/springboot/SpringbootApplication.java deleted file mode 100644 index b9446210..00000000 --- a/springboot-integration-examples/springboot-banner/src/main/java/cn/lastwhisper/springboot/SpringbootApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.springboot; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SpringbootApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringbootApplication.class, args); - } - -} diff --git a/springboot-integration-examples/springboot-banner/src/main/resources/banner.txt b/springboot-integration-examples/springboot-banner/src/main/resources/banner.txt deleted file mode 100644 index 2fe75c5c..00000000 --- a/springboot-integration-examples/springboot-banner/src/main/resources/banner.txt +++ /dev/null @@ -1,6 +0,0 @@ - _ ___ - | |__ ( _ ) ___ - | / / / _ \ (_-< - |_\_\ \___/ /__/_ -_|"""""|_|"""""|_|"""""| -"`-0-0-'"`-0-0-'"`-0-0-' diff --git a/springboot-integration-examples/springboot-banner/src/test/java/cn/lastwhisper/springboot/SpringbootApplicationTests.java b/springboot-integration-examples/springboot-banner/src/test/java/cn/lastwhisper/springboot/SpringbootApplicationTests.java deleted file mode 100644 index 9c68e80b..00000000 --- a/springboot-integration-examples/springboot-banner/src/test/java/cn/lastwhisper/springboot/SpringbootApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.springboot; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class SpringbootApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-api/pom.xml b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-api/pom.xml deleted file mode 100644 index c5acbd23..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-api/pom.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - springboot-dubbo-tcc - cn.lastwhisper.springboot - 0.0.1-SNAPSHOT - - 4.0.0 - - cn.lastwhisper.springboot - dubbo-api - - dubbo-api - - http://www.example.com - - - UTF-8 - 1.7 - 1.7 - - - - - junit - junit - 4.11 - test - - - org.mengyun - tcc-transaction-api - 1.2.4.23 - - - - - - - - - maven-clean-plugin - 3.1.0 - - - - maven-resources-plugin - 3.0.2 - - - maven-compiler-plugin - 3.8.0 - - - maven-surefire-plugin - 2.22.1 - - - maven-jar-plugin - 3.0.2 - - - maven-install-plugin - 2.5.2 - - - maven-deploy-plugin - 2.8.2 - - - - maven-site-plugin - 3.7.1 - - - maven-project-info-reports-plugin - 3.0.0 - - - - - diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-api/src/main/java/cn/lastwhisper/springboot/ServiceAPI.java b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-api/src/main/java/cn/lastwhisper/springboot/ServiceAPI.java deleted file mode 100644 index d0d3e02a..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-api/src/main/java/cn/lastwhisper/springboot/ServiceAPI.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.lastwhisper.springboot; - - -import org.mengyun.tcctransaction.api.Compensable; - -public interface ServiceAPI { - @Compensable - String sendMessage(String message); - - /* - * 传入购票数量、传入购票座位,影厅编号 - * - */ - - //判断座位是否存在,模拟一个事务 - @Compensable - boolean isTrueSeats(String seats); - - //判断座位是否售出,模拟一个事务 - @Compensable - boolean isNotSold(String seats); - - //保存订单,模拟一个事务 - @Compensable - String saveOrder(String field, String seats, String seatsNum); - -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-api/src/test/java/cn/lastwhisper/springboot/AppTest.java b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-api/src/test/java/cn/lastwhisper/springboot/AppTest.java deleted file mode 100644 index ecb89484..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-api/src/test/java/cn/lastwhisper/springboot/AppTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.lastwhisper.springboot; - -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -/** - * Unit test for simple App. - */ -public class AppTest -{ - /** - * Rigorous Test :-) - */ - @Test - public void shouldAnswerWithTrue() - { - assertTrue( true ); - } -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/pom.xml b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/pom.xml deleted file mode 100644 index 521b26c0..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/pom.xml +++ /dev/null @@ -1,136 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.7.RELEASE - - - cn.lastwhisper.springboot - dubbo-consumer - 0.0.1-SNAPSHOT - dubbo-consumer - 服务消费者 - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter - - - com.alibaba.spring.boot - dubbo-spring-boot-starter - 2.0.0 - - - org.springframework.boot - spring-boot-starter-test - test - - - com.101tec - zkclient - 0.10 - - - org.mengyun - tcc-transaction-dubbo - 1.2.4.23 - - - org.mengyun - tcc-transaction-spring - 1.2.4.23 - - - org.mengyun - tcc-transaction-core - 1.2.4.23 - - - org.mengyun - tcc-transaction-api - 1.2.4.23 - - - com.alibaba - druid - 1.1.12 - - - mysql - mysql-connector-java - 5.1.10 - - - org.springframework.boot - spring-boot-starter-aop - - - org.quartz-scheduler - quartz - 2.2.1 - - - slf4j-api - org.slf4j - - - - - org.springframework - spring-context-support - - - org.springframework.boot - spring-boot-starter-jdbc - - - com.google.guava - guava - 23.0 - - - com.esotericsoftware - kryo-shaded - 4.0.2 - - - org.apache.commons - commons-lang3 - 3.8.1 - - - com.alibaba - fastjson - 1.2.51 - - - cn.lastwhisper.springboot - dubbo-api - 0.0.1-SNAPSHOT - compile - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplication.java b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplication.java deleted file mode 100644 index 29ec1d64..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplication.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.consumer; - -import cn.lastwhisper.springboot.dubbo.consumer.transaction.TransactionConsumer; -import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.ConfigurableApplicationContext; - -@SpringBootApplication -@EnableDubboConfiguration -public class ConsumerApplication { - - public static void main(String[] args) { - ConfigurableApplicationContext context = SpringApplication.run(ConsumerApplication.class, args); - //QuickstartConsumer quickstartConsumer = (QuickstartConsumer) context.getBean("quickstartConsumer"); - //quickstartConsumer.sendMessage("你好"); - - TransactionConsumer consumer = (TransactionConsumer) context.getBean("transactionConsumer"); - // 1,2,3 isTrueSeats报错 - // 4,5 - consumer.sendMessage("4,5"); - - } - -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/config/TCCConfig.java b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/config/TCCConfig.java deleted file mode 100644 index f3de5b89..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/config/TCCConfig.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.consumer.config; - -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; - -/** - * @author lastwhisper - */ -@Configuration -@ImportResource(locations = {"classpath:tcc-transaction.xml","classpath:tcc-transaction-dubbo.xml"}) -public class TCCConfig { -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/quickstart/QuickstartConsumer.java b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/quickstart/QuickstartConsumer.java deleted file mode 100644 index 05c24052..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/quickstart/QuickstartConsumer.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.consumer.quickstart; - -import cn.lastwhisper.springboot.ServiceAPI; -import com.alibaba.dubbo.config.annotation.Reference; -import org.springframework.stereotype.Component; - -/** - * @author lastwhisper - */ -//@Component -public class QuickstartConsumer { - //@Reference(url ="dubbo://localhost:20880") - //@Reference(interfaceClass = ServiceAPI.class) - ServiceAPI serviceAPI; - - public void sendMessage(String message) { - System.out.println(serviceAPI.sendMessage(message)); - } -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/transaction/TransactionConsumer.java b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/transaction/TransactionConsumer.java deleted file mode 100644 index 1dada24b..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/transaction/TransactionConsumer.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.consumer.transaction; - -import cn.lastwhisper.springboot.ServiceAPI; -import com.alibaba.dubbo.config.annotation.Reference; -import org.mengyun.tcctransaction.api.Compensable; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -/** - * @author lastwhisper - */ -@Component("transactionConsumer") -public class TransactionConsumer { - //@Reference(interfaceClass = ServiceAPI.class) - @Autowired - ServiceAPI serviceAPI; - - // 主事务 - @Compensable(confirmMethod = "confirmSendMessage", cancelMethod = "cancelSendMessage", asyncConfirm = true) - public void sendMessage(String message) { - //System.out.println("this is consumer sendMessage="+message); - //System.out.println(serviceAPI.sendMessage(message)); - - // 业务 - serviceAPI.saveOrder("001", message, "5"); - - serviceAPI.isTrueSeats(message); - serviceAPI.isNotSold(message); - - } - - public void confirmSendMessage(String message) { - System.out.println("this is consumer confirmSendMessage=" + message); - } - - public void cancelSendMessage(String message) { - System.out.println("this is consumer cancelSendMessage=" + message); - } -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/resources/application.properties b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/resources/application.properties deleted file mode 100644 index 6f0465df..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -spring.application.name=dubbo-spring-boot-starter -spring.dubbo.registry=zookeeper://localhost:2181 \ No newline at end of file diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/resources/tcc-transaction-dubbo.xml b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/resources/tcc-transaction-dubbo.xml deleted file mode 100644 index 53d009a0..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/resources/tcc-transaction-dubbo.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/resources/tcc-transaction.xml b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/resources/tcc-transaction.xml deleted file mode 100644 index bccba078..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/main/resources/tcc-transaction.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - com.alibaba.dubbo.remoting.TimeoutException - - - - - \ No newline at end of file diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/test/java/cn/lastwhisper/springboot/dubboconsumer/DubboConsumerApplicationTests.java b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/test/java/cn/lastwhisper/springboot/dubboconsumer/DubboConsumerApplicationTests.java deleted file mode 100644 index 82925eb9..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-consumer/src/test/java/cn/lastwhisper/springboot/dubboconsumer/DubboConsumerApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.springboot.dubboconsumer; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class DubboConsumerApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/pom.xml b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/pom.xml deleted file mode 100644 index a9b90230..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/pom.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.7.RELEASE - - - cn.lastwhisper.springboot - dubbo-provider - 0.0.1-SNAPSHOT - dubbo-provider - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - com.alibaba.spring.boot - dubbo-spring-boot-starter - 2.0.0 - - - org.springframework.boot - spring-boot-starter-test - test - - - com.101tec - zkclient - 0.10 - - - org.mengyun - tcc-transaction-dubbo - 1.2.4.23 - - - org.mengyun - tcc-transaction-spring - 1.2.4.23 - - - org.mengyun - tcc-transaction-core - 1.2.4.23 - - - org.mengyun - tcc-transaction-api - 1.2.4.23 - - - com.alibaba - druid - 1.1.12 - - - mysql - mysql-connector-java - 5.1.10 - - - org.springframework.boot - spring-boot-starter-aop - - - org.quartz-scheduler - quartz - 2.2.1 - - - slf4j-api - org.slf4j - - - - - org.springframework - spring-context-support - - - org.springframework.boot - spring-boot-starter-jdbc - - - com.google.guava - guava - 23.0 - - - com.esotericsoftware - kryo-shaded - 4.0.2 - - - org.apache.commons - commons-lang3 - 3.8.1 - - - com.alibaba - fastjson - 1.2.51 - - - cn.lastwhisper.springboot - dubbo-api - 0.0.1-SNAPSHOT - compile - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplication.java b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplication.java deleted file mode 100644 index 2d9530d2..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplication.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.provider; - -import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -@EnableDubboConfiguration -public class ProviderApplication { - - public static void main(String[] args) { - SpringApplication.run(ProviderApplication.class, args); - - - } - -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/config/TCCConfig.java b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/config/TCCConfig.java deleted file mode 100644 index f6cc6a63..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/config/TCCConfig.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.provider.config; - -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; - -/** - * @author lastwhisper - */ -@Configuration -@ImportResource(locations = {"classpath:tcc-transaction.xml","classpath:tcc-transaction-dubbo.xml"}) -public class TCCConfig { -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/quickstart/QuickstartServiceImpl.java b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/quickstart/QuickstartServiceImpl.java deleted file mode 100644 index a0f50fe3..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/quickstart/QuickstartServiceImpl.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.provider.quickstart; - -import cn.lastwhisper.springboot.ServiceAPI; -import com.alibaba.dubbo.config.annotation.Service; -import org.springframework.stereotype.Component; - -/** - * @author lastwhisper - */ -//@Component -//@Service(interfaceClass = ServiceAPI.class) -public class QuickstartServiceImpl implements ServiceAPI { - - @Override - public String sendMessage(String message) { - return "quickstart-provider-message=" + message; - } - - @Override - public boolean isTrueSeats(String seats) { - return false; - } - - @Override - public boolean isNotSold(String seats) { - return false; - } - - @Override - public String saveOrder(String field, String seats, String seatsNum) { - return null; - } -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/transaction/TransactionService.java b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/transaction/TransactionService.java deleted file mode 100644 index 4f8b5c8e..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/transaction/TransactionService.java +++ /dev/null @@ -1,96 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.provider.transaction; - -import cn.lastwhisper.springboot.ServiceAPI; -import com.alibaba.dubbo.config.annotation.Service; -import org.mengyun.tcctransaction.api.Compensable; -import org.mengyun.tcctransaction.dubbo.context.DubboTransactionContextEditor; -import org.springframework.stereotype.Component; - -/** - * @author lastwhisper - */ -@Component -@Service(interfaceClass = ServiceAPI.class) -public class TransactionService implements ServiceAPI { - - @Compensable(confirmMethod = "confirmSendMessage", cancelMethod = "cancelSendMessage", transactionContextEditor = DubboTransactionContextEditor.class) - @Override - public String sendMessage(String message) { - System.out.println("this is provider sendMessage=" + message); - if ("123".equals(message)) { - throw new NullPointerException(); - } - return "tcc-provider-message=" + message; - } - - @Override - @Compensable(confirmMethod = "confirmIsTrueSeats", cancelMethod = "cancelIsTrueSeats", transactionContextEditor = DubboTransactionContextEditor.class) - public boolean isTrueSeats(String seats) { - // 假设1,2,3座位不存在 - if ("1,2,3".equals(seats)) { - throw new IllegalArgumentException(); - } else { - return true; - } - } - - - @Override - @Compensable(confirmMethod = "confirmIsNotSold", cancelMethod = "cancelIsNotSold", transactionContextEditor = DubboTransactionContextEditor.class) - public boolean isNotSold(String seats) { - // 假设4,5已经售出 - if ("4,5".equals(seats)) { - throw new IllegalArgumentException(); - } else { - return true; - } - } - - // 幂等性 - @Override - @Compensable(confirmMethod = "confirmSaveOrder", cancelMethod = "cancelSaveOrder", transactionContextEditor = DubboTransactionContextEditor.class) - public String saveOrder(String field, String seats, String seatsNum) { - System.out.println("创建一个待支付状态的订单"); - return ""; - } - - - public String confirmSaveOrder(String field, String seats, String seatsNum) { - System.out.println("将订单修改为支付中"); - return ""; - } - public String cancelSaveOrder(String field, String seats, String seatsNum) { - System.out.println("将订单修改为已关闭"); - return ""; - } - - public boolean confirmIsNotSold(String seats) { - System.out.println("this is confirmIsNotSold"); - return true; - } - - public boolean cancelIsNotSold(String seats) { - System.out.println("this is cancelIsNotSold"); - return true; - } - - public boolean confirmIsTrueSeats(String seats) { - System.out.println("this is confirmIsTrueSeats"); - return true; - } - - public boolean cancelIsTrueSeats(String seats) { - System.out.println("this is cancelIsTrueSeats"); - return true; - } - - public String confirmSendMessage(String message) { - System.out.println("this is provider confirmSendMessage=" + message); - return "tcc-provider-message=" + message; - } - - public String cancelSendMessage(String message) { - System.out.println("this is provider cancelSendMessage=" + message); - return "tcc-provider-message=" + message; - } -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/resources/application.properties b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/resources/application.properties deleted file mode 100644 index 0d2d5ac4..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/resources/application.properties +++ /dev/null @@ -1,3 +0,0 @@ -spring.application.name=dubbo-spring-boot-starter -spring.dubbo.server=true -spring.dubbo.registry=zookeeper://localhost:2181 \ No newline at end of file diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/resources/tcc-transaction-dubbo.xml b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/resources/tcc-transaction-dubbo.xml deleted file mode 100644 index 6fd7c1f3..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/resources/tcc-transaction-dubbo.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - \ No newline at end of file diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/resources/tcc-transaction.xml b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/resources/tcc-transaction.xml deleted file mode 100644 index c3ed94ec..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/main/resources/tcc-transaction.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - com.alibaba.dubbo.remoting.TimeoutException - - - - - \ No newline at end of file diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/test/java/cn/lastwhisper/springboot/dubboprovider/DubboProviderApplicationTests.java b/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/test/java/cn/lastwhisper/springboot/dubboprovider/DubboProviderApplicationTests.java deleted file mode 100644 index 2cd9a38d..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/dubbo-provider/src/test/java/cn/lastwhisper/springboot/dubboprovider/DubboProviderApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.springboot.dubboprovider; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class DubboProviderApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/pom.xml b/springboot-integration-examples/springboot-dubbo-tcc-instance/pom.xml deleted file mode 100644 index 4d2a0da5..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - 4.0.0 - pom - - dubbo-api - - - org.springframework.boot - spring-boot-starter-parent - 2.1.7.RELEASE - - - cn.lastwhisper.springboot - springboot-dubbo-tcc - 0.0.1-SNAPSHOT - springboot-dubbo-tcc - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/src/main/java/cn/lastwhisper/springboot/springbootdubbotcc/SpringbootDubboTccApplication.java b/springboot-integration-examples/springboot-dubbo-tcc-instance/src/main/java/cn/lastwhisper/springboot/springbootdubbotcc/SpringbootDubboTccApplication.java deleted file mode 100644 index 4929e634..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/src/main/java/cn/lastwhisper/springboot/springbootdubbotcc/SpringbootDubboTccApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.springboot.springbootdubbotcc; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SpringbootDubboTccApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringbootDubboTccApplication.class, args); - } - -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-instance/src/test/java/cn/lastwhisper/springboot/springbootdubbotcc/SpringbootDubboTccApplicationTests.java b/springboot-integration-examples/springboot-dubbo-tcc-instance/src/test/java/cn/lastwhisper/springboot/springbootdubbotcc/SpringbootDubboTccApplicationTests.java deleted file mode 100644 index 7911d933..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-instance/src/test/java/cn/lastwhisper/springboot/springbootdubbotcc/SpringbootDubboTccApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.springboot.springbootdubbotcc; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class SpringbootDubboTccApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-api/pom.xml b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-api/pom.xml deleted file mode 100644 index c5acbd23..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-api/pom.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - springboot-dubbo-tcc - cn.lastwhisper.springboot - 0.0.1-SNAPSHOT - - 4.0.0 - - cn.lastwhisper.springboot - dubbo-api - - dubbo-api - - http://www.example.com - - - UTF-8 - 1.7 - 1.7 - - - - - junit - junit - 4.11 - test - - - org.mengyun - tcc-transaction-api - 1.2.4.23 - - - - - - - - - maven-clean-plugin - 3.1.0 - - - - maven-resources-plugin - 3.0.2 - - - maven-compiler-plugin - 3.8.0 - - - maven-surefire-plugin - 2.22.1 - - - maven-jar-plugin - 3.0.2 - - - maven-install-plugin - 2.5.2 - - - maven-deploy-plugin - 2.8.2 - - - - maven-site-plugin - 3.7.1 - - - maven-project-info-reports-plugin - 3.0.0 - - - - - diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-api/src/main/java/cn/lastwhisper/springboot/ServiceAPI.java b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-api/src/main/java/cn/lastwhisper/springboot/ServiceAPI.java deleted file mode 100644 index 7a1985db..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-api/src/main/java/cn/lastwhisper/springboot/ServiceAPI.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.lastwhisper.springboot; - - -import org.mengyun.tcctransaction.api.Compensable; - -public interface ServiceAPI { - @Compensable - String sendMessage(String message); -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-api/src/test/java/cn/lastwhisper/springboot/AppTest.java b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-api/src/test/java/cn/lastwhisper/springboot/AppTest.java deleted file mode 100644 index ecb89484..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-api/src/test/java/cn/lastwhisper/springboot/AppTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.lastwhisper.springboot; - -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -/** - * Unit test for simple App. - */ -public class AppTest -{ - /** - * Rigorous Test :-) - */ - @Test - public void shouldAnswerWithTrue() - { - assertTrue( true ); - } -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/pom.xml b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/pom.xml deleted file mode 100644 index 521b26c0..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/pom.xml +++ /dev/null @@ -1,136 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.7.RELEASE - - - cn.lastwhisper.springboot - dubbo-consumer - 0.0.1-SNAPSHOT - dubbo-consumer - 服务消费者 - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter - - - com.alibaba.spring.boot - dubbo-spring-boot-starter - 2.0.0 - - - org.springframework.boot - spring-boot-starter-test - test - - - com.101tec - zkclient - 0.10 - - - org.mengyun - tcc-transaction-dubbo - 1.2.4.23 - - - org.mengyun - tcc-transaction-spring - 1.2.4.23 - - - org.mengyun - tcc-transaction-core - 1.2.4.23 - - - org.mengyun - tcc-transaction-api - 1.2.4.23 - - - com.alibaba - druid - 1.1.12 - - - mysql - mysql-connector-java - 5.1.10 - - - org.springframework.boot - spring-boot-starter-aop - - - org.quartz-scheduler - quartz - 2.2.1 - - - slf4j-api - org.slf4j - - - - - org.springframework - spring-context-support - - - org.springframework.boot - spring-boot-starter-jdbc - - - com.google.guava - guava - 23.0 - - - com.esotericsoftware - kryo-shaded - 4.0.2 - - - org.apache.commons - commons-lang3 - 3.8.1 - - - com.alibaba - fastjson - 1.2.51 - - - cn.lastwhisper.springboot - dubbo-api - 0.0.1-SNAPSHOT - compile - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplication.java b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplication.java deleted file mode 100644 index 9b2bc169..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplication.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.consumer; - -import cn.lastwhisper.springboot.dubbo.consumer.transaction.TransactionConsumer; -import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.ConfigurableApplicationContext; - -@SpringBootApplication -@EnableDubboConfiguration -public class ConsumerApplication { - - public static void main(String[] args) { - ConfigurableApplicationContext context = SpringApplication.run(ConsumerApplication.class, args); - //QuickstartConsumer quickstartConsumer = (QuickstartConsumer) context.getBean("quickstartConsumer"); - //quickstartConsumer.sendMessage("你好"); - - TransactionConsumer consumer = (TransactionConsumer) context.getBean("transactionConsumer"); - consumer.sendMessage("123"); - } - -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/config/TCCConfig.java b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/config/TCCConfig.java deleted file mode 100644 index f3de5b89..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/config/TCCConfig.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.consumer.config; - -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; - -/** - * @author lastwhisper - */ -@Configuration -@ImportResource(locations = {"classpath:tcc-transaction.xml","classpath:tcc-transaction-dubbo.xml"}) -public class TCCConfig { -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/quickstart/QuickstartConsumer.java b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/quickstart/QuickstartConsumer.java deleted file mode 100644 index 05c24052..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/quickstart/QuickstartConsumer.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.consumer.quickstart; - -import cn.lastwhisper.springboot.ServiceAPI; -import com.alibaba.dubbo.config.annotation.Reference; -import org.springframework.stereotype.Component; - -/** - * @author lastwhisper - */ -//@Component -public class QuickstartConsumer { - //@Reference(url ="dubbo://localhost:20880") - //@Reference(interfaceClass = ServiceAPI.class) - ServiceAPI serviceAPI; - - public void sendMessage(String message) { - System.out.println(serviceAPI.sendMessage(message)); - } -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/transaction/TransactionConsumer.java b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/transaction/TransactionConsumer.java deleted file mode 100644 index 646c687c..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/transaction/TransactionConsumer.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.consumer.transaction; - -import cn.lastwhisper.springboot.ServiceAPI; -import com.alibaba.dubbo.config.annotation.Reference; -import org.mengyun.tcctransaction.api.Compensable; -import org.springframework.stereotype.Component; - -/** - * @author lastwhisper - */ -@Component("transactionConsumer") -public class TransactionConsumer { - @Reference(interfaceClass = ServiceAPI.class) - ServiceAPI serviceAPI; - - @Compensable(confirmMethod = "confirmSendMessage", cancelMethod = "cancelSendMessage", asyncConfirm = true) - public void sendMessage(String message) { - System.out.println("this is consumer sendMessage="+message); - System.out.println(serviceAPI.sendMessage(message)); - } - - public void confirmSendMessage(String message) { - System.out.println("this is consumer confirmSendMessage="+message); - } - - public void cancelSendMessage(String message) { - System.out.println("this is consumer cancelSendMessage="+message); - } -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/resources/application.properties b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/resources/application.properties deleted file mode 100644 index 6f0465df..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -spring.application.name=dubbo-spring-boot-starter -spring.dubbo.registry=zookeeper://localhost:2181 \ No newline at end of file diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/resources/tcc-transaction-dubbo.xml b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/resources/tcc-transaction-dubbo.xml deleted file mode 100644 index 7bcd668b..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/resources/tcc-transaction-dubbo.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/resources/tcc-transaction.xml b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/resources/tcc-transaction.xml deleted file mode 100644 index bccba078..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/main/resources/tcc-transaction.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - com.alibaba.dubbo.remoting.TimeoutException - - - - - \ No newline at end of file diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/test/java/cn/lastwhisper/springboot/dubboconsumer/DubboConsumerApplicationTests.java b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/test/java/cn/lastwhisper/springboot/dubboconsumer/DubboConsumerApplicationTests.java deleted file mode 100644 index 82925eb9..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-consumer/src/test/java/cn/lastwhisper/springboot/dubboconsumer/DubboConsumerApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.springboot.dubboconsumer; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class DubboConsumerApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/pom.xml b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/pom.xml deleted file mode 100644 index a9b90230..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/pom.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.7.RELEASE - - - cn.lastwhisper.springboot - dubbo-provider - 0.0.1-SNAPSHOT - dubbo-provider - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - com.alibaba.spring.boot - dubbo-spring-boot-starter - 2.0.0 - - - org.springframework.boot - spring-boot-starter-test - test - - - com.101tec - zkclient - 0.10 - - - org.mengyun - tcc-transaction-dubbo - 1.2.4.23 - - - org.mengyun - tcc-transaction-spring - 1.2.4.23 - - - org.mengyun - tcc-transaction-core - 1.2.4.23 - - - org.mengyun - tcc-transaction-api - 1.2.4.23 - - - com.alibaba - druid - 1.1.12 - - - mysql - mysql-connector-java - 5.1.10 - - - org.springframework.boot - spring-boot-starter-aop - - - org.quartz-scheduler - quartz - 2.2.1 - - - slf4j-api - org.slf4j - - - - - org.springframework - spring-context-support - - - org.springframework.boot - spring-boot-starter-jdbc - - - com.google.guava - guava - 23.0 - - - com.esotericsoftware - kryo-shaded - 4.0.2 - - - org.apache.commons - commons-lang3 - 3.8.1 - - - com.alibaba - fastjson - 1.2.51 - - - cn.lastwhisper.springboot - dubbo-api - 0.0.1-SNAPSHOT - compile - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplication.java b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplication.java deleted file mode 100644 index 2d9530d2..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplication.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.provider; - -import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -@EnableDubboConfiguration -public class ProviderApplication { - - public static void main(String[] args) { - SpringApplication.run(ProviderApplication.class, args); - - - } - -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/config/TCCConfig.java b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/config/TCCConfig.java deleted file mode 100644 index f6cc6a63..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/config/TCCConfig.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.provider.config; - -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; - -/** - * @author lastwhisper - */ -@Configuration -@ImportResource(locations = {"classpath:tcc-transaction.xml","classpath:tcc-transaction-dubbo.xml"}) -public class TCCConfig { -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/quickstart/QuickstartServiceImpl.java b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/quickstart/QuickstartServiceImpl.java deleted file mode 100644 index d823e0f9..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/quickstart/QuickstartServiceImpl.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.provider.quickstart; - -import cn.lastwhisper.springboot.ServiceAPI; -import com.alibaba.dubbo.config.annotation.Service; -import org.springframework.stereotype.Component; - -/** - * @author lastwhisper - */ -//@Component -//@Service(interfaceClass = ServiceAPI.class) -public class QuickstartServiceImpl implements ServiceAPI { - - @Override - public String sendMessage(String message) { - return "quickstart-provider-message=" + message; - } -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/transaction/TransactionService.java b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/transaction/TransactionService.java deleted file mode 100644 index 4562e128..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/transaction/TransactionService.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.provider.transaction; - -import cn.lastwhisper.springboot.ServiceAPI; -import com.alibaba.dubbo.config.annotation.Service; -import org.mengyun.tcctransaction.api.Compensable; -import org.mengyun.tcctransaction.dubbo.context.DubboTransactionContextEditor; -import org.springframework.stereotype.Component; - -/** - * @author lastwhisper - */ -@Component -@Service(interfaceClass = ServiceAPI.class) -public class TransactionService implements ServiceAPI { - - @Compensable(confirmMethod = "confirmSendMessage", cancelMethod = "cancelSendMessage", transactionContextEditor = DubboTransactionContextEditor.class) - @Override - public String sendMessage(String message) { - System.out.println("this is provider sendMessage=" + message); - if ("123".equals(message)) { - throw new NullPointerException(); - } - return "tcc-provider-message=" + message; - } - - public String confirmSendMessage(String message) { - System.out.println("this is provider confirmSendMessage=" + message); - return "tcc-provider-message=" + message; - } - - public String cancelSendMessage(String message) { - System.out.println("this is provider cancelSendMessage=" + message); - return "tcc-provider-message=" + message; - } -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/resources/application.properties b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/resources/application.properties deleted file mode 100644 index 0d2d5ac4..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/resources/application.properties +++ /dev/null @@ -1,3 +0,0 @@ -spring.application.name=dubbo-spring-boot-starter -spring.dubbo.server=true -spring.dubbo.registry=zookeeper://localhost:2181 \ No newline at end of file diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/resources/tcc-transaction-dubbo.xml b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/resources/tcc-transaction-dubbo.xml deleted file mode 100644 index 6fd7c1f3..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/resources/tcc-transaction-dubbo.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - \ No newline at end of file diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/resources/tcc-transaction.xml b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/resources/tcc-transaction.xml deleted file mode 100644 index c3ed94ec..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/main/resources/tcc-transaction.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - com.alibaba.dubbo.remoting.TimeoutException - - - - - \ No newline at end of file diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/test/java/cn/lastwhisper/springboot/dubboprovider/DubboProviderApplicationTests.java b/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/test/java/cn/lastwhisper/springboot/dubboprovider/DubboProviderApplicationTests.java deleted file mode 100644 index 2cd9a38d..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/dubbo-provider/src/test/java/cn/lastwhisper/springboot/dubboprovider/DubboProviderApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.springboot.dubboprovider; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class DubboProviderApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-dubbo-tcc-rt/pom.xml b/springboot-integration-examples/springboot-dubbo-tcc-rt/pom.xml deleted file mode 100644 index 4d2a0da5..00000000 --- a/springboot-integration-examples/springboot-dubbo-tcc-rt/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - 4.0.0 - pom - - dubbo-api - - - org.springframework.boot - spring-boot-starter-parent - 2.1.7.RELEASE - - - cn.lastwhisper.springboot - springboot-dubbo-tcc - 0.0.1-SNAPSHOT - springboot-dubbo-tcc - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-duboo-filter/dubbo-api/pom.xml b/springboot-integration-examples/springboot-duboo-filter/dubbo-api/pom.xml deleted file mode 100644 index 911d7ddf..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/dubbo-api/pom.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - springboot-duboo - cn.lastwhisper.springboot.dubbo - 0.0.1-SNAPSHOT - - 4.0.0 - - cn.lastwhisper.springboot.dubbo - dubbo-api - - dubbo-api - - http://www.example.com - - - UTF-8 - 1.7 - 1.7 - - - - - junit - junit - 4.11 - test - - - - - - - - - maven-clean-plugin - 3.1.0 - - - - maven-resources-plugin - 3.0.2 - - - maven-compiler-plugin - 3.8.0 - - - maven-surefire-plugin - 2.22.1 - - - maven-jar-plugin - 3.0.2 - - - maven-install-plugin - 2.5.2 - - - maven-deploy-plugin - 2.8.2 - - - - maven-site-plugin - 3.7.1 - - - maven-project-info-reports-plugin - 3.0.0 - - - - - diff --git a/springboot-integration-examples/springboot-duboo-filter/dubbo-api/src/main/java/cn/lastwhisper/springboot/dubbo/ServiceAPI.java b/springboot-integration-examples/springboot-duboo-filter/dubbo-api/src/main/java/cn/lastwhisper/springboot/dubbo/ServiceAPI.java deleted file mode 100644 index 8231e710..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/dubbo-api/src/main/java/cn/lastwhisper/springboot/dubbo/ServiceAPI.java +++ /dev/null @@ -1,5 +0,0 @@ -package cn.lastwhisper.springboot.dubbo; - -public interface ServiceAPI { - String sendMessage(String message); -} diff --git a/springboot-integration-examples/springboot-duboo-filter/dubbo-api/src/test/java/cn/lastwhisper/springboot/dubbo/AppTest.java b/springboot-integration-examples/springboot-duboo-filter/dubbo-api/src/test/java/cn/lastwhisper/springboot/dubbo/AppTest.java deleted file mode 100644 index 6aaab91b..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/dubbo-api/src/test/java/cn/lastwhisper/springboot/dubbo/AppTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.lastwhisper.springboot.dubbo; - -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -/** - * Unit test for simple App. - */ -public class AppTest -{ - /** - * Rigorous Test :-) - */ - @Test - public void shouldAnswerWithTrue() - { - assertTrue( true ); - } -} diff --git a/springboot-integration-examples/springboot-duboo-filter/dubbo-consumer/pom.xml b/springboot-integration-examples/springboot-duboo-filter/dubbo-consumer/pom.xml deleted file mode 100644 index d75196cc..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/dubbo-consumer/pom.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.7.RELEASE - - - cn.lastwhisper.springboot.dubbo - dubbo-consumer - 0.0.1-SNAPSHOT - dubbo-consumer - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - com.alibaba.spring.boot - dubbo-spring-boot-starter - 2.0.0 - - - - cn.lastwhisper.springboot.dubbo - dubbo-api - 0.0.1-SNAPSHOT - - - - com.101tec - zkclient - 0.10 - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-duboo-filter/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplication.java b/springboot-integration-examples/springboot-duboo-filter/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplication.java deleted file mode 100644 index 3ad18963..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplication.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.consumer; - -import cn.lastwhisper.springboot.dubbo.consumer.quickstart.QuickstartConsumer; -import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.ConfigurableApplicationContext; - -@SpringBootApplication -@EnableDubboConfiguration -public class ConsumerApplication { - - public static void main(String[] args) { - ConfigurableApplicationContext context = SpringApplication.run(ConsumerApplication.class, args); - QuickstartConsumer quickstartConsumer = (QuickstartConsumer) context.getBean("quickstartConsumer"); - - quickstartConsumer.sendMessage("你好"); - - } - -} diff --git a/springboot-integration-examples/springboot-duboo-filter/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/quickstart/QuickstartConsumer.java b/springboot-integration-examples/springboot-duboo-filter/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/quickstart/QuickstartConsumer.java deleted file mode 100644 index cb6e6110..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/dubbo-consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/quickstart/QuickstartConsumer.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.consumer.quickstart; - -import cn.lastwhisper.springboot.dubbo.ServiceAPI; -import com.alibaba.dubbo.config.annotation.Reference; -import org.springframework.stereotype.Component; - -/** - * @author lastwhisper - */ -@Component -public class QuickstartConsumer { - //@Reference(url ="dubbo://localhost:20880") - @Reference(interfaceClass = ServiceAPI.class) - ServiceAPI serviceAPI; - - public void sendMessage(String message) { - System.out.println(serviceAPI.sendMessage(message)); - } -} diff --git a/springboot-integration-examples/springboot-duboo-filter/dubbo-consumer/src/main/resources/application.properties b/springboot-integration-examples/springboot-duboo-filter/dubbo-consumer/src/main/resources/application.properties deleted file mode 100644 index 6f0465df..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/dubbo-consumer/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -spring.application.name=dubbo-spring-boot-starter -spring.dubbo.registry=zookeeper://localhost:2181 \ No newline at end of file diff --git a/springboot-integration-examples/springboot-duboo-filter/dubbo-consumer/src/test/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplicationTests.java b/springboot-integration-examples/springboot-duboo-filter/dubbo-consumer/src/test/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplicationTests.java deleted file mode 100644 index 7c1d8b40..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/dubbo-consumer/src/test/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.consumer; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class ConsumerApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/pom.xml b/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/pom.xml deleted file mode 100644 index 40ded237..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/pom.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.7.RELEASE - - - cn.lastwhisper.springboot.dubbo - dubbo-provider - 0.0.1-SNAPSHOT - dubbo-provider - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - com.alibaba.spring.boot - dubbo-spring-boot-starter - 2.0.0 - - - - cn.lastwhisper.springboot.dubbo - dubbo-api - 0.0.1-SNAPSHOT - - - - com.101tec - zkclient - 0.10 - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplication.java b/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplication.java deleted file mode 100644 index 2d9530d2..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplication.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.provider; - -import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -@EnableDubboConfiguration -public class ProviderApplication { - - public static void main(String[] args) { - SpringApplication.run(ProviderApplication.class, args); - - - } - -} diff --git a/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/filter/MyFilter.java b/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/filter/MyFilter.java deleted file mode 100644 index 48c03acc..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/filter/MyFilter.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.provider.filter; - -import com.alibaba.dubbo.rpc.*; - -/** - * @author lastwhisper - */ -public class MyFilter implements Filter { - @Override - public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { - System.out.println("服务调用之前"); - Result invoke = invoker.invoke(invocation); - System.out.println("服务调用之后"); - return invoke; - - } -} diff --git a/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/quickstart/QuickstartServiceImpl.java b/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/quickstart/QuickstartServiceImpl.java deleted file mode 100644 index 26729bce..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/quickstart/QuickstartServiceImpl.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.provider.quickstart; - -import cn.lastwhisper.springboot.dubbo.ServiceAPI; -import com.alibaba.dubbo.config.annotation.Service; -import org.springframework.stereotype.Component; - -/** - * @author lastwhisper - */ -@Component -@Service(interfaceClass = ServiceAPI.class) -public class QuickstartServiceImpl implements ServiceAPI { - - @Override - public String sendMessage(String message) { - return "quickstart-provider-message=" + message; - } -} diff --git a/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter b/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter deleted file mode 100644 index e195640e..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter +++ /dev/null @@ -1 +0,0 @@ -MyFilterExt=cn.lastwhisper.springboot.dubbo.provider.filter.MyFilter \ No newline at end of file diff --git a/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/main/resources/application.properties b/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/main/resources/application.properties deleted file mode 100644 index 919697c2..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/main/resources/application.properties +++ /dev/null @@ -1,4 +0,0 @@ -spring.application.name=dubbo-spring-boot-starter -spring.dubbo.server=true -spring.dubbo.registry=zookeeper://localhost:2181 -spring.dubbo.provider.filter=MyFilterExt \ No newline at end of file diff --git a/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/test/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplicationTests.java b/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/test/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplicationTests.java deleted file mode 100644 index 2ceac86a..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/dubbo-provider/src/test/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.provider; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class ProviderApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-duboo-filter/pom.xml b/springboot-integration-examples/springboot-duboo-filter/pom.xml deleted file mode 100644 index 6de1e68c..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - 4.0.0 - pom - - dubbo-api - - - org.springframework.boot - spring-boot-starter-parent - 2.1.7.RELEASE - - - cn.lastwhisper.springboot.dubbo - springboot-duboo - 0.0.1-SNAPSHOT - springboot-duboo - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-duboo-filter/src/main/java/cn/lastwhisper/springboot/dubbo/springbootduboo/SpringbootDubooApplication.java b/springboot-integration-examples/springboot-duboo-filter/src/main/java/cn/lastwhisper/springboot/dubbo/springbootduboo/SpringbootDubooApplication.java deleted file mode 100644 index 02963579..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/src/main/java/cn/lastwhisper/springboot/dubbo/springbootduboo/SpringbootDubooApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.springbootduboo; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SpringbootDubooApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringbootDubooApplication.class, args); - } - -} diff --git a/springboot-integration-examples/springboot-duboo-filter/src/test/java/cn/lastwhisper/springboot/dubbo/springbootduboo/SpringbootDubooApplicationTests.java b/springboot-integration-examples/springboot-duboo-filter/src/test/java/cn/lastwhisper/springboot/dubbo/springbootduboo/SpringbootDubooApplicationTests.java deleted file mode 100644 index 213364d4..00000000 --- a/springboot-integration-examples/springboot-duboo-filter/src/test/java/cn/lastwhisper/springboot/dubbo/springbootduboo/SpringbootDubooApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.springbootduboo; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class SpringbootDubooApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-duboo/.gitignore b/springboot-integration-examples/springboot-duboo/.gitignore deleted file mode 100644 index a2a3040a..00000000 --- a/springboot-integration-examples/springboot-duboo/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/** -!**/src/test/** - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ - -### VS Code ### -.vscode/ diff --git a/springboot-integration-examples/springboot-duboo/.mvn/wrapper/MavenWrapperDownloader.java b/springboot-integration-examples/springboot-duboo/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index 7f91a56e..00000000 --- a/springboot-integration-examples/springboot-duboo/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF 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 - - https://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. -*/ - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.Properties; - -public class MavenWrapperDownloader { - - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = - "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if (mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if (mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: : " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if (!outputFile.getParentFile().exists()) { - if (!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/springboot-integration-examples/springboot-duboo/.mvn/wrapper/maven-wrapper.jar b/springboot-integration-examples/springboot-duboo/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 01e67997..00000000 Binary files a/springboot-integration-examples/springboot-duboo/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/springboot-integration-examples/springboot-duboo/.mvn/wrapper/maven-wrapper.properties b/springboot-integration-examples/springboot-duboo/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index cd0d451c..00000000 --- a/springboot-integration-examples/springboot-duboo/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip diff --git a/springboot-integration-examples/springboot-duboo/consumer/.gitignore b/springboot-integration-examples/springboot-duboo/consumer/.gitignore deleted file mode 100644 index a2a3040a..00000000 --- a/springboot-integration-examples/springboot-duboo/consumer/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/** -!**/src/test/** - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ - -### VS Code ### -.vscode/ diff --git a/springboot-integration-examples/springboot-duboo/consumer/.mvn/wrapper/MavenWrapperDownloader.java b/springboot-integration-examples/springboot-duboo/consumer/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index 7f91a56e..00000000 --- a/springboot-integration-examples/springboot-duboo/consumer/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF 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 - - https://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. -*/ - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.Properties; - -public class MavenWrapperDownloader { - - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = - "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if (mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if (mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: : " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if (!outputFile.getParentFile().exists()) { - if (!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/springboot-integration-examples/springboot-duboo/consumer/.mvn/wrapper/maven-wrapper.jar b/springboot-integration-examples/springboot-duboo/consumer/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 01e67997..00000000 Binary files a/springboot-integration-examples/springboot-duboo/consumer/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/springboot-integration-examples/springboot-duboo/consumer/.mvn/wrapper/maven-wrapper.properties b/springboot-integration-examples/springboot-duboo/consumer/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index cd0d451c..00000000 --- a/springboot-integration-examples/springboot-duboo/consumer/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip diff --git a/springboot-integration-examples/springboot-duboo/consumer/mvnw b/springboot-integration-examples/springboot-duboo/consumer/mvnw deleted file mode 100644 index 8b9da3b8..00000000 --- a/springboot-integration-examples/springboot-duboo/consumer/mvnw +++ /dev/null @@ -1,286 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF 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 -# -# https://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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - wget "$jarUrl" -O "$wrapperJarPath" - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - curl -o "$wrapperJarPath" "$jarUrl" - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/springboot-integration-examples/springboot-duboo/consumer/mvnw.cmd b/springboot-integration-examples/springboot-duboo/consumer/mvnw.cmd deleted file mode 100644 index fef5a8f7..00000000 --- a/springboot-integration-examples/springboot-duboo/consumer/mvnw.cmd +++ /dev/null @@ -1,161 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" -FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - echo Found %WRAPPER_JAR% -) else ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" - echo Finished downloading %WRAPPER_JAR% -) -@REM End of extension - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/springboot-integration-examples/springboot-duboo/consumer/pom.xml b/springboot-integration-examples/springboot-duboo/consumer/pom.xml deleted file mode 100644 index a9175cea..00000000 --- a/springboot-integration-examples/springboot-duboo/consumer/pom.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.7.RELEASE - - - cn.lastwhisper.springboot.dubbo - consumer - 0.0.1-SNAPSHOT - consumer - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - com.alibaba.spring.boot - dubbo-spring-boot-starter - 2.0.0 - - - - cn.lastwhisper.springboot.dubbo - dubbo-api - 0.0.1-SNAPSHOT - - - - com.101tec - zkclient - 0.10 - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-duboo/consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplication.java b/springboot-integration-examples/springboot-duboo/consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplication.java deleted file mode 100644 index 3ad18963..00000000 --- a/springboot-integration-examples/springboot-duboo/consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplication.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.consumer; - -import cn.lastwhisper.springboot.dubbo.consumer.quickstart.QuickstartConsumer; -import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.ConfigurableApplicationContext; - -@SpringBootApplication -@EnableDubboConfiguration -public class ConsumerApplication { - - public static void main(String[] args) { - ConfigurableApplicationContext context = SpringApplication.run(ConsumerApplication.class, args); - QuickstartConsumer quickstartConsumer = (QuickstartConsumer) context.getBean("quickstartConsumer"); - - quickstartConsumer.sendMessage("你好"); - - } - -} diff --git a/springboot-integration-examples/springboot-duboo/consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/quickstart/QuickstartConsumer.java b/springboot-integration-examples/springboot-duboo/consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/quickstart/QuickstartConsumer.java deleted file mode 100644 index cb6e6110..00000000 --- a/springboot-integration-examples/springboot-duboo/consumer/src/main/java/cn/lastwhisper/springboot/dubbo/consumer/quickstart/QuickstartConsumer.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.consumer.quickstart; - -import cn.lastwhisper.springboot.dubbo.ServiceAPI; -import com.alibaba.dubbo.config.annotation.Reference; -import org.springframework.stereotype.Component; - -/** - * @author lastwhisper - */ -@Component -public class QuickstartConsumer { - //@Reference(url ="dubbo://localhost:20880") - @Reference(interfaceClass = ServiceAPI.class) - ServiceAPI serviceAPI; - - public void sendMessage(String message) { - System.out.println(serviceAPI.sendMessage(message)); - } -} diff --git a/springboot-integration-examples/springboot-duboo/consumer/src/main/resources/application.properties b/springboot-integration-examples/springboot-duboo/consumer/src/main/resources/application.properties deleted file mode 100644 index 6f0465df..00000000 --- a/springboot-integration-examples/springboot-duboo/consumer/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -spring.application.name=dubbo-spring-boot-starter -spring.dubbo.registry=zookeeper://localhost:2181 \ No newline at end of file diff --git a/springboot-integration-examples/springboot-duboo/consumer/src/test/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplicationTests.java b/springboot-integration-examples/springboot-duboo/consumer/src/test/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplicationTests.java deleted file mode 100644 index 7c1d8b40..00000000 --- a/springboot-integration-examples/springboot-duboo/consumer/src/test/java/cn/lastwhisper/springboot/dubbo/consumer/ConsumerApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.consumer; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class ConsumerApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-duboo/dubbo-api/pom.xml b/springboot-integration-examples/springboot-duboo/dubbo-api/pom.xml deleted file mode 100644 index 911d7ddf..00000000 --- a/springboot-integration-examples/springboot-duboo/dubbo-api/pom.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - springboot-duboo - cn.lastwhisper.springboot.dubbo - 0.0.1-SNAPSHOT - - 4.0.0 - - cn.lastwhisper.springboot.dubbo - dubbo-api - - dubbo-api - - http://www.example.com - - - UTF-8 - 1.7 - 1.7 - - - - - junit - junit - 4.11 - test - - - - - - - - - maven-clean-plugin - 3.1.0 - - - - maven-resources-plugin - 3.0.2 - - - maven-compiler-plugin - 3.8.0 - - - maven-surefire-plugin - 2.22.1 - - - maven-jar-plugin - 3.0.2 - - - maven-install-plugin - 2.5.2 - - - maven-deploy-plugin - 2.8.2 - - - - maven-site-plugin - 3.7.1 - - - maven-project-info-reports-plugin - 3.0.0 - - - - - diff --git a/springboot-integration-examples/springboot-duboo/dubbo-api/src/main/java/cn/lastwhisper/springboot/dubbo/ServiceAPI.java b/springboot-integration-examples/springboot-duboo/dubbo-api/src/main/java/cn/lastwhisper/springboot/dubbo/ServiceAPI.java deleted file mode 100644 index 8231e710..00000000 --- a/springboot-integration-examples/springboot-duboo/dubbo-api/src/main/java/cn/lastwhisper/springboot/dubbo/ServiceAPI.java +++ /dev/null @@ -1,5 +0,0 @@ -package cn.lastwhisper.springboot.dubbo; - -public interface ServiceAPI { - String sendMessage(String message); -} diff --git a/springboot-integration-examples/springboot-duboo/dubbo-api/src/test/java/cn/lastwhisper/springboot/dubbo/AppTest.java b/springboot-integration-examples/springboot-duboo/dubbo-api/src/test/java/cn/lastwhisper/springboot/dubbo/AppTest.java deleted file mode 100644 index 6aaab91b..00000000 --- a/springboot-integration-examples/springboot-duboo/dubbo-api/src/test/java/cn/lastwhisper/springboot/dubbo/AppTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.lastwhisper.springboot.dubbo; - -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -/** - * Unit test for simple App. - */ -public class AppTest -{ - /** - * Rigorous Test :-) - */ - @Test - public void shouldAnswerWithTrue() - { - assertTrue( true ); - } -} diff --git a/springboot-integration-examples/springboot-duboo/mvnw b/springboot-integration-examples/springboot-duboo/mvnw deleted file mode 100644 index 8b9da3b8..00000000 --- a/springboot-integration-examples/springboot-duboo/mvnw +++ /dev/null @@ -1,286 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF 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 -# -# https://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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - wget "$jarUrl" -O "$wrapperJarPath" - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - curl -o "$wrapperJarPath" "$jarUrl" - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/springboot-integration-examples/springboot-duboo/mvnw.cmd b/springboot-integration-examples/springboot-duboo/mvnw.cmd deleted file mode 100644 index fef5a8f7..00000000 --- a/springboot-integration-examples/springboot-duboo/mvnw.cmd +++ /dev/null @@ -1,161 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" -FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - echo Found %WRAPPER_JAR% -) else ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" - echo Finished downloading %WRAPPER_JAR% -) -@REM End of extension - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/springboot-integration-examples/springboot-duboo/pom.xml b/springboot-integration-examples/springboot-duboo/pom.xml deleted file mode 100644 index 6de1e68c..00000000 --- a/springboot-integration-examples/springboot-duboo/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - 4.0.0 - pom - - dubbo-api - - - org.springframework.boot - spring-boot-starter-parent - 2.1.7.RELEASE - - - cn.lastwhisper.springboot.dubbo - springboot-duboo - 0.0.1-SNAPSHOT - springboot-duboo - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-duboo/provider/.gitignore b/springboot-integration-examples/springboot-duboo/provider/.gitignore deleted file mode 100644 index a2a3040a..00000000 --- a/springboot-integration-examples/springboot-duboo/provider/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/** -!**/src/test/** - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ - -### VS Code ### -.vscode/ diff --git a/springboot-integration-examples/springboot-duboo/provider/.mvn/wrapper/MavenWrapperDownloader.java b/springboot-integration-examples/springboot-duboo/provider/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index 7f91a56e..00000000 --- a/springboot-integration-examples/springboot-duboo/provider/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF 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 - - https://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. -*/ - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.Properties; - -public class MavenWrapperDownloader { - - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = - "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if (mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if (mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: : " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if (!outputFile.getParentFile().exists()) { - if (!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/springboot-integration-examples/springboot-duboo/provider/.mvn/wrapper/maven-wrapper.jar b/springboot-integration-examples/springboot-duboo/provider/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 01e67997..00000000 Binary files a/springboot-integration-examples/springboot-duboo/provider/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/springboot-integration-examples/springboot-duboo/provider/.mvn/wrapper/maven-wrapper.properties b/springboot-integration-examples/springboot-duboo/provider/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index cd0d451c..00000000 --- a/springboot-integration-examples/springboot-duboo/provider/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip diff --git a/springboot-integration-examples/springboot-duboo/provider/mvnw b/springboot-integration-examples/springboot-duboo/provider/mvnw deleted file mode 100644 index 8b9da3b8..00000000 --- a/springboot-integration-examples/springboot-duboo/provider/mvnw +++ /dev/null @@ -1,286 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF 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 -# -# https://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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - wget "$jarUrl" -O "$wrapperJarPath" - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - curl -o "$wrapperJarPath" "$jarUrl" - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/springboot-integration-examples/springboot-duboo/provider/mvnw.cmd b/springboot-integration-examples/springboot-duboo/provider/mvnw.cmd deleted file mode 100644 index fef5a8f7..00000000 --- a/springboot-integration-examples/springboot-duboo/provider/mvnw.cmd +++ /dev/null @@ -1,161 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" -FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - echo Found %WRAPPER_JAR% -) else ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" - echo Finished downloading %WRAPPER_JAR% -) -@REM End of extension - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/springboot-integration-examples/springboot-duboo/provider/pom.xml b/springboot-integration-examples/springboot-duboo/provider/pom.xml deleted file mode 100644 index 8f919c2a..00000000 --- a/springboot-integration-examples/springboot-duboo/provider/pom.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.7.RELEASE - - - cn.lastwhisper.springboot.dubbo - provider - 0.0.1-SNAPSHOT - provider - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - com.alibaba.spring.boot - dubbo-spring-boot-starter - 2.0.0 - - - - cn.lastwhisper.springboot.dubbo - dubbo-api - 0.0.1-SNAPSHOT - - - - com.101tec - zkclient - 0.10 - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-duboo/provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplication.java b/springboot-integration-examples/springboot-duboo/provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplication.java deleted file mode 100644 index 2d9530d2..00000000 --- a/springboot-integration-examples/springboot-duboo/provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplication.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.provider; - -import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -@EnableDubboConfiguration -public class ProviderApplication { - - public static void main(String[] args) { - SpringApplication.run(ProviderApplication.class, args); - - - } - -} diff --git a/springboot-integration-examples/springboot-duboo/provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/quickstart/QuickstartServiceImpl.java b/springboot-integration-examples/springboot-duboo/provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/quickstart/QuickstartServiceImpl.java deleted file mode 100644 index 26729bce..00000000 --- a/springboot-integration-examples/springboot-duboo/provider/src/main/java/cn/lastwhisper/springboot/dubbo/provider/quickstart/QuickstartServiceImpl.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.provider.quickstart; - -import cn.lastwhisper.springboot.dubbo.ServiceAPI; -import com.alibaba.dubbo.config.annotation.Service; -import org.springframework.stereotype.Component; - -/** - * @author lastwhisper - */ -@Component -@Service(interfaceClass = ServiceAPI.class) -public class QuickstartServiceImpl implements ServiceAPI { - - @Override - public String sendMessage(String message) { - return "quickstart-provider-message=" + message; - } -} diff --git a/springboot-integration-examples/springboot-duboo/provider/src/main/resources/application.properties b/springboot-integration-examples/springboot-duboo/provider/src/main/resources/application.properties deleted file mode 100644 index 0d2d5ac4..00000000 --- a/springboot-integration-examples/springboot-duboo/provider/src/main/resources/application.properties +++ /dev/null @@ -1,3 +0,0 @@ -spring.application.name=dubbo-spring-boot-starter -spring.dubbo.server=true -spring.dubbo.registry=zookeeper://localhost:2181 \ No newline at end of file diff --git a/springboot-integration-examples/springboot-duboo/provider/src/test/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplicationTests.java b/springboot-integration-examples/springboot-duboo/provider/src/test/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplicationTests.java deleted file mode 100644 index 2ceac86a..00000000 --- a/springboot-integration-examples/springboot-duboo/provider/src/test/java/cn/lastwhisper/springboot/dubbo/provider/ProviderApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.provider; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class ProviderApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-duboo/src/main/java/cn/lastwhisper/springboot/dubbo/springbootduboo/SpringbootDubooApplication.java b/springboot-integration-examples/springboot-duboo/src/main/java/cn/lastwhisper/springboot/dubbo/springbootduboo/SpringbootDubooApplication.java deleted file mode 100644 index 02963579..00000000 --- a/springboot-integration-examples/springboot-duboo/src/main/java/cn/lastwhisper/springboot/dubbo/springbootduboo/SpringbootDubooApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.springbootduboo; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SpringbootDubooApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringbootDubooApplication.class, args); - } - -} diff --git a/springboot-integration-examples/springboot-duboo/src/main/resources/application.properties b/springboot-integration-examples/springboot-duboo/src/main/resources/application.properties deleted file mode 100644 index 8b137891..00000000 --- a/springboot-integration-examples/springboot-duboo/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/springboot-integration-examples/springboot-duboo/src/test/java/cn/lastwhisper/springboot/dubbo/springbootduboo/SpringbootDubooApplicationTests.java b/springboot-integration-examples/springboot-duboo/src/test/java/cn/lastwhisper/springboot/dubbo/springbootduboo/SpringbootDubooApplicationTests.java deleted file mode 100644 index 213364d4..00000000 --- a/springboot-integration-examples/springboot-duboo/src/test/java/cn/lastwhisper/springboot/dubbo/springbootduboo/SpringbootDubooApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.springboot.dubbo.springbootduboo; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class SpringbootDubooApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-flyway-old/pom.xml b/springboot-integration-examples/springboot-flyway-old/pom.xml deleted file mode 100644 index 73052707..00000000 --- a/springboot-integration-examples/springboot-flyway-old/pom.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - 4.0.0 - - com.didispace - Chapter3-2-9 - 1.0.0 - jar - - Chapter3-2-9 - Spring Boot with JDBCTemplate - - - org.springframework.boot - spring-boot-starter-parent - 1.5.9.RELEASE - - - - - UTF-8 - 1.8 - - - - - org.springframework.boot - spring-boot-starter-test - test - - - - mysql - mysql-connector-java - 5.1.21 - - - - org.springframework.boot - spring-boot-starter-jdbc - - - - org.flywaydb - flyway-core - 5.0.3 - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - \ No newline at end of file diff --git a/springboot-integration-examples/springboot-flyway-old/src/main/java/com/didispace/Application.java b/springboot-integration-examples/springboot-flyway-old/src/main/java/com/didispace/Application.java deleted file mode 100644 index 2a14b751..00000000 --- a/springboot-integration-examples/springboot-flyway-old/src/main/java/com/didispace/Application.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.didispace; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class Application { - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } - -} diff --git a/springboot-integration-examples/springboot-flyway-old/src/main/java/com/didispace/service/UserService.java b/springboot-integration-examples/springboot-flyway-old/src/main/java/com/didispace/service/UserService.java deleted file mode 100644 index 620a443f..00000000 --- a/springboot-integration-examples/springboot-flyway-old/src/main/java/com/didispace/service/UserService.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.didispace.service; - -/** - * @author 程序猿DD - * @version 1.0.0 - * @date 16/3/17 下午7:04. - * @blog http://blog.didispace.com - */ -public interface UserService { - - /** - * 新增一个用户 - * @param name - * @param age - */ - void create(String name, Integer age); - - /** - * 根据name删除一个用户高 - * @param name - */ - void deleteByName(String name); - - /** - * 获取用户总量 - */ - Integer getAllUsers(); - - /** - * 删除所有用户 - */ - void deleteAllUsers(); - - -} diff --git a/springboot-integration-examples/springboot-flyway-old/src/main/java/com/didispace/service/UserServiceImpl.java b/springboot-integration-examples/springboot-flyway-old/src/main/java/com/didispace/service/UserServiceImpl.java deleted file mode 100644 index 05c04f09..00000000 --- a/springboot-integration-examples/springboot-flyway-old/src/main/java/com/didispace/service/UserServiceImpl.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.didispace.service; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.stereotype.Service; - -/** - * @author 程序猿DD - * @version 1.0.0 - * @date 16/3/17 下午6:44. - * @blog http://blog.didispace.com - */ -@Service -public class UserServiceImpl implements UserService { - - @Autowired - private JdbcTemplate jdbcTemplate; - - @Override - public void create(String name, Integer age) { - jdbcTemplate.update("insert into user(NAME, AGE) values(?, ?)", name, age); - } - - @Override - public void deleteByName(String name) { - jdbcTemplate.update("delete from user where NAME = ?", name); - } - - @Override - public Integer getAllUsers() { - return jdbcTemplate.queryForObject("select count(1) from user", Integer.class); - } - - @Override - public void deleteAllUsers() { - jdbcTemplate.update("delete from user"); - } -} diff --git a/springboot-integration-examples/springboot-flyway-old/src/main/resources/application.properties b/springboot-integration-examples/springboot-flyway-old/src/main/resources/application.properties deleted file mode 100644 index 5a82ecff..00000000 --- a/springboot-integration-examples/springboot-flyway-old/src/main/resources/application.properties +++ /dev/null @@ -1,6 +0,0 @@ -spring.datasource.url=jdbc:mysql://localhost:3306/test -spring.datasource.username=root -spring.datasource.password=root -spring.datasource.driver-class-name=com.mysql.jdbc.Driver - -flyway.locations=classpath:/db \ No newline at end of file diff --git a/springboot-integration-examples/springboot-flyway-old/src/main/resources/db/V1__Base_version.sql b/springboot-integration-examples/springboot-flyway-old/src/main/resources/db/V1__Base_version.sql deleted file mode 100644 index ff8bce17..00000000 --- a/springboot-integration-examples/springboot-flyway-old/src/main/resources/db/V1__Base_version.sql +++ /dev/null @@ -1,9 +0,0 @@ -DROP TABLE IF EXISTS `user` ; - - -CREATE TABLE `user` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', - `name` varchar(30) NOT NULL COMMENT '姓名', - `age` int(5) DEFAULT NULL COMMENT '年龄', - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/springboot-integration-examples/springboot-flyway-old/src/test/java/com/didispace/ApplicationTests.java b/springboot-integration-examples/springboot-flyway-old/src/test/java/com/didispace/ApplicationTests.java deleted file mode 100644 index ec6f8985..00000000 --- a/springboot-integration-examples/springboot-flyway-old/src/test/java/com/didispace/ApplicationTests.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.didispace; - -import com.didispace.service.UserService; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - - -@RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest -public class ApplicationTests { - - @Autowired - private UserService userSerivce; - - @Before - public void setUp() { - // 准备,清空user表 - userSerivce.deleteAllUsers(); - } - - @Test - public void test() throws Exception { - // 插入5个用户 - userSerivce.create("a", 1); - userSerivce.create("b", 2); - userSerivce.create("c", 3); - userSerivce.create("d", 4); - userSerivce.create("e", 5); - - // 查数据库,应该有5个用户 - Assert.assertEquals(5, userSerivce.getAllUsers().intValue()); - - // 删除两个用户 - userSerivce.deleteByName("a"); - userSerivce.deleteByName("e"); - - // 查数据库,应该有5个用户 - Assert.assertEquals(3, userSerivce.getAllUsers().intValue()); - - } - - -} diff --git a/springboot-integration-examples/springboot-flyway/.gitignore b/springboot-integration-examples/springboot-flyway/.gitignore deleted file mode 100644 index a2a3040a..00000000 --- a/springboot-integration-examples/springboot-flyway/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/** -!**/src/test/** - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ - -### VS Code ### -.vscode/ diff --git a/springboot-integration-examples/springboot-flyway/.mvn/wrapper/MavenWrapperDownloader.java b/springboot-integration-examples/springboot-flyway/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index 7f91a56e..00000000 --- a/springboot-integration-examples/springboot-flyway/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF 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 - - https://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. -*/ - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.Properties; - -public class MavenWrapperDownloader { - - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = - "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if (mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if (mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: : " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if (!outputFile.getParentFile().exists()) { - if (!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/springboot-integration-examples/springboot-flyway/.mvn/wrapper/maven-wrapper.jar b/springboot-integration-examples/springboot-flyway/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 01e67997..00000000 Binary files a/springboot-integration-examples/springboot-flyway/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/springboot-integration-examples/springboot-flyway/.mvn/wrapper/maven-wrapper.properties b/springboot-integration-examples/springboot-flyway/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index cd0d451c..00000000 --- a/springboot-integration-examples/springboot-flyway/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip diff --git a/springboot-integration-examples/springboot-flyway/mvnw b/springboot-integration-examples/springboot-flyway/mvnw deleted file mode 100644 index 8b9da3b8..00000000 --- a/springboot-integration-examples/springboot-flyway/mvnw +++ /dev/null @@ -1,286 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF 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 -# -# https://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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - wget "$jarUrl" -O "$wrapperJarPath" - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - curl -o "$wrapperJarPath" "$jarUrl" - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/springboot-integration-examples/springboot-flyway/mvnw.cmd b/springboot-integration-examples/springboot-flyway/mvnw.cmd deleted file mode 100644 index fef5a8f7..00000000 --- a/springboot-integration-examples/springboot-flyway/mvnw.cmd +++ /dev/null @@ -1,161 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" -FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - echo Found %WRAPPER_JAR% -) else ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" - echo Finished downloading %WRAPPER_JAR% -) -@REM End of extension - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/springboot-integration-examples/springboot-flyway/pom.xml b/springboot-integration-examples/springboot-flyway/pom.xml deleted file mode 100644 index 0f6397cb..00000000 --- a/springboot-integration-examples/springboot-flyway/pom.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.9.RELEASE - - - cn.lastwhisper.springboot - flyway - 0.0.1-SNAPSHOT - flyway - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - - org.flywaydb - flyway-core - 6.0.6 - - - - - mysql - mysql-connector-java - 8.0.17 - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-flyway/src/main/java/cn/lastwhisper/springboot/flyway/App.java b/springboot-integration-examples/springboot-flyway/src/main/java/cn/lastwhisper/springboot/flyway/App.java deleted file mode 100644 index f79de26b..00000000 --- a/springboot-integration-examples/springboot-flyway/src/main/java/cn/lastwhisper/springboot/flyway/App.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.springboot.flyway; - -import org.flywaydb.core.Flyway; - -public class App { - public static void main(String[] args) { - // Create the Flyway instance and point it to the database - Flyway flyway = Flyway.configure().dataSource("jdbc:mysql://localhost:3306/flyway", "root", "root").load(); - - // Start the migration - flyway.migrate(); - } -} \ No newline at end of file diff --git a/springboot-integration-examples/springboot-flyway/src/main/java/cn/lastwhisper/springboot/flyway/FlywayApplication.java b/springboot-integration-examples/springboot-flyway/src/main/java/cn/lastwhisper/springboot/flyway/FlywayApplication.java deleted file mode 100644 index 97a323cb..00000000 --- a/springboot-integration-examples/springboot-flyway/src/main/java/cn/lastwhisper/springboot/flyway/FlywayApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.springboot.flyway; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class FlywayApplication { - - public static void main(String[] args) { - SpringApplication.run(FlywayApplication.class, args); - } - -} diff --git a/springboot-integration-examples/springboot-flyway/src/main/resources/application.properties b/springboot-integration-examples/springboot-flyway/src/main/resources/application.properties deleted file mode 100644 index 8b137891..00000000 --- a/springboot-integration-examples/springboot-flyway/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/springboot-integration-examples/springboot-flyway/src/test/java/cn/lastwhisper/springboot/flyway/FlywayApplicationTests.java b/springboot-integration-examples/springboot-flyway/src/test/java/cn/lastwhisper/springboot/flyway/FlywayApplicationTests.java deleted file mode 100644 index 9dfed952..00000000 --- a/springboot-integration-examples/springboot-flyway/src/test/java/cn/lastwhisper/springboot/flyway/FlywayApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.springboot.flyway; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class FlywayApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-mybatisplus/.gitignore b/springboot-integration-examples/springboot-mybatisplus/.gitignore deleted file mode 100644 index 153c9335..00000000 --- a/springboot-integration-examples/springboot-mybatisplus/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -HELP.md -/target/ -!.mvn/wrapper/maven-wrapper.jar - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -/build/ - -### VS Code ### -.vscode/ diff --git a/springboot-integration-examples/springboot-mybatisplus/.mvn/wrapper/MavenWrapperDownloader.java b/springboot-integration-examples/springboot-mybatisplus/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index 7f91a56e..00000000 --- a/springboot-integration-examples/springboot-mybatisplus/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF 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 - - https://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. -*/ - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.Properties; - -public class MavenWrapperDownloader { - - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = - "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if (mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if (mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: : " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if (!outputFile.getParentFile().exists()) { - if (!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/springboot-integration-examples/springboot-mybatisplus/.mvn/wrapper/maven-wrapper.jar b/springboot-integration-examples/springboot-mybatisplus/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 01e67997..00000000 Binary files a/springboot-integration-examples/springboot-mybatisplus/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/springboot-integration-examples/springboot-mybatisplus/.mvn/wrapper/maven-wrapper.properties b/springboot-integration-examples/springboot-mybatisplus/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index cd0d451c..00000000 --- a/springboot-integration-examples/springboot-mybatisplus/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip diff --git a/springboot-integration-examples/springboot-mybatisplus/mvnw b/springboot-integration-examples/springboot-mybatisplus/mvnw deleted file mode 100644 index 8b9da3b8..00000000 --- a/springboot-integration-examples/springboot-mybatisplus/mvnw +++ /dev/null @@ -1,286 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF 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 -# -# https://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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - wget "$jarUrl" -O "$wrapperJarPath" - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - curl -o "$wrapperJarPath" "$jarUrl" - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/springboot-integration-examples/springboot-mybatisplus/mvnw.cmd b/springboot-integration-examples/springboot-mybatisplus/mvnw.cmd deleted file mode 100644 index fef5a8f7..00000000 --- a/springboot-integration-examples/springboot-mybatisplus/mvnw.cmd +++ /dev/null @@ -1,161 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" -FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - echo Found %WRAPPER_JAR% -) else ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" - echo Finished downloading %WRAPPER_JAR% -) -@REM End of extension - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/springboot-integration-examples/springboot-mybatisplus/pom.xml b/springboot-integration-examples/springboot-mybatisplus/pom.xml deleted file mode 100644 index 0d5b47bd..00000000 --- a/springboot-integration-examples/springboot-mybatisplus/pom.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.4.RELEASE - - - cn.lastwhisper - springbootmybatisplus - 0.0.1-SNAPSHOT - springbootmybatisplus - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - org.projectlombok - lombok - true - - - - com.baomidou - mybatis-plus-boot-starter - 3.1.1 - - - - mysql - mysql-connector-java - 5.1.47 - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-mybatisplus/sql/mybatisplus.sql b/springboot-integration-examples/springboot-mybatisplus/sql/mybatisplus.sql deleted file mode 100644 index e2864c3f..00000000 --- a/springboot-integration-examples/springboot-mybatisplus/sql/mybatisplus.sql +++ /dev/null @@ -1,41 +0,0 @@ -/* - Navicat Premium Data Transfer - - Source Server : 本地数据库-mysql5.7 - Source Server Type : MySQL - Source Server Version : 50724 - Source Host : localhost:3306 - Source Schema : mybatisplus - - Target Server Type : MySQL - Target Server Version : 50724 - File Encoding : 65001 - - Date: 02/05/2019 11:00:02 -*/ - -SET NAMES utf8mb4; -SET FOREIGN_KEY_CHECKS = 0; - --- ---------------------------- --- Table structure for user --- ---------------------------- -DROP TABLE IF EXISTS `user`; -CREATE TABLE `user` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', - `name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '姓名', - `age` int(11) NULL DEFAULT NULL COMMENT '年龄', - `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱', - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; - --- ---------------------------- --- Records of user --- ---------------------------- -INSERT INTO `user` VALUES (1, 'Jone', 18, 'test1@baomidou.com'); -INSERT INTO `user` VALUES (2, 'Jack', 20, 'test2@baomidou.com'); -INSERT INTO `user` VALUES (3, 'Tom', 28, 'test3@baomidou.com'); -INSERT INTO `user` VALUES (4, 'Sandy', 21, 'test4@baomidou.com'); -INSERT INTO `user` VALUES (5, 'gaojun', 24, 'gaojun56@163.com'); - -SET FOREIGN_KEY_CHECKS = 1; diff --git a/springboot-integration-examples/springboot-mybatisplus/src/main/java/cn/lastwhisper/springbootmybatisplus/SpringbootmybatisplusApplication.java b/springboot-integration-examples/springboot-mybatisplus/src/main/java/cn/lastwhisper/springbootmybatisplus/SpringbootmybatisplusApplication.java deleted file mode 100644 index 7a345070..00000000 --- a/springboot-integration-examples/springboot-mybatisplus/src/main/java/cn/lastwhisper/springbootmybatisplus/SpringbootmybatisplusApplication.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.lastwhisper.springbootmybatisplus; - -import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -@MapperScan("cn.lastwhisper.springbootmybatisplus.mapper") //设置mapper接口的扫描包 -@SpringBootApplication -public class SpringbootmybatisplusApplication { - - /** - * 分页插件 - */ - @Bean - public PaginationInterceptor paginationInterceptor() { - return new PaginationInterceptor(); - } - - public static void main(String[] args) { - SpringApplication.run(SpringbootmybatisplusApplication.class, args); - } - -} diff --git a/springboot-integration-examples/springboot-mybatisplus/src/main/java/cn/lastwhisper/springbootmybatisplus/mapper/UserMapper.java b/springboot-integration-examples/springboot-mybatisplus/src/main/java/cn/lastwhisper/springbootmybatisplus/mapper/UserMapper.java deleted file mode 100644 index f8a29919..00000000 --- a/springboot-integration-examples/springboot-mybatisplus/src/main/java/cn/lastwhisper/springbootmybatisplus/mapper/UserMapper.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.lastwhisper.springbootmybatisplus.mapper; - -import cn.lastwhisper.springbootmybatisplus.pojo.User; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -/** - * @desc - * - * @author lastwhisper - * @email gaojun56@163.com - */ -public interface UserMapper extends BaseMapper { -} \ No newline at end of file diff --git a/springboot-integration-examples/springboot-mybatisplus/src/main/java/cn/lastwhisper/springbootmybatisplus/pojo/User.java b/springboot-integration-examples/springboot-mybatisplus/src/main/java/cn/lastwhisper/springbootmybatisplus/pojo/User.java deleted file mode 100644 index 264c3c01..00000000 --- a/springboot-integration-examples/springboot-mybatisplus/src/main/java/cn/lastwhisper/springbootmybatisplus/pojo/User.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.lastwhisper.springbootmybatisplus.pojo; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import lombok.Data; -import lombok.ToString; - -/** - * @desc - * - * @author lastwhisper - * @email gaojun56@163.com - */ -@Data -@ToString -public class User { - @TableId(value = "ID", type = IdType.AUTO) - private Long id; - private String name; - private Integer age; - private String email; -} diff --git a/springboot-integration-examples/springboot-mybatisplus/src/main/resources/application.properties b/springboot-integration-examples/springboot-mybatisplus/src/main/resources/application.properties deleted file mode 100644 index c243caf8..00000000 --- a/springboot-integration-examples/springboot-mybatisplus/src/main/resources/application.properties +++ /dev/null @@ -1,5 +0,0 @@ -spring.application.name = lastwhisper-mybatis-plus -spring.datasource.driver-class-name=com.mysql.jdbc.Driver -spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mybatisplus?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false -spring.datasource.username=root -spring.datasource.password=root \ No newline at end of file diff --git a/springboot-integration-examples/springboot-mybatisplus/src/test/java/cn/lastwhisper/springbootmybatisplus/SpringbootmybatisplusApplicationTests.java b/springboot-integration-examples/springboot-mybatisplus/src/test/java/cn/lastwhisper/springbootmybatisplus/SpringbootmybatisplusApplicationTests.java deleted file mode 100644 index 6b6198e5..00000000 --- a/springboot-integration-examples/springboot-mybatisplus/src/test/java/cn/lastwhisper/springbootmybatisplus/SpringbootmybatisplusApplicationTests.java +++ /dev/null @@ -1,104 +0,0 @@ -package cn.lastwhisper.springbootmybatisplus; - -import cn.lastwhisper.springbootmybatisplus.mapper.UserMapper; -import cn.lastwhisper.springbootmybatisplus.pojo.User; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class SpringbootmybatisplusApplicationTests { - - - @Autowired - private UserMapper userMapper; - - @Test - public void testSelect() { - System.out.println(("----- selectAll method test ------")); - List userList = userMapper.selectList(null); - for (User user : userList) { - System.out.println(user); - } - } - - // like查询 - @Test - public void testselectByLike() { - QueryWrapper queryWrapper = new QueryWrapper<>(new User()); - // 查询名字中包含"o"的用户 - queryWrapper.like("name", "o"); - - List users = this.userMapper.selectList(queryWrapper); - for (User user : users) { - System.out.println(user); - } - } - - // 条件查询 - @Test - public void testselectByLe() { - QueryWrapper queryWrapper = new QueryWrapper<>(new User()); - //查询年龄小于等于20的用户 - queryWrapper.le("age", 20); - - List users = this.userMapper.selectList(queryWrapper); - for (User user : users) { - System.out.println(user); - } - } - - //插入数据 - @Test - public void testSave() { - User user = new User(); - user.setAge(21); - user.setEmail("gaojun56@163.com"); - user.setName("gaojun"); - int count = this.userMapper.insert(user); - System.out.println("新增数据成功! count => " + count); - } - - //删除数据 - @Test - public void testDelete() { - this.userMapper.deleteById(6L); - System.out.println("删除成功!"); - } - - //修改数据 - @Test - public void testUpdate() { - User user = new User(); - user.setId(5L); - user.setName("gaojun"); - user.setEmail("gaojun56@163.com"); - this.userMapper.updateById(user); - System.out.println("修改成功!"); - } - - //分页查询 - @Test - public void testselectPage() { - Page page = new Page<>(1, 2); - IPage userIPage = this.userMapper.selectPage(page, null); - System.out.println("总条数 ------> " + userIPage.getTotal()); - System.out.println("当前页数 ------> " + userIPage.getCurrent()); - System.out.println("当前每页显示数 ------> " + userIPage.getSize()); - List records = userIPage.getRecords(); - for (User user : records) { - System.out.println(user); - } - } - -} diff --git a/springboot-integration-examples/springboot-oss/.gitignore b/springboot-integration-examples/springboot-oss/.gitignore deleted file mode 100644 index 153c9335..00000000 --- a/springboot-integration-examples/springboot-oss/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -HELP.md -/target/ -!.mvn/wrapper/maven-wrapper.jar - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -/build/ - -### VS Code ### -.vscode/ diff --git a/springboot-integration-examples/springboot-oss/.mvn/wrapper/MavenWrapperDownloader.java b/springboot-integration-examples/springboot-oss/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index 7f91a56e..00000000 --- a/springboot-integration-examples/springboot-oss/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF 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 - - https://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. -*/ - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.Properties; - -public class MavenWrapperDownloader { - - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = - "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if (mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if (mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: : " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if (!outputFile.getParentFile().exists()) { - if (!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/springboot-integration-examples/springboot-oss/.mvn/wrapper/maven-wrapper.jar b/springboot-integration-examples/springboot-oss/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 01e67997..00000000 Binary files a/springboot-integration-examples/springboot-oss/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/springboot-integration-examples/springboot-oss/.mvn/wrapper/maven-wrapper.properties b/springboot-integration-examples/springboot-oss/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index cd0d451c..00000000 --- a/springboot-integration-examples/springboot-oss/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip diff --git a/springboot-integration-examples/springboot-oss/mvnw b/springboot-integration-examples/springboot-oss/mvnw deleted file mode 100644 index 8b9da3b8..00000000 --- a/springboot-integration-examples/springboot-oss/mvnw +++ /dev/null @@ -1,286 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF 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 -# -# https://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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - wget "$jarUrl" -O "$wrapperJarPath" - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - curl -o "$wrapperJarPath" "$jarUrl" - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/springboot-integration-examples/springboot-oss/mvnw.cmd b/springboot-integration-examples/springboot-oss/mvnw.cmd deleted file mode 100644 index fef5a8f7..00000000 --- a/springboot-integration-examples/springboot-oss/mvnw.cmd +++ /dev/null @@ -1,161 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" -FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - echo Found %WRAPPER_JAR% -) else ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" - echo Finished downloading %WRAPPER_JAR% -) -@REM End of extension - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/springboot-integration-examples/springboot-oss/pom.xml b/springboot-integration-examples/springboot-oss/pom.xml deleted file mode 100644 index c34123bb..00000000 --- a/springboot-integration-examples/springboot-oss/pom.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.4.RELEASE - - - cn.lastwhisper - springbootoss - 0.0.1-SNAPSHOT - springbootoss - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-test - test - - - - org.springframework.boot - spring-boot-devtools - true - - - - com.aliyun.oss - aliyun-sdk-oss - 2.8.3 - - - org.projectlombok - lombok - 1.18.4 - provided - - - joda-time - joda-time - 2.9.9 - - - - org.apache.commons - commons-lang3 - 3.8.1 - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - true - - - - - - diff --git a/springboot-integration-examples/springboot-oss/src/main/java/cn/lastwhisper/springbootoss/OssdemoApplication.java b/springboot-integration-examples/springboot-oss/src/main/java/cn/lastwhisper/springbootoss/OssdemoApplication.java deleted file mode 100644 index fb771ba2..00000000 --- a/springboot-integration-examples/springboot-oss/src/main/java/cn/lastwhisper/springbootoss/OssdemoApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.springbootoss; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class OssdemoApplication { - - public static void main(String[] args) { - SpringApplication.run(OssdemoApplication.class, args); - } - -} diff --git a/springboot-integration-examples/springboot-oss/src/main/java/cn/lastwhisper/springbootoss/config/AliyunConfig.java b/springboot-integration-examples/springboot-oss/src/main/java/cn/lastwhisper/springbootoss/config/AliyunConfig.java deleted file mode 100644 index 8e266c5e..00000000 --- a/springboot-integration-examples/springboot-oss/src/main/java/cn/lastwhisper/springbootoss/config/AliyunConfig.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.lastwhisper.springbootoss.config; - -import com.aliyun.oss.OSS; -import com.aliyun.oss.OSSClient; -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; -/** - * @desc - * - * @author lastwhisper - * @email gaojun56@163.com - */ -@Configuration -@PropertySource(value = {"classpath:application-oss.properties"}) -@ConfigurationProperties(prefix = "aliyun") -@Data -public class AliyunConfig { - private String endpoint; - private String accessKeyId; - private String accessKeySecret; - private String bucketName; - private String urlPrefix; - - @Bean - public OSS oSSClient() { - return new OSSClient(endpoint, accessKeyId, accessKeySecret); - } -} \ No newline at end of file diff --git a/springboot-integration-examples/springboot-oss/src/main/java/cn/lastwhisper/springbootoss/controller/FileUploadController.java b/springboot-integration-examples/springboot-oss/src/main/java/cn/lastwhisper/springbootoss/controller/FileUploadController.java deleted file mode 100644 index b8c2d821..00000000 --- a/springboot-integration-examples/springboot-oss/src/main/java/cn/lastwhisper/springbootoss/controller/FileUploadController.java +++ /dev/null @@ -1,82 +0,0 @@ -package cn.lastwhisper.springbootoss.controller; - -import cn.lastwhisper.springbootoss.service.FileUploadService; -import cn.lastwhisper.springbootoss.vo.FileUploadResult; -import com.aliyun.oss.model.OSSObjectSummary; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.multipart.MultipartFile; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; - -/** - * @author lastwhisper - * @desc - * @email gaojun56@163.com - */ -@Controller -public class FileUploadController { - @Autowired - private FileUploadService fileUploadService; - - /** - * @author lastwhisper - * @desc 文件上传到oss - * @return FileUploadResult - * @Param uploadFile - */ - @RequestMapping("file/upload") - @ResponseBody - public FileUploadResult upload(@RequestParam("file") MultipartFile uploadFile) - throws Exception { - return this.fileUploadService.upload(uploadFile); - } - - /** - * @return FileUploadResult - * @desc 根据文件名删除oss上的文件 - * http://localhost:8080/file/delete?fileName=images/2019/04/28/1556429167175766.jpg - * @author lastwhisper - * @Param objectName - */ - @RequestMapping("file/delete") - @ResponseBody - public FileUploadResult delete(@RequestParam("fileName") String objectName) - throws Exception { - return this.fileUploadService.delete(objectName); - } - - /** - * @author lastwhisper - * @desc 查询oss上的所有文件 - * http://localhost:8080/file/list - * @return List - * @Param - */ - @RequestMapping("file/list") - @ResponseBody - public List list() - throws Exception { - return this.fileUploadService.list(); - } - - /** - * @author lastwhisper - * @desc 根据文件名下载oss上的文件 - * @return - * @Param objectName - */ - @RequestMapping("file/download") - @ResponseBody - public void download(@RequestParam("fileName") String objectName, HttpServletResponse response) throws IOException { - //通知浏览器以附件形式下载 - response.setHeader("Content-Disposition", - "attachment;filename=" + new String(objectName.getBytes(), "ISO-8859-1")); - this.fileUploadService.exportOssFile(response.getOutputStream(),objectName); - } -} \ No newline at end of file diff --git a/springboot-integration-examples/springboot-oss/src/main/java/cn/lastwhisper/springbootoss/service/FileUploadService.java b/springboot-integration-examples/springboot-oss/src/main/java/cn/lastwhisper/springbootoss/service/FileUploadService.java deleted file mode 100644 index 245138a6..00000000 --- a/springboot-integration-examples/springboot-oss/src/main/java/cn/lastwhisper/springbootoss/service/FileUploadService.java +++ /dev/null @@ -1,145 +0,0 @@ -package cn.lastwhisper.springbootoss.service; - -import cn.lastwhisper.springbootoss.config.AliyunConfig; -import cn.lastwhisper.springbootoss.vo.FileUploadResult; -import com.aliyun.oss.OSS; -import com.aliyun.oss.model.*; -import org.apache.commons.lang3.RandomUtils; -import org.apache.commons.lang3.StringUtils; -import org.joda.time.DateTime; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; - -import java.io.*; -import java.util.List; - -/** - * @author lastwhisper - * @desc - * @email gaojun56@163.com - */ -@Service -public class FileUploadService { - // 允许上传的格式 - private static final String[] IMAGE_TYPE = new String[]{".bmp", ".jpg", - ".jpeg", ".gif", ".png"}; - @Autowired - private OSS ossClient; - @Autowired - private AliyunConfig aliyunConfig; - - /** - * @author lastwhisper - * @desc 文件上传 - * 文档链接 https://help.aliyun.com/document_detail/84781.html?spm=a2c4g.11186623.6.749.11987a7dRYVSzn - * @email gaojun56@163.com - */ - public FileUploadResult upload(MultipartFile uploadFile) { - // 校验图片格式 - boolean isLegal = false; - for (String type : IMAGE_TYPE) { - if (StringUtils.endsWithIgnoreCase(uploadFile.getOriginalFilename(), - type)) { - isLegal = true; - break; - } - } - //封装Result对象,并且将文件的byte数组放置到result对象中 - FileUploadResult fileUploadResult = new FileUploadResult(); - if (!isLegal) { - fileUploadResult.setStatus("error"); - return fileUploadResult; - } - //文件新路径 - String fileName = uploadFile.getOriginalFilename(); - String filePath = getFilePath(fileName); - // 上传到阿里云 - try { - ossClient.putObject(aliyunConfig.getBucketName(), filePath, new - ByteArrayInputStream(uploadFile.getBytes())); - } catch (Exception e) { - e.printStackTrace(); - //上传失败 - fileUploadResult.setStatus("error"); - return fileUploadResult; - } - fileUploadResult.setStatus("done"); - fileUploadResult.setResponse("success"); - //this.aliyunConfig.getUrlPrefix() + filePath 文件路径需要保存到数据库 - fileUploadResult.setName(this.aliyunConfig.getUrlPrefix() + filePath); - fileUploadResult.setUid(String.valueOf(System.currentTimeMillis())); - return fileUploadResult; - } - - /** - * @author lastwhisper - * @desc 生成路径以及文件名 例如://images/2019/04/28/15564277465972939.jpg - * @email gaojun56@163.com - */ - private String getFilePath(String sourceFileName) { - DateTime dateTime = new DateTime(); - return "images/" + dateTime.toString("yyyy") - + "/" + dateTime.toString("MM") + "/" - + dateTime.toString("dd") + "/" + System.currentTimeMillis() + - RandomUtils.nextInt(100, 9999) + "." + - StringUtils.substringAfterLast(sourceFileName, "."); - } - - /** - * @author lastwhisper - * @desc 查看文件列表 - * 文档链接 https://help.aliyun.com/document_detail/84841.html?spm=a2c4g.11186623.2.13.3ad5b5ddqxWWRu#concept-84841-zh - * @email gaojun56@163.com - */ - public List list() { - // 设置最大个数。 - final int maxKeys = 200; - // 列举文件。 - ObjectListing objectListing = ossClient.listObjects(new ListObjectsRequest(aliyunConfig.getBucketName()).withMaxKeys(maxKeys)); - List sums = objectListing.getObjectSummaries(); - return sums; - } - - /** - * @author lastwhisper - * @desc 删除文件 - * 文档链接 https://help.aliyun.com/document_detail/84842.html?spm=a2c4g.11186623.6.770.4f9474b4UYlCtr - * @email gaojun56@163.com - */ - public FileUploadResult delete(String objectName) { - // 根据BucketName,objectName删除文件 - ossClient.deleteObject(aliyunConfig.getBucketName(), objectName); - FileUploadResult fileUploadResult = new FileUploadResult(); - fileUploadResult.setName(objectName); - fileUploadResult.setStatus("removed"); - fileUploadResult.setResponse("success"); - return fileUploadResult; - } - - /** - * @author lastwhisper - * @desc 下载文件 - * 文档链接 https://help.aliyun.com/document_detail/84823.html?spm=a2c4g.11186623.2.7.37836e84ZIuZaC#concept-84823-zh - * @email gaojun56@163.com - */ - public void exportOssFile(OutputStream os, String objectName) throws IOException { - // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。 - OSSObject ossObject = ossClient.getObject(aliyunConfig.getBucketName(), objectName); - // 读取文件内容。 - BufferedInputStream in = new BufferedInputStream(ossObject.getObjectContent()); - BufferedOutputStream out = new BufferedOutputStream(os); - byte[] buffer = new byte[1024]; - int lenght = 0; - while ((lenght = in.read(buffer)) != -1) { - out.write(buffer, 0, lenght); - } - if (out != null) { - out.flush(); - out.close(); - } - if (in != null) { - in.close(); - } - } -} diff --git a/springboot-integration-examples/springboot-oss/src/main/java/cn/lastwhisper/springbootoss/vo/FileUploadResult.java b/springboot-integration-examples/springboot-oss/src/main/java/cn/lastwhisper/springbootoss/vo/FileUploadResult.java deleted file mode 100644 index f45e5a87..00000000 --- a/springboot-integration-examples/springboot-oss/src/main/java/cn/lastwhisper/springbootoss/vo/FileUploadResult.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.lastwhisper.springbootoss.vo; - -import lombok.Data; - -/** - * @author lastwhisper - * @desc 用于前后端交互的返回值 - * @email gaojun56@163.com - */ -@Data -public class FileUploadResult { - // 文件唯一标识 - private String uid; - // 文件名 - private String name; - // 状态有:uploading done error removed - private String status; - // 服务端响应内容,如:'{"status": "success"}' - private String response; -} diff --git a/springboot-integration-examples/springboot-oss/src/main/resources/application-oss.properties b/springboot-integration-examples/springboot-oss/src/main/resources/application-oss.properties deleted file mode 100644 index 41a8a813..00000000 --- a/springboot-integration-examples/springboot-oss/src/main/resources/application-oss.properties +++ /dev/null @@ -1,5 +0,0 @@ -aliyun.endpoint=oss-cn-shanghai.aliyuncs.com -aliyun.accessKeyId=accessKeyId -aliyun.accessKeySecret=accessKeySecret -aliyun.bucketName=gaojun-testbucket -aliyun.urlPrefix=http://gaojun-testbucket.oss-cn-shanghai.aliyuncs.com/ diff --git a/springboot-integration-examples/springboot-oss/src/main/resources/application.properties b/springboot-integration-examples/springboot-oss/src/main/resources/application.properties deleted file mode 100644 index b10d3b5d..00000000 --- a/springboot-integration-examples/springboot-oss/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -spring.servlet.multipart.max-file-size=100MB -spring.servlet.multipart.max-request-size=1000MB \ No newline at end of file diff --git a/springboot-integration-examples/springboot-oss/src/main/resources/static/manager.html b/springboot-integration-examples/springboot-oss/src/main/resources/static/manager.html deleted file mode 100644 index d5c6d9f9..00000000 --- a/springboot-integration-examples/springboot-oss/src/main/resources/static/manager.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - oss文件管理 - - - - -单击下载oss上的图片、双击删除oss上的图片
-
- -
- - \ No newline at end of file diff --git a/springboot-integration-examples/springboot-oss/src/main/resources/static/upload.html b/springboot-integration-examples/springboot-oss/src/main/resources/static/upload.html deleted file mode 100644 index a858aa49..00000000 --- a/springboot-integration-examples/springboot-oss/src/main/resources/static/upload.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - oss文件上传 - - - - -
   -    -
     -
-
-
- - \ No newline at end of file diff --git a/springboot-integration-examples/springboot-oss/src/test/java/cn/lastwhisper/springbootoss/OssdemoApplicationTests.java b/springboot-integration-examples/springboot-oss/src/test/java/cn/lastwhisper/springbootoss/OssdemoApplicationTests.java deleted file mode 100644 index 79ec8346..00000000 --- a/springboot-integration-examples/springboot-oss/src/test/java/cn/lastwhisper/springbootoss/OssdemoApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.springbootoss; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class OssdemoApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-simple-websocket/README.md b/springboot-integration-examples/springboot-simple-websocket/README.md deleted file mode 100644 index f6c3c00c..00000000 --- a/springboot-integration-examples/springboot-simple-websocket/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# 原生websocket - -重点看:index.html和MyWebSocket.java - -单播和多播 diff --git a/springboot-integration-examples/springboot-simple-websocket/pom.xml b/springboot-integration-examples/springboot-simple-websocket/pom.xml deleted file mode 100644 index 1529ccb5..00000000 --- a/springboot-integration-examples/springboot-simple-websocket/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.2.4.RELEASE - - - cn.lastwhisper - springboot-simple-websocket - 0.0.1-SNAPSHOT - springboot-simple-websocket - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter-websocket - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.junit.vintage - junit-vintage-engine - - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-simple-websocket/src/main/java/cn/lastwhisper/websocket/SpringbootSimpleWebsocketApplication.java b/springboot-integration-examples/springboot-simple-websocket/src/main/java/cn/lastwhisper/websocket/SpringbootSimpleWebsocketApplication.java deleted file mode 100644 index e2bc8692..00000000 --- a/springboot-integration-examples/springboot-simple-websocket/src/main/java/cn/lastwhisper/websocket/SpringbootSimpleWebsocketApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.websocket; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SpringbootSimpleWebsocketApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringbootSimpleWebsocketApplication.class, args); - } - -} diff --git a/springboot-integration-examples/springboot-simple-websocket/src/main/java/cn/lastwhisper/websocket/config/WebSocketConfig.java b/springboot-integration-examples/springboot-simple-websocket/src/main/java/cn/lastwhisper/websocket/config/WebSocketConfig.java deleted file mode 100644 index faeec882..00000000 --- a/springboot-integration-examples/springboot-simple-websocket/src/main/java/cn/lastwhisper/websocket/config/WebSocketConfig.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.websocket.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.socket.server.standard.ServerEndpointExporter; - -@Configuration -public class WebSocketConfig { - @Bean - public ServerEndpointExporter serverEndpointExporter() { - return new ServerEndpointExporter(); - } -} \ No newline at end of file diff --git a/springboot-integration-examples/springboot-simple-websocket/src/main/java/cn/lastwhisper/websocket/controller/HomeController.java b/springboot-integration-examples/springboot-simple-websocket/src/main/java/cn/lastwhisper/websocket/controller/HomeController.java deleted file mode 100644 index 14ca02a3..00000000 --- a/springboot-integration-examples/springboot-simple-websocket/src/main/java/cn/lastwhisper/websocket/controller/HomeController.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.lastwhisper.websocket.controller; - -import cn.lastwhisper.websocket.handler.MyWebSocket; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class HomeController { - - @GetMapping("/broadcast") - public void broadcast() { - MyWebSocket.broadcast(); - } -} \ No newline at end of file diff --git a/springboot-integration-examples/springboot-simple-websocket/src/main/java/cn/lastwhisper/websocket/handler/MyWebSocket.java b/springboot-integration-examples/springboot-simple-websocket/src/main/java/cn/lastwhisper/websocket/handler/MyWebSocket.java deleted file mode 100644 index 5e2b0a72..00000000 --- a/springboot-integration-examples/springboot-simple-websocket/src/main/java/cn/lastwhisper/websocket/handler/MyWebSocket.java +++ /dev/null @@ -1,93 +0,0 @@ -package cn.lastwhisper.websocket.handler; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.websocket.*; -import javax.websocket.server.ServerEndpoint; -import java.io.IOException; -import java.util.LinkedHashMap; -import java.util.Map; - -@ServerEndpoint(value = "/ws") //接受websocket请求路径 -@Component //注册到spring容器中 -public class MyWebSocket { - - - //保存所有在线socket连接 - private static Map webSocketMap = new LinkedHashMap<>(); - - //记录当前在线数目 - private static int count = 0; - - //当前连接(每个websocket连入都会创建一个MyWebSocket实例 - private Session session; - - private Logger log = LoggerFactory.getLogger(this.getClass()); - - //处理连接建立 - @OnOpen - public void onOpen(Session session) { - this.session = session; - webSocketMap.put(session.getId(), this); - addCount(); - log.info("新的连接加入:{}", session.getId()); - } - - //接受消息 - @OnMessage - public void onMessage(String message, Session session) { - log.info("收到客户端{}消息:{}", session.getId(), message); - try { - this.sendMessage("收到消息:" + message); - } catch (Exception e) { - e.printStackTrace(); - } - } - - //处理错误 - @OnError - public void onError(Throwable error, Session session) { - log.info("发生错误{},{}", session.getId(), error.getMessage()); - } - - //处理连接关闭 - @OnClose - public void onClose() { - webSocketMap.remove(this.session.getId()); - reduceCount(); - log.info("连接关闭:{}", this.session.getId()); - } - - //群发消息 - - //发送消息 - public void sendMessage(String message) throws IOException { - this.session.getBasicRemote().sendText(message); - } - - //广播消息 - public static void broadcast() { - MyWebSocket.webSocketMap.forEach((k, v) -> { - try { - v.sendMessage("这是一条测试广播"); - } catch (Exception e) { - } - }); - } - - //获取在线连接数目 - public static int getCount() { - return count; - } - - //操作count,使用synchronized确保线程安全 - public static synchronized void addCount() { - MyWebSocket.count++; - } - - public static synchronized void reduceCount() { - MyWebSocket.count--; - } -} \ No newline at end of file diff --git a/springboot-integration-examples/springboot-simple-websocket/src/main/resources/application.properties b/springboot-integration-examples/springboot-simple-websocket/src/main/resources/application.properties deleted file mode 100644 index 5ff02851..00000000 --- a/springboot-integration-examples/springboot-simple-websocket/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -server.port=9090 \ No newline at end of file diff --git a/springboot-integration-examples/springboot-simple-websocket/src/main/resources/static/index.html b/springboot-integration-examples/springboot-simple-websocket/src/main/resources/static/index.html deleted file mode 100644 index d96d04d6..00000000 --- a/springboot-integration-examples/springboot-simple-websocket/src/main/resources/static/index.html +++ /dev/null @@ -1,30 +0,0 @@ - - - websocket测试 - - - - - - - - \ No newline at end of file diff --git a/springboot-integration-examples/springboot-simple-websocket/src/test/java/cn/lastwhisper/websocket/SpringbootSimpleWebsocketApplicationTests.java b/springboot-integration-examples/springboot-simple-websocket/src/test/java/cn/lastwhisper/websocket/SpringbootSimpleWebsocketApplicationTests.java deleted file mode 100644 index 14c56ac3..00000000 --- a/springboot-integration-examples/springboot-simple-websocket/src/test/java/cn/lastwhisper/websocket/SpringbootSimpleWebsocketApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.websocket; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class SpringbootSimpleWebsocketApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-websocket-stomp-chat-cluster b/springboot-integration-examples/springboot-websocket-stomp-chat-cluster deleted file mode 160000 index e3d00852..00000000 --- a/springboot-integration-examples/springboot-websocket-stomp-chat-cluster +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e3d00852bba9b287e2f6bb6f20dc850d842a7bec diff --git a/springboot-integration-examples/springboot-websocket-stomp-chat-single b/springboot-integration-examples/springboot-websocket-stomp-chat-single deleted file mode 160000 index 89c86405..00000000 --- a/springboot-integration-examples/springboot-websocket-stomp-chat-single +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 89c8640570eb9b4c87957d084b6b7f0f08450e30 diff --git a/springboot-integration-examples/springboot-websocket-stomp/pom.xml b/springboot-integration-examples/springboot-websocket-stomp/pom.xml deleted file mode 100644 index 019d70cc..00000000 --- a/springboot-integration-examples/springboot-websocket-stomp/pom.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.2.2.RELEASE - - - com.example - springboot-websocket-stomp - 0.0.1-SNAPSHOT - springboot-websocket-stomp - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter-websocket - - - org.webjars - webjars-locator-core - - - org.webjars - sockjs-client - 1.0.2 - - - org.webjars - stomp-websocket - 2.3.3 - - - org.webjars - bootstrap - 3.3.7 - - - org.webjars - jquery - 3.1.1-1 - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.junit.vintage - junit-vintage-engine - - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-websocket-stomp/src/main/java/com/example/messagingstompwebsocket/Greeting.java b/springboot-integration-examples/springboot-websocket-stomp/src/main/java/com/example/messagingstompwebsocket/Greeting.java deleted file mode 100644 index bbee9963..00000000 --- a/springboot-integration-examples/springboot-websocket-stomp/src/main/java/com/example/messagingstompwebsocket/Greeting.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.example.messagingstompwebsocket; - -public class Greeting { - - private String content; - - public Greeting() { - } - - public Greeting(String content) { - this.content = content; - } - - public String getContent() { - return content; - } - -} diff --git a/springboot-integration-examples/springboot-websocket-stomp/src/main/java/com/example/messagingstompwebsocket/GreetingController.java b/springboot-integration-examples/springboot-websocket-stomp/src/main/java/com/example/messagingstompwebsocket/GreetingController.java deleted file mode 100644 index 963c6697..00000000 --- a/springboot-integration-examples/springboot-websocket-stomp/src/main/java/com/example/messagingstompwebsocket/GreetingController.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.example.messagingstompwebsocket; - -import org.springframework.messaging.handler.annotation.MessageMapping; -import org.springframework.messaging.handler.annotation.SendTo; -import org.springframework.stereotype.Controller; -import org.springframework.web.util.HtmlUtils; - -@Controller -public class GreetingController { - - @MessageMapping("/hello")//@MessageMapping保证如果一个消息被发送到"/hello",greeting()方法被调用 - @SendTo("/topic/greetings")//@SendTo将返回值广播给所有"/topic/greetings" - public Greeting greeting(HelloMessage message) throws Exception { - //Thread.sleep(1000); // simulated delay - return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!"); - } - -} diff --git a/springboot-integration-examples/springboot-websocket-stomp/src/main/java/com/example/messagingstompwebsocket/HelloMessage.java b/springboot-integration-examples/springboot-websocket-stomp/src/main/java/com/example/messagingstompwebsocket/HelloMessage.java deleted file mode 100644 index 8eed11be..00000000 --- a/springboot-integration-examples/springboot-websocket-stomp/src/main/java/com/example/messagingstompwebsocket/HelloMessage.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.example.messagingstompwebsocket; - -public class HelloMessage { - - private String name; - - public HelloMessage() { - } - - public HelloMessage(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} diff --git a/springboot-integration-examples/springboot-websocket-stomp/src/main/java/com/example/messagingstompwebsocket/MessagingStompWebsocketApplication.java b/springboot-integration-examples/springboot-websocket-stomp/src/main/java/com/example/messagingstompwebsocket/MessagingStompWebsocketApplication.java deleted file mode 100644 index acb15005..00000000 --- a/springboot-integration-examples/springboot-websocket-stomp/src/main/java/com/example/messagingstompwebsocket/MessagingStompWebsocketApplication.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.example.messagingstompwebsocket; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class MessagingStompWebsocketApplication { - - public static void main(String[] args) { - SpringApplication.run(MessagingStompWebsocketApplication.class, args); - } -} diff --git a/springboot-integration-examples/springboot-websocket-stomp/src/main/java/com/example/messagingstompwebsocket/WebSocketConfig.java b/springboot-integration-examples/springboot-websocket-stomp/src/main/java/com/example/messagingstompwebsocket/WebSocketConfig.java deleted file mode 100644 index 8179ba17..00000000 --- a/springboot-integration-examples/springboot-websocket-stomp/src/main/java/com/example/messagingstompwebsocket/WebSocketConfig.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.example.messagingstompwebsocket; - -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.simp.config.MessageBrokerRegistry; -import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; -import org.springframework.web.socket.config.annotation.StompEndpointRegistry; -import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; - -@Configuration -@EnableWebSocketMessageBroker -public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { - - @Override - public void configureMessageBroker(MessageBrokerRegistry config) { - // 使一个简单的基于内存的message broker的问候消息回客户机在目的地前缀/topic - config.enableSimpleBroker("/topic"); - // /app前缀为消息绑定方法注释@MessageMapping. 这个前缀将用于定义所有消息映射 - // 例如,/app/hello端点的吗GreetingController.greeting()映射到处理方法 - config.setApplicationDestinationPrefixes("/app"); - } - - @Override - public void registerStompEndpoints(StompEndpointRegistry registry) { - // 注册/gs-guide-websocket端点,使SockJS后备选项,这样交替传输可以使用如果WebSocket不可用。 - // SockJS客户端将尝试连接/gs-guide-websocket - registry.addEndpoint("/gs-guide-websocket").withSockJS(); - } - -} diff --git a/springboot-integration-examples/springboot-websocket-stomp/src/main/resources/application.properties b/springboot-integration-examples/springboot-websocket-stomp/src/main/resources/application.properties deleted file mode 100644 index 51ad5ebf..00000000 --- a/springboot-integration-examples/springboot-websocket-stomp/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -server.port=9090 diff --git a/springboot-integration-examples/springboot-websocket-stomp/src/main/resources/static/app.js b/springboot-integration-examples/springboot-websocket-stomp/src/main/resources/static/app.js deleted file mode 100644 index 4d3ed96a..00000000 --- a/springboot-integration-examples/springboot-websocket-stomp/src/main/resources/static/app.js +++ /dev/null @@ -1,51 +0,0 @@ -var stompClient = null; - -function setConnected(connected) { - $("#connect").prop("disabled", connected); - $("#disconnect").prop("disabled", !connected); - if (connected) { - $("#conversation").show(); - } - else { - $("#conversation").hide(); - } - $("#greetings").html(""); -} - -function connect() { - var socket = new SockJS('/gs-guide-websocket'); - stompClient = Stomp.over(socket); - stompClient.connect({}, function (frame) { - setConnected(true); - console.log('Connected: ' + frame); - stompClient.subscribe('/topic/greetings', function (greeting) { - showGreeting(JSON.parse(greeting.body).content); - }); - }); -} - -function disconnect() { - if (stompClient !== null) { - stompClient.disconnect(); - } - setConnected(false); - console.log("Disconnected"); -} - -function sendName() { - stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()})); -} - -function showGreeting(message) { - $("#greetings").append("" + message + ""); -} - -$(function () { - $("form").on('submit', function (e) { - e.preventDefault(); - }); - $( "#connect" ).click(function() { connect(); }); - $( "#disconnect" ).click(function() { disconnect(); }); - $( "#send" ).click(function() { sendName(); }); -}); - diff --git a/springboot-integration-examples/springboot-websocket-stomp/src/main/resources/static/index.html b/springboot-integration-examples/springboot-websocket-stomp/src/main/resources/static/index.html deleted file mode 100644 index 61a4a249..00000000 --- a/springboot-integration-examples/springboot-websocket-stomp/src/main/resources/static/index.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - Hello WebSocket - - - - - - - - - -
-
-
-
-
- - - -
-
-
-
-
-
- - -
- -
-
-
-
-
- - - - - - - - -
Greetings
-
-
-
- - diff --git a/springboot-integration-examples/springboot-websocket-stomp/src/main/resources/static/main.css b/springboot-integration-examples/springboot-websocket-stomp/src/main/resources/static/main.css deleted file mode 100644 index 8643b769..00000000 --- a/springboot-integration-examples/springboot-websocket-stomp/src/main/resources/static/main.css +++ /dev/null @@ -1,14 +0,0 @@ -body { - background-color: #f5f5f5; -} - -#main-content { - max-width: 940px; - padding: 2em 3em; - margin: 0 auto 20px; - background-color: #fff; - border: 1px solid #e5e5e5; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} \ No newline at end of file diff --git a/springboot-integration-examples/springboot-websocket-stomp/src/test/java/com/example/messagingstompwebsocket/GreetingIntegrationTests.java b/springboot-integration-examples/springboot-websocket-stomp/src/test/java/com/example/messagingstompwebsocket/GreetingIntegrationTests.java deleted file mode 100644 index d7e24a27..00000000 --- a/springboot-integration-examples/springboot-websocket-stomp/src/test/java/com/example/messagingstompwebsocket/GreetingIntegrationTests.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.example.messagingstompwebsocket; - -import static org.junit.jupiter.api.Assertions.*; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.messaging.converter.MappingJackson2MessageConverter; -import org.springframework.messaging.simp.stomp.StompCommand; -import org.springframework.messaging.simp.stomp.StompFrameHandler; -import org.springframework.messaging.simp.stomp.StompHeaders; -import org.springframework.messaging.simp.stomp.StompSession; -import org.springframework.messaging.simp.stomp.StompSessionHandler; -import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter; -import org.springframework.web.socket.WebSocketHttpHeaders; -import org.springframework.web.socket.client.standard.StandardWebSocketClient; -import org.springframework.web.socket.messaging.WebSocketStompClient; -import org.springframework.web.socket.sockjs.client.SockJsClient; -import org.springframework.web.socket.sockjs.client.Transport; -import org.springframework.web.socket.sockjs.client.WebSocketTransport; - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class GreetingIntegrationTests { - - @LocalServerPort - private int port; - - private SockJsClient sockJsClient; - - private WebSocketStompClient stompClient; - - private final WebSocketHttpHeaders headers = new WebSocketHttpHeaders(); - - @BeforeEach - public void setup() { - List transports = new ArrayList<>(); - transports.add(new WebSocketTransport(new StandardWebSocketClient())); - this.sockJsClient = new SockJsClient(transports); - - this.stompClient = new WebSocketStompClient(sockJsClient); - this.stompClient.setMessageConverter(new MappingJackson2MessageConverter()); - } - - @Test - public void getGreeting() throws Exception { - - final CountDownLatch latch = new CountDownLatch(1); - final AtomicReference failure = new AtomicReference<>(); - - StompSessionHandler handler = new TestSessionHandler(failure) { - - @Override - public void afterConnected(final StompSession session, StompHeaders connectedHeaders) { - session.subscribe("/topic/greetings", new StompFrameHandler() { - @Override - public Type getPayloadType(StompHeaders headers) { - return Greeting.class; - } - - @Override - public void handleFrame(StompHeaders headers, Object payload) { - Greeting greeting = (Greeting) payload; - try { - assertEquals("Hello, Spring!", greeting.getContent()); - } catch (Throwable t) { - failure.set(t); - } finally { - session.disconnect(); - latch.countDown(); - } - } - }); - try { - session.send("/app/hello", new HelloMessage("Spring")); - } catch (Throwable t) { - failure.set(t); - latch.countDown(); - } - } - }; - - this.stompClient.connect("ws://localhost:{port}/gs-guide-websocket", this.headers, handler, this.port); - - if (latch.await(3, TimeUnit.SECONDS)) { - if (failure.get() != null) { - throw new AssertionError("", failure.get()); - } - } - else { - fail("Greeting not received"); - } - - } - - private class TestSessionHandler extends StompSessionHandlerAdapter { - - private final AtomicReference failure; - - public TestSessionHandler(AtomicReference failure) { - this.failure = failure; - } - - @Override - public void handleFrame(StompHeaders headers, Object payload) { - this.failure.set(new Exception(headers.toString())); - } - - @Override - public void handleException(StompSession s, StompCommand c, StompHeaders h, byte[] p, Throwable ex) { - this.failure.set(ex); - } - - @Override - public void handleTransportError(StompSession session, Throwable ex) { - this.failure.set(ex); - } - } -} diff --git a/springboot-integration-examples/springboot-websocket/.gitignore b/springboot-integration-examples/springboot-websocket/.gitignore deleted file mode 100644 index 153c9335..00000000 --- a/springboot-integration-examples/springboot-websocket/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -HELP.md -/target/ -!.mvn/wrapper/maven-wrapper.jar - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -/build/ - -### VS Code ### -.vscode/ diff --git a/springboot-integration-examples/springboot-websocket/.mvn/wrapper/MavenWrapperDownloader.java b/springboot-integration-examples/springboot-websocket/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index 7f91a56e..00000000 --- a/springboot-integration-examples/springboot-websocket/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF 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 - - https://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. -*/ - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.Properties; - -public class MavenWrapperDownloader { - - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = - "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if (mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if (mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: : " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if (!outputFile.getParentFile().exists()) { - if (!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/springboot-integration-examples/springboot-websocket/.mvn/wrapper/maven-wrapper.jar b/springboot-integration-examples/springboot-websocket/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 01e67997..00000000 Binary files a/springboot-integration-examples/springboot-websocket/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/springboot-integration-examples/springboot-websocket/.mvn/wrapper/maven-wrapper.properties b/springboot-integration-examples/springboot-websocket/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index cd0d451c..00000000 --- a/springboot-integration-examples/springboot-websocket/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip diff --git a/springboot-integration-examples/springboot-websocket/mvnw b/springboot-integration-examples/springboot-websocket/mvnw deleted file mode 100644 index 8b9da3b8..00000000 --- a/springboot-integration-examples/springboot-websocket/mvnw +++ /dev/null @@ -1,286 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF 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 -# -# https://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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - wget "$jarUrl" -O "$wrapperJarPath" - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - curl -o "$wrapperJarPath" "$jarUrl" - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/springboot-integration-examples/springboot-websocket/mvnw.cmd b/springboot-integration-examples/springboot-websocket/mvnw.cmd deleted file mode 100644 index fef5a8f7..00000000 --- a/springboot-integration-examples/springboot-websocket/mvnw.cmd +++ /dev/null @@ -1,161 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" -FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - echo Found %WRAPPER_JAR% -) else ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" - echo Finished downloading %WRAPPER_JAR% -) -@REM End of extension - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/springboot-integration-examples/springboot-websocket/pom.xml b/springboot-integration-examples/springboot-websocket/pom.xml deleted file mode 100644 index 44ccb431..00000000 --- a/springboot-integration-examples/springboot-websocket/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.5.RELEASE - - - cn.lastwhisper - springboot-websocket - 0.0.1-SNAPSHOT - springboot-websocket - Demo project for websocket - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter-websocket - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.2 - - 1.8 - 1.8 - UTF-8 - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-websocket/src/main/java/cn/lastwhisper/springbootwebsocket/SpringbootWebsocketApplication.java b/springboot-integration-examples/springboot-websocket/src/main/java/cn/lastwhisper/springbootwebsocket/SpringbootWebsocketApplication.java deleted file mode 100644 index cf2b337f..00000000 --- a/springboot-integration-examples/springboot-websocket/src/main/java/cn/lastwhisper/springbootwebsocket/SpringbootWebsocketApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.springbootwebsocket; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SpringbootWebsocketApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringbootWebsocketApplication.class, args); - } - -} diff --git a/springboot-integration-examples/springboot-websocket/src/main/java/cn/lastwhisper/springbootwebsocket/config/WebSocketConfig.java b/springboot-integration-examples/springboot-websocket/src/main/java/cn/lastwhisper/springbootwebsocket/config/WebSocketConfig.java deleted file mode 100644 index f99d6373..00000000 --- a/springboot-integration-examples/springboot-websocket/src/main/java/cn/lastwhisper/springbootwebsocket/config/WebSocketConfig.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.lastwhisper.springbootwebsocket.config; - -import cn.lastwhisper.springbootwebsocket.handler.MyHandler; -import cn.lastwhisper.springbootwebsocket.interceptor.MyHandshakeInterceptor; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.socket.WebSocketHandler; -import org.springframework.web.socket.config.annotation.EnableWebSocket; -import org.springframework.web.socket.config.annotation.WebSocketConfigurer; -import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; - -/** - * @author lastwhisper - * @desc - */ -@Configuration -@EnableWebSocket -public class WebSocketConfig implements WebSocketConfigurer { - - @Autowired - private MyHandshakeInterceptor myHandshakeInterceptor; - - /** - * ws://localhost:9501/ws - * http://www.websocket-test.com/ - * http://coolaf.com/tool/chattest - */ - @Override - public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) { - webSocketHandlerRegistry.addHandler(myHandler(), "/ws") - .setAllowedOrigins("*") - .addInterceptors(myHandshakeInterceptor); - } - - @Bean - public WebSocketHandler myHandler() { - return new MyHandler(); - } -} diff --git a/springboot-integration-examples/springboot-websocket/src/main/java/cn/lastwhisper/springbootwebsocket/handler/MyHandler.java b/springboot-integration-examples/springboot-websocket/src/main/java/cn/lastwhisper/springbootwebsocket/handler/MyHandler.java deleted file mode 100644 index 07160d9d..00000000 --- a/springboot-integration-examples/springboot-websocket/src/main/java/cn/lastwhisper/springbootwebsocket/handler/MyHandler.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.lastwhisper.springbootwebsocket.handler; - -import org.springframework.web.socket.CloseStatus; -import org.springframework.web.socket.TextMessage; -import org.springframework.web.socket.WebSocketSession; -import org.springframework.web.socket.handler.TextWebSocketHandler; - -/** - * @author lastwhisper - * @desc - */ -public class MyHandler extends TextWebSocketHandler { - /** - * 测试服务器向客户端推送消息 - */ - @Override - protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { - Integer uid = (Integer) session.getAttributes().get("uid"); - System.out.println("uid=" + uid + " 获取到消息 >> " + message.getPayload()); - - session.sendMessage(new TextMessage("消息已收到")); - if ("10".equals(message.getPayload())) { - for (int i = 0; i < 10; i++) { - session.sendMessage(new TextMessage("消息 -> " + i)); - Thread.sleep(100); - } - } - } - - @Override - public void afterConnectionEstablished(WebSocketSession session) throws Exception { - Integer uid = (Integer) session.getAttributes().get("uid"); - session.sendMessage(new TextMessage(uid + ", 你好!欢迎连接到ws服务")); - } - - @Override - public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { - System.out.println("断开连接!"); - } -} diff --git a/springboot-integration-examples/springboot-websocket/src/main/java/cn/lastwhisper/springbootwebsocket/interceptor/MyHandshakeInterceptor.java b/springboot-integration-examples/springboot-websocket/src/main/java/cn/lastwhisper/springbootwebsocket/interceptor/MyHandshakeInterceptor.java deleted file mode 100644 index 527c8b1d..00000000 --- a/springboot-integration-examples/springboot-websocket/src/main/java/cn/lastwhisper/springbootwebsocket/interceptor/MyHandshakeInterceptor.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.lastwhisper.springbootwebsocket.interceptor; - -import org.springframework.http.server.ServerHttpRequest; -import org.springframework.http.server.ServerHttpResponse; -import org.springframework.stereotype.Component; -import org.springframework.web.socket.WebSocketHandler; -import org.springframework.web.socket.server.HandshakeInterceptor; - -import java.util.Map; - -/** - * @author lastwhisper - * @desc - */ -@Component -public class MyHandshakeInterceptor implements HandshakeInterceptor { - /** - * @author lastwhisper - * @desc 握手之前,若返回false,则不建立链接 - * @return boolean - */ - @Override - public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse - response, WebSocketHandler wsHandler, Map attributes) throws - Exception { - //将用户id放入socket处理器的会话(WebSocketSession)中 - attributes.put("uid", 1001); - System.out.println("握手准备。。。。。。。"); - return true; - } - - @Override - public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) { - System.out.println("握手成功。。。。。。"); - } -} diff --git a/springboot-integration-examples/springboot-websocket/src/main/resources/application.properties b/springboot-integration-examples/springboot-websocket/src/main/resources/application.properties deleted file mode 100644 index 8d95ab2a..00000000 --- a/springboot-integration-examples/springboot-websocket/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -server.port=9501 diff --git a/springboot-integration-examples/springboot-websocket/src/test/java/cn/lastwhisper/springbootwebsocket/SpringbootWebsocketApplicationTests.java b/springboot-integration-examples/springboot-websocket/src/test/java/cn/lastwhisper/springbootwebsocket/SpringbootWebsocketApplicationTests.java deleted file mode 100644 index 02613926..00000000 --- a/springboot-integration-examples/springboot-websocket/src/test/java/cn/lastwhisper/springbootwebsocket/SpringbootWebsocketApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.springbootwebsocket; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class SpringbootWebsocketApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/springboot-integration-examples/springboot-wx/.gitignore b/springboot-integration-examples/springboot-wx/.gitignore deleted file mode 100644 index 153c9335..00000000 --- a/springboot-integration-examples/springboot-wx/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -HELP.md -/target/ -!.mvn/wrapper/maven-wrapper.jar - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -/build/ - -### VS Code ### -.vscode/ diff --git a/springboot-integration-examples/springboot-wx/.mvn/wrapper/MavenWrapperDownloader.java b/springboot-integration-examples/springboot-wx/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index 7f91a56e..00000000 --- a/springboot-integration-examples/springboot-wx/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF 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 - - https://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. -*/ - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.Properties; - -public class MavenWrapperDownloader { - - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = - "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if (mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if (mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: : " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if (!outputFile.getParentFile().exists()) { - if (!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/springboot-integration-examples/springboot-wx/.mvn/wrapper/maven-wrapper.jar b/springboot-integration-examples/springboot-wx/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 01e67997..00000000 Binary files a/springboot-integration-examples/springboot-wx/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/springboot-integration-examples/springboot-wx/.mvn/wrapper/maven-wrapper.properties b/springboot-integration-examples/springboot-wx/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index cd0d451c..00000000 --- a/springboot-integration-examples/springboot-wx/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip diff --git a/springboot-integration-examples/springboot-wx/mvnw b/springboot-integration-examples/springboot-wx/mvnw deleted file mode 100644 index 8b9da3b8..00000000 --- a/springboot-integration-examples/springboot-wx/mvnw +++ /dev/null @@ -1,286 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF 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 -# -# https://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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - wget "$jarUrl" -O "$wrapperJarPath" - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - curl -o "$wrapperJarPath" "$jarUrl" - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/springboot-integration-examples/springboot-wx/mvnw.cmd b/springboot-integration-examples/springboot-wx/mvnw.cmd deleted file mode 100644 index fef5a8f7..00000000 --- a/springboot-integration-examples/springboot-wx/mvnw.cmd +++ /dev/null @@ -1,161 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" -FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - echo Found %WRAPPER_JAR% -) else ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" - echo Finished downloading %WRAPPER_JAR% -) -@REM End of extension - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/springboot-integration-examples/springboot-wx/pom.xml b/springboot-integration-examples/springboot-wx/pom.xml deleted file mode 100644 index 192581f5..00000000 --- a/springboot-integration-examples/springboot-wx/pom.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.4.RELEASE - - - cn.lastwhisper - springbootwx - 0.0.1-SNAPSHOT - springbootwx - Demo project for Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - org.apache.httpcomponents - httpclient - 4.5.2 - - - - org.bouncycastle - bcprov-jdk16 - 1.46 - - - - - - org.apache.shiro - shiro-core - 1.4.0 - - - slf4j-api - org.slf4j - - - - - - - com.alibaba - fastjson - 1.2.47 - - - - - org.projectlombok - lombok - true - - - - com.baomidou - mybatis-plus-boot-starter - 3.1.1 - - - - mysql - mysql-connector-java - 5.1.47 - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/springboot-integration-examples/springboot-wx/sql/wxlogin.sql b/springboot-integration-examples/springboot-wx/sql/wxlogin.sql deleted file mode 100644 index 92d1e6f6..00000000 --- a/springboot-integration-examples/springboot-wx/sql/wxlogin.sql +++ /dev/null @@ -1,39 +0,0 @@ -/* - Navicat Premium Data Transfer - - Source Server : 本地数据库-mysql5.7 - Source Server Type : MySQL - Source Server Version : 50724 - Source Host : localhost:3306 - Source Schema : wxlogin - - Target Server Type : MySQL - Target Server Version : 50724 - File Encoding : 65001 - - Date: 02/05/2019 11:33:43 -*/ - -SET NAMES utf8mb4; -SET FOREIGN_KEY_CHECKS = 0; - --- ---------------------------- --- Table structure for user --- ---------------------------- -DROP TABLE IF EXISTS `user`; -CREATE TABLE `user` ( - `open_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'open_id', - `skey` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'skey', - `create_time` timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `last_visit_time` timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后登录时间', - `session_key` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'session_key', - `city` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '市', - `province` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '省', - `country` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '国', - `avatar_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '头像', - `gender` tinyint(11) NULL DEFAULT NULL COMMENT '性别', - `nick_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '网名', - PRIMARY KEY (`open_id`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '微信用户信息' ROW_FORMAT = Dynamic; - -SET FOREIGN_KEY_CHECKS = 1; diff --git a/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/SpringbootwxApplication.java b/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/SpringbootwxApplication.java deleted file mode 100644 index 1f3b6a1f..00000000 --- a/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/SpringbootwxApplication.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.lastwhisper.springbootwx; - -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -@MapperScan("cn.lastwhisper.springbootwx.mapper") //设置mapper接口的扫描包 -@SpringBootApplication -public class SpringbootwxApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringbootwxApplication.class, args); - } - -} diff --git a/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/common/GlobalResult.java b/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/common/GlobalResult.java deleted file mode 100644 index f7d42ab2..00000000 --- a/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/common/GlobalResult.java +++ /dev/null @@ -1,107 +0,0 @@ -package cn.lastwhisper.springbootwx.common; - -/** - * @Description: 自定义响应数据结构 - * 这个类是提供给门户,ios,安卓,微信商城用的 - * 门户接受此类数据后需要使用本类的方法转换成对于的数据类型格式(类,或者list) - * 其他自行处理 - * 200:表示成功 - * 500:表示错误,错误信息在msg字段中 - * 501:bean验证错误,不管多少个错误都以map形式返回 - * 502:拦截器拦截到用户token出错 - * 555:异常抛出信息 - */ -public class GlobalResult { - - // 响应业务状态 - private Integer status; - - // 响应消息 - private String msg; - - // 响应中的数据 - private Object data; - - private String ok; // 不使用 - - public static GlobalResult build(Integer status, String msg, Object data) { - return new GlobalResult(status, msg, data); - } - - public static GlobalResult ok(Object data) { - return new GlobalResult(data); - } - - public static GlobalResult ok() { - return new GlobalResult(null); - } - - public static GlobalResult errorMsg(String msg) { - return new GlobalResult(500, msg, null); - } - - public static GlobalResult errorMap(Object data) { - return new GlobalResult(501, "error", data); - } - - public static GlobalResult errorTokenMsg(String msg) { - return new GlobalResult(502, msg, null); - } - - public static GlobalResult errorException(String msg) { - return new GlobalResult(555, msg, null); - } - - public GlobalResult() { - - } - - public GlobalResult(Integer status, String msg, Object data) { - this.status = status; - this.msg = msg; - this.data = data; - } - - public GlobalResult(Object data) { - this.status = 200; - this.msg = "OK"; - this.data = data; - } - - public Boolean isOK() { - return this.status == 200; - } - - public Integer getStatus() { - return status; - } - - public void setStatus(Integer status) { - this.status = status; - } - - public String getMsg() { - return msg; - } - - public void setMsg(String msg) { - this.msg = msg; - } - - public Object getData() { - return data; - } - - public void setData(Object data) { - this.data = data; - } - - public String getOk() { - return ok; - } - - public void setOk(String ok) { - this.ok = ok; - } - -} diff --git a/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/common/HttpClientUtil.java b/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/common/HttpClientUtil.java deleted file mode 100644 index 15631c49..00000000 --- a/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/common/HttpClientUtil.java +++ /dev/null @@ -1,133 +0,0 @@ -package cn.lastwhisper.springbootwx.common; - -import org.apache.http.NameValuePair; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.util.EntityUtils; - -import java.io.IOException; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class HttpClientUtil { - - public static String doGet(String url, Map param) { - - // 创建Httpclient对象 - CloseableHttpClient httpclient = HttpClients.createDefault(); - - String resultString = ""; - CloseableHttpResponse response = null; - try { - // 创建uri - URIBuilder builder = new URIBuilder(url); - if (param != null) { - for (String key : param.keySet()) { - builder.addParameter(key, param.get(key)); - } - } - URI uri = builder.build(); - - // 创建http GET请求 - HttpGet httpGet = new HttpGet(uri); - - // 执行请求 - response = httpclient.execute(httpGet); - // 判断返回状态是否为200 - if (response.getStatusLine().getStatusCode() == 200) { - resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); - } - } catch (Exception e) { - e.printStackTrace(); - } finally { - try { - if (response != null) { - response.close(); - } - httpclient.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - return resultString; - } - - public static String doGet(String url) { - return doGet(url, null); - } - - public static String doPost(String url, Map param) { - // 创建Httpclient对象 - CloseableHttpClient httpClient = HttpClients.createDefault(); - CloseableHttpResponse response = null; - String resultString = ""; - try { - // 创建Http Post请求 - HttpPost httpPost = new HttpPost(url); - // 创建参数列表 - if (param != null) { - List paramList = new ArrayList<>(); - for (String key : param.keySet()) { - paramList.add(new BasicNameValuePair(key, param.get(key))); - } - // 模拟表单 - UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList); - httpPost.setEntity(entity); - } - // 执行http请求 - response = httpClient.execute(httpPost); - resultString = EntityUtils.toString(response.getEntity(), "utf-8"); - } catch (Exception e) { - e.printStackTrace(); - } finally { - try { - response.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - return resultString; - } - - public static String doPost(String url) { - return doPost(url, null); - } - - public static String doPostJson(String url, String json) { - // 创建Httpclient对象 - CloseableHttpClient httpClient = HttpClients.createDefault(); - CloseableHttpResponse response = null; - String resultString = ""; - try { - // 创建Http Post请求 - HttpPost httpPost = new HttpPost(url); - // 创建请求内容 - StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); - httpPost.setEntity(entity); - // 执行http请求 - response = httpClient.execute(httpPost); - resultString = EntityUtils.toString(response.getEntity(), "utf-8"); - } catch (Exception e) { - e.printStackTrace(); - } finally { - try { - response.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - return resultString; - } -} diff --git a/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/common/WechatUtil.java b/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/common/WechatUtil.java deleted file mode 100644 index a28af706..00000000 --- a/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/common/WechatUtil.java +++ /dev/null @@ -1,77 +0,0 @@ -package cn.lastwhisper.springbootwx.common;/** - * Create by eval on 2019/3/20 - */ - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import org.apache.shiro.codec.Base64; -import org.bouncycastle.jce.provider.BouncyCastleProvider; - -import javax.crypto.Cipher; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; -import java.security.AlgorithmParameters; -import java.security.Security; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -/** - * @ClassName WechatUtil - * @Description TODO - * @Author eval - * @Date 9:44 2019/3/20 - * @Version 1.0 - */ -public class WechatUtil { - public static JSONObject getSessionKeyOrOpenId(String code) { - String requestUrl = "https://api.weixin.qq.com/sns/jscode2session"; - Map requestUrlParam = new HashMap<>(); - // https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN - //小程序appId - requestUrlParam.put("appid", "wx8405074e879dab6e"); - //小程序secret - requestUrlParam.put("secret", "3d599bbd3395fbb286e2814909cd841e"); - //小程序端返回的code - requestUrlParam.put("js_code", code); - //默认参数 - requestUrlParam.put("grant_type", "authorization_code"); - //发送post请求读取调用微信接口获取openid用户唯一标识 - JSONObject jsonObject = JSON.parseObject(HttpClientUtil.doPost(requestUrl, requestUrlParam)); - return jsonObject; - } - - public static JSONObject getUserInfo(String encryptedData, String sessionKey, String iv) { - // 被加密的数据 - byte[] dataByte = Base64.decode(encryptedData); - // 加密秘钥 - byte[] keyByte = Base64.decode(sessionKey); - // 偏移量 - byte[] ivByte = Base64.decode(iv); - try { - // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要 - int base = 16; - if (keyByte.length % base != 0) { - int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0); - byte[] temp = new byte[groups * base]; - Arrays.fill(temp, (byte) 0); - System.arraycopy(keyByte, 0, temp, 0, keyByte.length); - keyByte = temp; - } - // 初始化 - Security.addProvider(new BouncyCastleProvider()); - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC"); - SecretKeySpec spec = new SecretKeySpec(keyByte, "AES"); - AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES"); - parameters.init(new IvParameterSpec(ivByte)); - cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化 - byte[] resultByte = cipher.doFinal(dataByte); - if (null != resultByte && resultByte.length > 0) { - String result = new String(resultByte, "UTF-8"); - return JSON.parseObject(result); - } - } catch (Exception e) { - } - return null; - } -} diff --git a/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/controller/UserController.java b/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/controller/UserController.java deleted file mode 100644 index 44225184..00000000 --- a/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/controller/UserController.java +++ /dev/null @@ -1,95 +0,0 @@ -package cn.lastwhisper.springbootwx.controller; - -import cn.lastwhisper.springbootwx.common.GlobalResult; -import cn.lastwhisper.springbootwx.mapper.UserMapper; -import cn.lastwhisper.springbootwx.pojo.User; -import cn.lastwhisper.springbootwx.common.WechatUtil; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import org.apache.commons.codec.digest.DigestUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; - -import java.util.Date; -import java.util.UUID; - -/** - * @author lastwhisper - * @desc - * @email gaojun56@163.com - */ -@Controller -public class UserController { - - @Autowired - private UserMapper userMapper; - - /** - * 微信用户登录详情 - */ - @PostMapping("wx/login") - @ResponseBody - public GlobalResult user_login(@RequestParam(value = "code", required = false) String code, - @RequestParam(value = "rawData", required = false) String rawData, - @RequestParam(value = "signature", required = false) String signature, - @RequestParam(value = "encrypteData", required = false) String encrypteData, - @RequestParam(value = "iv", required = false) String iv) { - // 用户非敏感信息:rawData - // 签名:signature - JSONObject rawDataJson = JSON.parseObject(rawData); - // 1.接收小程序发送的code - // 2.开发者服务器 登录凭证校验接口 appi + appsecret + code - JSONObject SessionKeyOpenId = WechatUtil.getSessionKeyOrOpenId(code); - // 3.接收微信接口服务 获取返回的参数 - String openid = SessionKeyOpenId.getString("openid"); - String sessionKey = SessionKeyOpenId.getString("session_key"); - - // 4.校验签名 小程序发送的签名signature与服务器端生成的签名signature2 = sha1(rawData + sessionKey) - String signature2 = DigestUtils.sha1Hex(rawData + sessionKey); - if (!signature.equals(signature2)) { - return GlobalResult.build(500, "签名校验失败", null); - } - // 5.根据返回的User实体类,判断用户是否是新用户,是的话,将用户信息存到数据库;不是的话,更新最新登录时间 - User user = this.userMapper.selectById(openid); - // uuid生成唯一key,用于维护微信小程序用户与服务端的会话 - String skey = UUID.randomUUID().toString(); - if (user == null) { - // 用户信息入库 - String nickName = rawDataJson.getString("nickName"); - String avatarUrl = rawDataJson.getString("avatarUrl"); - String gender = rawDataJson.getString("gender"); - String city = rawDataJson.getString("city"); - String country = rawDataJson.getString("country"); - String province = rawDataJson.getString("province"); - - user = new User(); - user.setOpenId(openid); - user.setSkey(skey); - user.setCreateTime(new Date()); - user.setLastVisitTime(new Date()); - user.setSessionKey(sessionKey); - user.setCity(city); - user.setProvince(province); - user.setCountry(country); - user.setAvatarUrl(avatarUrl); - user.setGender(Integer.parseInt(gender)); - user.setNickName(nickName); - - this.userMapper.insert(user); - } else { - // 已存在,更新用户登录时间 - user.setLastVisitTime(new Date()); - // 重新设置会话skey - user.setSkey(skey); - this.userMapper.updateById(user); - } - //encrypteData比rowData多了appid和openid - //JSONObject userInfo = WechatUtil.getUserInfo(encrypteData, sessionKey, iv); - //6. 把新的skey返回给小程序 - GlobalResult result = GlobalResult.build(200, null, skey); - return result; - } -} diff --git a/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/mapper/UserMapper.java b/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/mapper/UserMapper.java deleted file mode 100644 index f5c386c2..00000000 --- a/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/mapper/UserMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.lastwhisper.springbootwx.mapper; - -import cn.lastwhisper.springbootwx.pojo.User; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; - -/** - * @desc - * - * @author lastwhisper - * @email gaojun56@163.com - */ -public interface UserMapper extends BaseMapper { -} diff --git a/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/pojo/User.java b/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/pojo/User.java deleted file mode 100644 index 5c6270b3..00000000 --- a/springboot-integration-examples/springboot-wx/src/main/java/cn/lastwhisper/springbootwx/pojo/User.java +++ /dev/null @@ -1,78 +0,0 @@ -package cn.lastwhisper.springbootwx.pojo; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.util.Date; - -/** - * @author lastwhisper - * @desc - * @email gaojun56@163.com - */ -@Data -@TableName("user") -public class User { - private static final long serialVersionUID = 1L; - /** - * open_id - */ - @TableId(value = "open_id",type = IdType.INPUT) - private String openId; - /** - * skey - */ - private String skey; - /** - * 创建时间 - */ - @TableField("create_time") - @DateTimeFormat(pattern = "yyyy-MM-dd") - private Date createTime; - /** - * 最后登录时间 - */ - @TableField("last_visit_time") - @DateTimeFormat(pattern = "yyyy-MM-dd") - private Date lastVisitTime; - /** - * session_key - */ - @TableField("session_key") - private String sessionKey; - /** - * 市 - */ - @TableField("city") - private String city; - /** - * 省 - */ - @TableField("province") - private String province; - /** - * 国 - */ - @TableField("country") - private String country; - /** - * 头像 - */ - @TableField("avatar_url") - private String avatarUrl; - /** - * 性别 - */ - @TableField("gender") - private Integer gender; - /** - * 网名 - */ - @TableField("nick_name") - private String nickName; - -} diff --git a/springboot-integration-examples/springboot-wx/src/main/resources/application.properties b/springboot-integration-examples/springboot-wx/src/main/resources/application.properties deleted file mode 100644 index d232612b..00000000 --- a/springboot-integration-examples/springboot-wx/src/main/resources/application.properties +++ /dev/null @@ -1,5 +0,0 @@ -spring.application.name = lastwhisper-wxlogin -spring.datasource.driver-class-name=com.mysql.jdbc.Driver -spring.datasource.url=jdbc:mysql://127.0.0.1:3306/wxlogin?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false -spring.datasource.username=root -spring.datasource.password=root \ No newline at end of file diff --git a/springboot-integration-examples/springboot-wx/src/test/java/cn/lastwhisper/springbootwx/SpringbootwxApplicationTests.java b/springboot-integration-examples/springboot-wx/src/test/java/cn/lastwhisper/springbootwx/SpringbootwxApplicationTests.java deleted file mode 100644 index 84a162f3..00000000 --- a/springboot-integration-examples/springboot-wx/src/test/java/cn/lastwhisper/springbootwx/SpringbootwxApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.lastwhisper.springbootwx; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class SpringbootwxApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git "a/springboot-integration-examples/\345\257\271\345\272\224\347\254\224\350\256\260/SpringBoot-aoplogmd.md" "b/springboot-integration-examples/\345\257\271\345\272\224\347\254\224\350\256\260/SpringBoot-aoplogmd.md" deleted file mode 100644 index d8ca4ede..00000000 --- "a/springboot-integration-examples/\345\257\271\345\272\224\347\254\224\350\256\260/SpringBoot-aoplogmd.md" +++ /dev/null @@ -1,362 +0,0 @@ -> **该项目源码地址:https://github.com/ggb2312/springboot-integration-examples(其中包含SpringBoot和其他常用技术的整合,配套源码以及笔记。基于最新的 SpringBoot2.1+,欢迎各位 Star)** - -# 1. 开发前准备 - -## 1.1 前置知识 -- java基础自定义注解、反射 -- Spring aop -- SpringBoot简单基础知识即可 - -## 1.2 环境参数 -- 开发工具:IDEA -- 基础环境:Maven+JDK8 -- 所用技术:SpringBoot、lombok、mybatisplus、**Spring aop** -- SpringBoot版本:2.1.4 - -## 1.3 涉及知识点 -- 自定义注解、 反射 -- spring aop 环绕通知 - - - -# 2. aop日志实现 - -AOP(Aspect Oriented Programming)是一个大话题,这里不做介绍,直接使用。 -**实现效果:**用户在浏览器操作web页面,对应的操作会被记录到数据库中。 -**实现思路:**自定义一个注解,将注解加到某个方法上,使用aop环绕通知代理带有注解的方法,在环绕前进行日志准备,执行完方法后进行日志入库。 -**项目结构:** -![项目结构](https://upload-images.jianshu.io/upload_images/5336514-c965fd1d513dedec.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - - - -## 2.1 log表 - -```sql -CREATE TABLE `log` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `operateor` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `operateType` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `operateDate` datetime(0) NULL DEFAULT NULL, - `operateResult` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `ip` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -``` - - - -## 2.2 pojo - -log表对应的实体类,使用了lombok的`@Data`注解,也可以使用get、set代替,使用了mybatisplus,所以配置了@TableName等注解,如果使用mybatis或者其他的orm,可以把注解拿掉。 - -```java -package cn.lastwhisper.springbootaop.pojo; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.util.Date; - -@Data -@TableName("log") -public class Log { - @TableId(value = "id", type = IdType.AUTO) - private Integer id; - - @TableField("operateor") - private String operateor; - - @TableField("operateType") - private String operatetype; - - @TableField("operateDate") - @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private Date operatedate; - - @TableField("operatereSult") - private String operateresult; - - @TableField("ip") - private String ip; -} -``` - - - -## 2.3 controller - -该Controller用于接收用户的请求,并对用户操作进行记录。 - -```java -package cn.lastwhisper.springbootaop.controller; -import cn.lastwhisper.springbootaop.core.annotation.LogAnno; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author lastwhisper - * @desc - * @email gaojun56@163.com - */ -@RestController -public class UserController { - /** - * @desc 这里为了方便直接在controller上进行aop日志记录,也可以放在service上。 - * @author lastwhisper - * @Param - * @return - */ - @LogAnno(operateType = "添加用户") - @RequestMapping(value = "/user/add") - public void add() { - System.out.println("向数据库中添加用户!!"); - } -} -``` - - - -## 2.4 mapper - -该mapper用于对log表进行操作 - -```java -package cn.lastwhisper.springbootaop.mapper; - -import cn.lastwhisper.springbootaop.pojo.Log; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; - -/** - * @desc - * - * @author lastwhisper - * @email gaojun56@163.com - */ -public interface LogMapper extends BaseMapper { -} - -``` - - - -## 2.5 core - -### 2.5.1 日志注解 - -该注解用于标识需要被环绕通知进行日志操作的方法 - -```java -package cn.lastwhisper.springbootaop.core.annotation; - -import org.springframework.core.annotation.Order; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 日志注解 - * - * @author lastwhisper - */ -@Order(20) -@Target(ElementType.METHOD) // 方法注解 -@Retention(RetentionPolicy.RUNTIME) // 运行时可见 -public @interface LogAnno { - String operateType();// 记录日志的操作类型 -} -``` - -### 2.5.2 aop环绕通知类 - -对带有LogAnno注解的方法进行环绕通知日志记录。 - -`@Order(3)`注解一定要带上,**标记支持AspectJ的切面排序**。 - -```java -package cn.lastwhisper.springbootaop.core.aop; - -import java.lang.reflect.Method; -import java.sql.SQLException; -import java.util.Date; - -import cn.lastwhisper.springbootaop.core.annotation.LogAnno; -import cn.lastwhisper.springbootaop.core.common.HttpContextUtil; -import cn.lastwhisper.springbootaop.mapper.LogMapper; -import cn.lastwhisper.springbootaop.pojo.Log; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; - -/** - * AOP实现日志 - * - * @author 最后的轻语_dd43 - * - */ -@Order(3) -@Component -@Aspect -public class LogAopAspect { - // 日志mapper,这里省事少写了service - @Autowired - private LogMapper logMapper; - - /** - * 环绕通知记录日志通过注解匹配到需要增加日志功能的方法 - * - * @param pjp - * @return - * @throws Throwable - */ - @Around("@annotation(cn.lastwhisper.springbootaop.core.annotation.LogAnno)") - public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable { - // 1.方法执行前的处理,相当于前置通知 - // 获取方法签名 - MethodSignature methodSignature = (MethodSignature) pjp.getSignature(); - // 获取方法 - Method method = methodSignature.getMethod(); - // 获取方法上面的注解 - LogAnno logAnno = method.getAnnotation(LogAnno.class); - // 获取操作描述的属性值 - String operateType = logAnno.operateType(); - // 创建一个日志对象(准备记录日志) - Log log = new Log(); - log.setOperatetype(operateType);// 操作说明 - - // 设置操作人,从session中获取,这里简化了一下,写死了。 - log.setOperateor("lastwhisper"); - String ip = HttpContextUtil.getIpAddress(); - log.setIp(ip); - Object result = null; - try { - // 让代理方法执行 - result = pjp.proceed(); - // 2.相当于后置通知(方法成功执行之后走这里) - log.setOperateresult("正常");// 设置操作结果 - } catch (SQLException e) { - // 3.相当于异常通知部分 - log.setOperateresult("失败");// 设置操作结果 - } finally { - // 4.相当于最终通知 - log.setOperatedate(new Date());// 设置操作日期 - logMapper.insert(log);// 添加日志记录 - } - return result; - } - -} -``` - -### 2.5.3 common - -用于获取用户的ip - -```java -package cn.lastwhisper.springbootaop.core.common; - -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -import javax.servlet.http.HttpServletRequest; - -/** - * @desc - * - * @author lastwhisper - * @email gaojun56@163.com - */ -public class HttpContextUtil { - public static HttpServletRequest getRequest() { - return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) - .getRequest(); - } - - /** - * 获取IP地址的方法 - * - * @param request 传一个request对象下来 - * @return - */ - public static String getIpAddress() { - HttpServletRequest request = getRequest(); - String ip = request.getHeader("x-forwarded-for"); - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { - ip = request.getHeader("Proxy-Client-IP"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { - ip = request.getHeader("WL-Proxy-Client-IP"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { - ip = request.getHeader("HTTP_CLIENT_IP"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { - ip = request.getHeader("HTTP_X_FORWARDED_FOR"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { - ip = request.getRemoteAddr(); - } - return ip; - } -} -``` - -## 2.6 最终配置 - -配置application.properties文件 - -```properties -spring.application.name = lastwhisper-aoplog -spring.datasource.driver-class-name=com.mysql.jdbc.Driver -spring.datasource.url=jdbc:mysql://127.0.0.1:3306/wxlogin?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false -spring.datasource.username=root -spring.datasource.password=root - -``` - -配置springboot启动类SpringbootaopApplication - -```java -package cn.lastwhisper.springbootaop; - -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@MapperScan("cn.lastwhisper.springbootaop.mapper") //设置mapper接口的扫描包 -@SpringBootApplication -public class SpringbootaopApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringbootaopApplication.class, args); - } - -} - -``` - -至此一个完整的SpringBoot AOP日志系统基本成型。 - -# 3. 测试 - -启动`SpringbootaopApplication`的main方法。访问 http://localhost:8080/user/add - -会在idea的控制台看到 `` - -![console](https://upload-images.jianshu.io/upload_images/5336514-f8f34db34104ff59.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -然后再看一下数据库,保存了日志信息。 -![aop 日志](https://upload-images.jianshu.io/upload_images/5336514-7239a28ae9997af1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - - - -如果是springmvc项目没有生效,应该是自定义aop与事务aop顺序问题,需要在配置文件中配置`order="200"`。如果配置文件配置order无效,建议不要使用配置文件事务,使用注解事务。 \ No newline at end of file diff --git "a/springboot-integration-examples/\345\257\271\345\272\224\347\254\224\350\256\260/SpringBoot-mybatisplus.md" "b/springboot-integration-examples/\345\257\271\345\272\224\347\254\224\350\256\260/SpringBoot-mybatisplus.md" deleted file mode 100644 index eb282307..00000000 --- "a/springboot-integration-examples/\345\257\271\345\272\224\347\254\224\350\256\260/SpringBoot-mybatisplus.md" +++ /dev/null @@ -1,542 +0,0 @@ -> **该项目源码地址:https://github.com/ggb2312/springboot-integration-examples(其中包含SpringBoot和其他常用技术的整合,配套源码以及笔记。基于最新的 SpringBoot2.1+,欢迎各位 Star)** - -# 1. 开发前准备 - -## 1.1 前置知识 -- java基础 -- SpringBoot简单基础知识 - - -## 1.2 环境参数 -- 开发工具:IDEA -- 基础环境:Maven+JDK8 -- 所用技术:SpringBoot、lombok、MybatisPlus -- SpringBoot版本:2.1.4 - -## 1.3 涉及知识点 -- MybatisPlus简介、特性、架构 -- MybatisPlus快速入门 -- MybatisPlus的基本CRUD -- MybatisPlus的高级查询:like查询、条件查询、分页查询等 - -# 2. MybatisPlus入门 - -## 2.1 简介 - -[MyBatis-Plus](https://github.com/baomidou/mybatis-plus)(简称 MP)是一个 [MyBatis](http://www.mybatis.org/mybatis-3/) 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 - -## 2.2 特性 - -- **无侵入**:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑 -- **损耗小**:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作 -- **强大的 CRUD 操作**:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求 -- **支持 Lambda 形式调用**:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错 -- **支持多种数据库**:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer2005、SQLServer 等多种数据库 -- **支持主键自动生成**:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题 -- **支持 XML 热加载**:Mapper 对应的 XML 支持热加载,对于简单的 CRUD 操作,甚至可以无 XML 启动 -- **支持 ActiveRecord 模式**:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作 -- **支持自定义全局通用操作**:支持全局通用方法注入( Write once, use anywhere ) -- **支持关键词自动转义**:支持数据库关键词(order、key......)自动转义,还可自定义关键词 -- **内置代码生成器**:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用 -- **内置分页插件**:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询 -- **内置性能分析插件**:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询 -- **内置全局拦截插件**:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作 -- **内置 Sql 注入剥离器**:支持 Sql 注入剥离,有效预防 Sql 注入攻击 - -## 2.3 架构 -![MybatisPlus架构](https://upload-images.jianshu.io/upload_images/5336514-de256f59d2e18cf3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -## 2.4 快速入门 -项目结构: -![项目结构](https://upload-images.jianshu.io/upload_images/5336514-93f1ecb4766522a5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -### 2.4.1 创建表 - -```sql -DROP TABLE IF EXISTS user; - -CREATE TABLE user -( - id BIGINT(20) NOT NULL COMMENT '主键ID', - name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', - age INT(11) NULL DEFAULT NULL COMMENT '年龄', - email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱', - PRIMARY KEY (id) -)ENGINE=InnoDB DEFAULT CHARSET=utf8; - -DELETE FROM user; - -INSERT INTO user (id, name, age, email) VALUES -(1, 'Jone', 18, 'test1@baomidou.com'), -(2, 'Jack', 20, 'test2@baomidou.com'), -(3, 'Tom', 28, 'test3@baomidou.com'), -(4, 'Sandy', 21, 'test4@baomidou.com'), -(5, 'Billie', 24, 'test5@baomidou.com'); -``` - -### 2.4.2 创建工程以及导入依赖 - -[SpringBoot项目新建](https://www.jianshu.com/p/c6f4fbd1e492) - -```xml - - - - org.projectlombok - lombok - true - - - - com.baomidou - mybatis-plus-boot-starter - 3.1.1 - - - - mysql - mysql-connector-java - 5.1.47 - - - -``` - -### 2.4.3 编写application.properties文件 - -```properties -spring.application.name = lastwhisper-mybatis-plus -spring.datasource.driver-class-name=com.mysql.jdbc.Driver -spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mybatisplus?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false -spring.datasource.username=root -spring.datasource.password=root -``` - -### 2.4.4 创建User对象 - -```java -package cn.lastwhisper.springbootmybatisplus.pojo; - -import lombok.Data; -import lombok.ToString; - -/** - * @desc - * - * @author lastwhisper - * @email gaojun56@163.com - */ -@Data -@ToString -public class User { - private Long id; - private String name; - private Integer age; - private String email; -} - -``` - -### 2.4.5 编写UserMapper - -```java -package cn.lastwhisper.springbootmybatisplus.mapper; - -import cn.lastwhisper.springbootmybatisplus.pojo.User; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -/** - * @desc - * - * @author lastwhisper - * @email gaojun56@163.com - */ -public interface UserMapper extends BaseMapper { -} -``` - -### 2.4.6 设置Mapper接口的包扫描 - -修改SpringBoot启动类 - -```java -package cn.lastwhisper.springbootmybatisplus; - -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@MapperScan("cn.lastwhisper.springbootmybatisplus.mapper") //设置mapper接口的扫描包 -@SpringBootApplication -public class SpringbootmybatisplusApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringbootmybatisplusApplication.class, args); - } - -} - -``` - -### 2.4.7 编写测试单元 - -```java -package cn.lastwhisper.springbootmybatisplus; - -import cn.lastwhisper.springbootmybatisplus.mapper.UserMapper; -import cn.lastwhisper.springbootmybatisplus.pojo.User; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -import java.util.List; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class SpringbootmybatisplusApplicationTests { - - - @Autowired - private UserMapper userMapper; - - @Test - public void testSelect() { - System.out.println(("----- selectAll method test ------")); - List userList = userMapper.selectList(null); - for (User user : userList) { - System.out.println(user); - } - } -} - -``` -![测试结果](https://upload-images.jianshu.io/upload_images/5336514-64faf3f0a913d511.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - - - -## 2.5 BaseMapper - -在MybatisPlus中,BaseMapper中定义了一些常用的CRUD方法,当我们自定义的Mapper接口继承BaseMapper后即可拥有了这些方法。 - -> 需要说明的是:这些方法仅适合单表操作。 - -BaseMapper接口的代码如下 - -```java -/** - * Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能 - *

这个 Mapper 支持 id 泛型

- * - * @author hubin - * @since 2016-01-23 - */ -public interface BaseMapper extends Mapper { - - /** - * 插入一条记录 - * - * @param entity 实体对象 - */ - int insert(T entity); - - /** - * 根据 ID 删除 - * - * @param id 主键ID - */ - int deleteById(Serializable id); - - /** - * 根据 columnMap 条件,删除记录 - * - * @param columnMap 表字段 map 对象 - */ - int deleteByMap(@Param(Constants.COLUMN_MAP) Map columnMap); - - /** - * 根据 entity 条件,删除记录 - * - * @param wrapper 实体对象封装操作类(可以为 null) - */ - int delete(@Param(Constants.WRAPPER) Wrapper wrapper); - - /** - * 删除(根据ID 批量删除) - * - * @param idList 主键ID列表(不能为 null 以及 empty) - */ - int deleteBatchIds(@Param(Constants.COLLECTION) Collection idList); - - /** - * 根据 ID 修改 - * - * @param entity 实体对象 - */ - int updateById(@Param(Constants.ENTITY) T entity); - - /** - * 根据 whereEntity 条件,更新记录 - * - * @param entity 实体对象 (set 条件值,可以为 null) - * @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句) - */ - int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper updateWrapper); - - /** - * 根据 ID 查询 - * - * @param id 主键ID - */ - T selectById(Serializable id); - - /** - * 查询(根据ID 批量查询) - * - * @param idList 主键ID列表(不能为 null 以及 empty) - */ - List selectBatchIds(@Param(Constants.COLLECTION) Collection idList); - - /** - * 查询(根据 columnMap 条件) - * - * @param columnMap 表字段 map 对象 - */ - List selectByMap(@Param(Constants.COLUMN_MAP) Map columnMap); - - /** - * 根据 entity 条件,查询一条记录 - * - * @param queryWrapper 实体对象封装操作类(可以为 null) - */ - T selectOne(@Param(Constants.WRAPPER) Wrapper queryWrapper); - - /** - * 根据 Wrapper 条件,查询总记录数 - * - * @param queryWrapper 实体对象封装操作类(可以为 null) - */ - Integer selectCount(@Param(Constants.WRAPPER) Wrapper queryWrapper); - - /** - * 根据 entity 条件,查询全部记录 - * - * @param queryWrapper 实体对象封装操作类(可以为 null) - */ - List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper); - - /** - * 根据 Wrapper 条件,查询全部记录 - * - * @param queryWrapper 实体对象封装操作类(可以为 null) - */ - List> selectMaps(@Param(Constants.WRAPPER) Wrapper queryWrapper); - - /** - * 根据 Wrapper 条件,查询全部记录 - *

注意: 只返回第一个字段的值

- * - * @param queryWrapper 实体对象封装操作类(可以为 null) - */ - List selectObjs(@Param(Constants.WRAPPER) Wrapper queryWrapper); - - /** - * 根据 entity 条件,查询全部记录(并翻页) - * - * @param page 分页查询条件(可以为 RowBounds.DEFAULT) - * @param queryWrapper 实体对象封装操作类(可以为 null) - */ - IPage selectPage(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper); - - /** - * 根据 Wrapper 条件,查询全部记录(并翻页) - * - * @param page 分页查询条件 - * @param queryWrapper 实体对象封装操作类 - */ - IPage> selectMapsPage(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper); -} - -``` - - - -### 2.5.1 like查询 - -```java -@Test - public void testselectByLike() { - QueryWrapper queryWrapper = new QueryWrapper<>(new User()); - // 查询名字中包含"o"的用户 - queryWrapper.like("name", "o"); - - List users = this.userMapper.selectList(queryWrapper); - for (User user : users) { - System.out.println(user); - } - } -``` -测试结果: - -![like查询](https://upload-images.jianshu.io/upload_images/5336514-5628a2b4fca702c7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -### 2.5.2 条件查询 -```java -// 条件查询 - @Test - public void testselectByLe(){ - QueryWrapper queryWrapper = new QueryWrapper<>(new User()); - //查询年龄小于等于20的用户 - queryWrapper.le("age",20); - - List users = this.userMapper.selectList(queryWrapper); - for (User user:users) { - System.out.println(user); - } - } -``` - -测试结果: - -![条件查询](https://upload-images.jianshu.io/upload_images/5336514-cf18cb54eb560256.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -更多查看:http://mp.baomidou.com/guide/wrapper.html#abstractwrapper - -### 2.5.3 插入数据 -数据库主键自增: @TableId(value = "ID", type = IdType.AUTO) -数据库主键自己维护:@TableId(value = "open_id",type = IdType.INPUT) - -设置主键自增长 -```java -@Data -@ToString -public class User { - @TableId(value = "ID", type = IdType.AUTO) - private Long id; - private String name; - private Integer age; - private String email; -} -``` - -设置表主键自增 - -![主键自增](https://upload-images.jianshu.io/upload_images/5336514-9b01af648b413e8f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -测试代码 - -```java -//插入数据 - @Test - public void testSave(){ - User user = new User(); - user.setAge(21); - user.setEmail("gaojun56@163.com"); - user.setName("gaojun"); - int count = this.userMapper.insert(user); - System.out.println("新增数据成功! count => " + count); - } -``` -测试结果: - -![测试结果](https://upload-images.jianshu.io/upload_images/5336514-147f70abd8225e68.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -数据库: - -![测试结果](https://upload-images.jianshu.io/upload_images/5336514-5e1f34cb0f368f80.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -### 2.5.4 删除数据 -```java -//删除数据 - @Test - public void testDelete(){ - this.userMapper.deleteById(6L); - System.out.println("删除成功!"); - } -``` -测试结果: - -![测试结果](https://upload-images.jianshu.io/upload_images/5336514-e1479c0a8b5e7c02.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -### 2.5.5 修改数据 -根据id修改数据,修改不为null的字段 -```java -//修改数据 -@Test - public void testUpdate(){ - User user = new User(); - user.setId(5L); - user.setName("gaojun"); - user.setEmail("gaojun56@163.com"); - this.userMapper.updateById(user); - System.out.println("修改成功!"); - } -``` -测试结果: - -![测试结果](https://upload-images.jianshu.io/upload_images/5336514-c1db5140e574d5f5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -![测试结果](https://upload-images.jianshu.io/upload_images/5336514-843fd6e20cdedafa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -### 2.5.6 分页查询 - -首先在SpringBoot启动类中配置分页插件 - -```java -@MapperScan("cn.lastwhisper.springbootmybatisplus.mapper") //设置mapper接口的扫描包 -@SpringBootApplication -public class SpringbootmybatisplusApplication { - - /** - * 分页插件 - */ - @Bean - public PaginationInterceptor paginationInterceptor() { - return new PaginationInterceptor(); - } - - public static void main(String[] args) { - SpringApplication.run(SpringbootmybatisplusApplication.class, args); - } - -} - -``` - -测试类: - -```java -//分页查询 - @Test - public void testselectPage() { - Page page = new Page<>(1, 2); - IPage userIPage = this.userMapper.selectPage(page, null); - System.out.println("总条数 ------> " + userIPage.getTotal()); - System.out.println("当前页数 ------> " + userIPage.getCurrent()); - System.out.println("当前每页显示数 ------> " + userIPage.getSize()); - List records = userIPage.getRecords(); - for (User user : records) { - System.out.println(user); - } - } -``` - -测试结果: -![测试结果](https://upload-images.jianshu.io/upload_images/5336514-2da133a78d36d3a9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - - - -## 2.6 配置 - -虽然在MybatisPlus中可以实现零配置,但是有些时候需要我们自定义一些配置,就需要使用Mybatis原生的一些配置文件方式了。 - - application.properties: - -```properties -# 指定全局配置文件 -mybatis-plus.config-location = classpath:mybatis-config.xml -# 指定mapper.xml文件 -mybatis-plus.mapper-locations = classpath*:mybatis/*.xml -``` - -更多配置:https://mp.baomidou.com/guide/config.html \ No newline at end of file diff --git "a/springboot-integration-examples/\345\257\271\345\272\224\347\254\224\350\256\260/SpringBoot-oss.md" "b/springboot-integration-examples/\345\257\271\345\272\224\347\254\224\350\256\260/SpringBoot-oss.md" deleted file mode 100644 index 98336d26..00000000 --- "a/springboot-integration-examples/\345\257\271\345\272\224\347\254\224\350\256\260/SpringBoot-oss.md" +++ /dev/null @@ -1,579 +0,0 @@ -> **该项目源码地址:https://github.com/ggb2312/springboot-integration-examples(其中包含SpringBoot和其他常用技术的整合,配套源码以及笔记。基于最新的 SpringBoot2.1+,欢迎各位 Star)** - -# 1. 开发前准备 - -## 1.1 前置知识 -- java基础 -- SpringBoot简单基础知识 - -## 1.2 环境参数 -- 开发工具:IDEA -- 基础环境:Maven+JDK8 -- 所用技术:SpringBoot、lombok、阿里云OSS存储服务 -- SpringBoot版本:2.1.4 - -## 1.3 涉及知识点 -- OSS简介,以及阿里云OSS控制台快速入门使用 -- SpringBoot 整合 阿里云OSS 存储服务,进行文件上传、下载、查看、删除 -- 阿里云OSS文档介绍,以及快速入门使用 -- lombok入门使用以及IDEA lombok插件安装 -- SpringMVC与AJAX前后端分离交互 -- AJAX文件异步上传 - -# 2. 使用阿里云OSS -对象存储OSS的多重冗余架构设计,为数据持久存储提供可靠保障。 -## 2.1 创建Bucket -使用OSS,首先需要创建Bucket,Bucket翻译成中文是水桶的意思,把存储的图片资源看做是水,想要盛水必须得 -有桶。 -进入控制台,https://oss.console.aliyun.com/overview - -![新建Bucket](https://upload-images.jianshu.io/upload_images/5336514-f8c5512fa6084fe5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -![新建 Bucket](https://upload-images.jianshu.io/upload_images/5336514-e3006193988291c4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -创建完成后,在左侧可以看到已经创建好的Bucket: - -![Bucket](https://upload-images.jianshu.io/upload_images/5336514-b42a82d12baa340b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -选择Bucket后,即可看到对应的信息,如:url、消耗流量等 - -![Bucket相关信息](https://upload-images.jianshu.io/upload_images/5336514-38cb38befa6aeaf6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -## 2.2 管理文件 -可以通过在线的方式进行管理文件 - -![管理文件](https://upload-images.jianshu.io/upload_images/5336514-4eea09a699e304ac.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -## 2.3 阿里云OSS文档 - -[阿里云OSS文档](https://help.aliyun.com/product/31815.html?spm=a2c4g.11186623.6.540.517822372ASOvk) - -![阿里云OSS文档](https://upload-images.jianshu.io/upload_images/5336514-4df24be98ecfa55b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -右侧的开发指南说的更加详细 -![开发指南](https://upload-images.jianshu.io/upload_images/5336514-4f709bb5848c7c3f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -阿里云虽然提供了完整的文档,但是做一个完整的前后端交互的文件上传、下载、查看、删除等操作,对于小白来说还是有点难度的,所以我把自己学习OSS的步骤以及代码分享了出来,共有需要的人使用。 - -# 3. 项目初始化 - -## 3.1 创建SpringBoot项目 -在Idea中File——>New——>Project -![创建SpringBoot项目 步骤一](https://upload-images.jianshu.io/upload_images/5336514-0f9a30d8fe087c50.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -![创建SpringBoot项目 步骤二](https://upload-images.jianshu.io/upload_images/5336514-a658fb76a0950b01.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -![创建SpringBoot项目 步骤三](https://upload-images.jianshu.io/upload_images/5336514-6be4593b1c65adec.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -![创建SpringBoot项目 步骤四](https://upload-images.jianshu.io/upload_images/5336514-0ae22056caa7f423.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -## 3.2 Maven依赖 -导入Maven相关依赖 -``` - - com.aliyun.oss - aliyun-sdk-oss - 2.8.3 - - - - org.projectlombok - lombok - 1.18.4 - provided - - - - joda-time - joda-time - 2.9.9 - - - - org.apache.commons - commons-lang3 - 3.8.1 - -``` -## 3.3 安装lombok插件 -因为项目中使用了lombok的`@Data`注解,当然你也可以自己写get、set等方法。 -File——>settings——>Plugins -![安装lombok插件](https://upload-images.jianshu.io/upload_images/5336514-5276d48cc6776ce4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -![安装lombok插件](https://upload-images.jianshu.io/upload_images/5336514-d5ac2a7871a502f2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -然后restart IDEA即可。 - -# 4. 后端服务编写 -![项目结构](https://upload-images.jianshu.io/upload_images/5336514-aada92c3c74e00d2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -## 4.1 阿里云OSS配置 -在resource下新建一个application-oss.properties -``` -aliyun.endpoint=oss-cn-shanghai.aliyuncs.com -aliyun.accessKeyId=你的accessKeyId -aliyun.accessKeySecret=你的accessKeySecret -aliyun.bucketName=gaojun-testbucket -aliyun.urlPrefix=http://gaojun-testbucket.oss-cn-shanghai.aliyuncs.com/ -spring.servlet.multipart.max-file-size=100MB -spring.servlet.multipart.max-request-size=1000MB -``` - -endpoint、bucketName、urlPrefix在OSS主面板就可以看到 - -![bucketName、endpoint与urlPrefix](https://upload-images.jianshu.io/upload_images/5336514-2818153bf58ebfce.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -accessKeyId、accessKeySecret需要在accesskeys里面查看 - -![accesskeys与accessKeySecret](https://upload-images.jianshu.io/upload_images/5336514-176959cccd4e52de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -在java的包下新建一个config包,创建一个AliyunConfig.java -```java -package com.example.ossdemo.config; - -import com.aliyun.oss.OSS; -import com.aliyun.oss.OSSClient; -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; -/** - * @desc - * - * @author lastwhisper - * @email gaojun56@163.com - */ -@Configuration -@PropertySource(value = {"classpath:application-oss.properties"}) -@ConfigurationProperties(prefix = "aliyun") -@Data -public class AliyunConfig { - private String endpoint; - private String accessKeyId; - private String accessKeySecret; - private String bucketName; - private String urlPrefix; - - @Bean - public OSS oSSClient() { - return new OSSClient(endpoint, accessKeyId, accessKeySecret); - } -} -``` - -## 4.2 后端业务 -### 4.2.1 vo - -该实体类用于后台返回给前台。 - -```java -package com.example.ossdemo.vo; - -import lombok.Data; - -/** - * @author lastwhisper - * @desc 用于前后端交互的返回值 - * @email gaojun56@163.com - */ -@Data -public class FileUploadResult { - // 文件唯一标识 - private String uid; - // 文件名 - private String name; - // 状态有:uploading done error removed - private String status; - // 服务端响应内容,如:'{"status": "success"}' - private String response; -} - -``` -### 4.2.2 service - -在service使用ossClient操作阿里云OSS,进行上传、下载、删除、查看所有文件等操作,同时可以将图片的url进行入库操作。 - -```java -package com.example.ossdemo.service; - -import com.aliyun.oss.OSS; -import com.aliyun.oss.model.*; -import com.example.ossdemo.config.AliyunConfig; -import com.example.ossdemo.vo.FileUploadResult; -import org.apache.commons.lang3.RandomUtils; -import org.apache.commons.lang3.StringUtils; -import org.joda.time.DateTime; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; - -import java.io.*; -import java.util.List; - -/** - * @author lastwhisper - * @desc - * @email gaojun56@163.com - */ -@Service -public class FileUploadService { - // 允许上传的格式 - private static final String[] IMAGE_TYPE = new String[]{".bmp", ".jpg", - ".jpeg", ".gif", ".png"}; - @Autowired - private OSS ossClient; - @Autowired - private AliyunConfig aliyunConfig; - - /** - * @author lastwhisper - * @desc 文件上传 - * 文档链接 https://help.aliyun.com/document_detail/84781.html?spm=a2c4g.11186623.6.749.11987a7dRYVSzn - * @email gaojun56@163.com - */ - public FileUploadResult upload(MultipartFile uploadFile) { - // 校验图片格式 - boolean isLegal = false; - for (String type : IMAGE_TYPE) { - if (StringUtils.endsWithIgnoreCase(uploadFile.getOriginalFilename(), - type)) { - isLegal = true; - break; - } - } - //封装Result对象,并且将文件的byte数组放置到result对象中 - FileUploadResult fileUploadResult = new FileUploadResult(); - if (!isLegal) { - fileUploadResult.setStatus("error"); - return fileUploadResult; - } - //文件新路径 - String fileName = uploadFile.getOriginalFilename(); - String filePath = getFilePath(fileName); - // 上传到阿里云 - try { - ossClient.putObject(aliyunConfig.getBucketName(), filePath, new - ByteArrayInputStream(uploadFile.getBytes())); - } catch (Exception e) { - e.printStackTrace(); - //上传失败 - fileUploadResult.setStatus("error"); - return fileUploadResult; - } - fileUploadResult.setStatus("done"); - fileUploadResult.setResponse("success"); - //this.aliyunConfig.getUrlPrefix() + filePath 文件路径需要保存到数据库 - fileUploadResult.setName(this.aliyunConfig.getUrlPrefix() + filePath); - fileUploadResult.setUid(String.valueOf(System.currentTimeMillis())); - return fileUploadResult; - } - - /** - * @author lastwhisper - * @desc 生成路径以及文件名 例如://images/2019/04/28/15564277465972939.jpg - * @email gaojun56@163.com - */ - private String getFilePath(String sourceFileName) { - DateTime dateTime = new DateTime(); - return "images/" + dateTime.toString("yyyy") - + "/" + dateTime.toString("MM") + "/" - + dateTime.toString("dd") + "/" + System.currentTimeMillis() + - RandomUtils.nextInt(100, 9999) + "." + - StringUtils.substringAfterLast(sourceFileName, "."); - } - - /** - * @author lastwhisper - * @desc 查看文件列表 - * 文档链接 https://help.aliyun.com/document_detail/84841.html?spm=a2c4g.11186623.2.13.3ad5b5ddqxWWRu#concept-84841-zh - * @email gaojun56@163.com - */ - public List list() { - // 设置最大个数。 - final int maxKeys = 200; - // 列举文件。 - ObjectListing objectListing = ossClient.listObjects(new ListObjectsRequest(aliyunConfig.getBucketName()).withMaxKeys(maxKeys)); - List sums = objectListing.getObjectSummaries(); - return sums; - } - - /** - * @author lastwhisper - * @desc 删除文件 - * 文档链接 https://help.aliyun.com/document_detail/84842.html?spm=a2c4g.11186623.6.770.4f9474b4UYlCtr - * @email gaojun56@163.com - */ - public FileUploadResult delete(String objectName) { - // 根据BucketName,objectName删除文件 - ossClient.deleteObject(aliyunConfig.getBucketName(), objectName); - FileUploadResult fileUploadResult = new FileUploadResult(); - fileUploadResult.setName(objectName); - fileUploadResult.setStatus("removed"); - fileUploadResult.setResponse("success"); - return fileUploadResult; - } - - /** - * @author lastwhisper - * @desc 下载文件 - * 文档链接 https://help.aliyun.com/document_detail/84823.html?spm=a2c4g.11186623.2.7.37836e84ZIuZaC#concept-84823-zh - * @email gaojun56@163.com - */ - public void exportOssFile(OutputStream os, String objectName) throws IOException { - // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。 - OSSObject ossObject = ossClient.getObject(aliyunConfig.getBucketName(), objectName); - // 读取文件内容。 - BufferedInputStream in = new BufferedInputStream(ossObject.getObjectContent()); - BufferedOutputStream out = new BufferedOutputStream(os); - byte[] buffer = new byte[1024]; - int lenght = 0; - while ((lenght = in.read(buffer)) != -1) { - out.write(buffer, 0, lenght); - } - if (out != null) { - out.flush(); - out.close(); - } - if (in != null) { - in.close(); - } - } -} - -``` -### 4.2.3 controller - -controller进行接收用户请求 - -```java -package com.example.ossdemo.controller; - -import com.aliyun.oss.model.OSSObjectSummary; -import com.example.ossdemo.service.FileUploadService; -import com.example.ossdemo.vo.FileUploadResult; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.multipart.MultipartFile; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.InputStream; -import java.net.URLEncoder; -import java.util.List; - -/** - * @author lastwhisper - * @desc - * @email gaojun56@163.com - */ -@Controller -public class FileUploadController { - @Autowired - private FileUploadService fileUploadService; - - /** - * @author lastwhisper - * @desc 文件上传到oss - * @return FileUploadResult - * @Param uploadFile - */ - @RequestMapping("file/upload") - @ResponseBody - public FileUploadResult upload(@RequestParam("file") MultipartFile uploadFile) - throws Exception { - return this.fileUploadService.upload(uploadFile); - } - - /** - * @return FileUploadResult - * @desc 根据文件名删除oss上的文件 - * http://localhost:8080/file/delete?fileName=images/2019/04/28/1556429167175766.jpg - * @author lastwhisper - * @Param objectName - */ - @RequestMapping("file/delete") - @ResponseBody - public FileUploadResult delete(@RequestParam("fileName") String objectName) - throws Exception { - return this.fileUploadService.delete(objectName); - } - - /** - * @author lastwhisper - * @desc 查询oss上的所有文件 - * http://localhost:8080/file/list - * @return List - * @Param - */ - @RequestMapping("file/list") - @ResponseBody - public List list() - throws Exception { - return this.fileUploadService.list(); - } - - /** - * @author lastwhisper - * @desc 根据文件名下载oss上的文件 - * @return - * @Param objectName - */ - @RequestMapping("file/download") - @ResponseBody - public void download(@RequestParam("fileName") String objectName, HttpServletResponse response) throws IOException { - //通知浏览器以附件形式下载 - response.setHeader("Content-Disposition", - "attachment;filename=" + new String(objectName.getBytes(), "ISO-8859-1")); - this.fileUploadService.exportOssFile(response.getOutputStream(),objectName); - } -} -``` - - -# 5. 前端页面编写与测试 - -## 5.1 文件上传页面 - -使用ajax异步文件上传到后端对接的OSS上。 - -```html - - - - - - oss文件上传 - - - - -
   -    -
     -
-
-
- - -``` - -**效果展示:** - -![ajax文件上传到OSS](https://upload-images.jianshu.io/upload_images/5336514-9ce7586f3cff4448.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -![ajax文件上传到OSS](https://upload-images.jianshu.io/upload_images/5336514-8979815659db74f7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -![ajax文件上传到OSS成功](https://upload-images.jianshu.io/upload_images/5336514-74764aaef98c5634.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -## 5.2 文件管理页面 - -```html - - - - - oss文件管理 - - - - -单击下载oss上的图片、双击删除oss上的图片
-
- -
- - -``` - -**效果展示:** - -刚才上传了一张照片,可以立马看到 - -![文件管理](https://upload-images.jianshu.io/upload_images/5336514-62efcdedbb874287.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -单击页面即可下载图片 - -![image.png](https://upload-images.jianshu.io/upload_images/5336514-fa9b54c11e9a7ba4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -双击即可删除图片: - -![删除图片](https://upload-images.jianshu.io/upload_images/5336514-a69777b462e3b919.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -![删除图片](https://upload-images.jianshu.io/upload_images/5336514-670a3aa6e65cfb9e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) \ No newline at end of file diff --git "a/springboot-integration-examples/\345\257\271\345\272\224\347\254\224\350\256\260/SpringBoot-wx.md" "b/springboot-integration-examples/\345\257\271\345\272\224\347\254\224\350\256\260/SpringBoot-wx.md" deleted file mode 100644 index b129c456..00000000 --- "a/springboot-integration-examples/\345\257\271\345\272\224\347\254\224\350\256\260/SpringBoot-wx.md" +++ /dev/null @@ -1,901 +0,0 @@ -> **该项目源码地址:https://github.com/ggb2312/springboot-integration-examples(其中包含SpringBoot和其他常用技术的整合,配套源码以及笔记。基于最新的 SpringBoot2.1+,欢迎各位 Star)** - -# 1. 开发前准备 - -## 1.1 前置知识 -- java基础 -- SpringBoot简单基础知识 - -## 1.2 环境参数 -- 开发工具:IDEA -- 基础环境:Maven+JDK8 -- 所用技术:SpringBoot、lombok、mybatisplus、微信小程序 -- SpringBoot版本:2.1.4 - -## 1.3 涉及知识点 -- 微信小程序登录流程 - -# 2. 微信小程序登录流程 -微信小程序登录流程涉及到三个角色:**小程序、开发者服务器、微信服务器** - -三者交互步骤如下: - ->第一步:`小程序`通过wx.login()获取code。 ->第二步:`小程序`通过wx.request()发送code到开发者服务器。 ->第三步:`开发者服务器`接收小程序发送的code,并携带appid、appsecret(这两个需要到微信小程序后台查看)、code发送到`微信服务器`。 ->第四步:`微信服务器`接收开发者服务器发送的appid、appsecret、code进行校验。校验通过后向`开发者服务器`发送session_key、openid。 ->第五步:`开发者服务器`自己生成一个skey(自定义登录状态)与openid、session_key进行关联,并存到数据库中(mysql、redis等)。 ->第六步:`开发者服务器`返回生成skey(自定义登录状态)到小程序。 ->第七步:`小程序`存储skey(自定义登录状态)到本地。 ->第八步:`小程序`通过wx.request()发起业务请求到`开发者服务器`,同时携带skey(自定义登录状态)。 ->第九步:`开发者服务器`接收`小程序`发送的skey(自定义登录状态),查询skey在数据库中是否有对应的openid、session_key。 ->第十步:`开发者服务器`返回业务数据到`小程序`。 - - - -登录流程时序如下: - - - -![登录流程时序](https://upload-images.jianshu.io/upload_images/5336514-96d351a21eb8cbad.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - - - -本文实现了前七个步骤,因为微信小程序登录的核心就是前七个步骤。 - - - ->第一步:`小程序`通过wx.login()获取code。 ->第二步:`小程序`通过wx.request()发送code到开发者服务器。 ->第三步:`开发者服务器`接收小程序发送的code,并携带appid、appsecret(这两个需要到微信小程序后台查看)、code发送到`微信服务器。` ->第四步:`微信服务器`接收开发者服务器发送的appid、appsecret、code进行校验。校验通过后向`开发者服务器`发送session_key、openid。 ->第五步:`开发者服务器`自己生成一个skey(自定义登录状态)与openid、session_key进行关联,并存到数据库中(mysql、redis等)。 ->第六步:`开发者服务器`返回生成skey(自定义登录状态)到小程序。 ->第七步:`小程序`存储skey(自定义登录状态)到本地。 - - - -![本文介绍的流程](https://upload-images.jianshu.io/upload_images/5336514-fe6e3cb43c775db0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - - - -# 3. 开发者服务器 - -项目结构: - -![项目结构](https://upload-images.jianshu.io/upload_images/5336514-e0568415537890ba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -## 3.1 初始配置 - -(1)pom.xml配置 - -```xml - - - org.apache.httpcomponents - httpclient - 4.5.2 - - - - org.bouncycastle - bcprov-jdk16 - 1.46 - - - - - - org.apache.shiro - shiro-core - 1.4.0 - - - slf4j-api - org.slf4j - - - - - - - com.alibaba - fastjson - 1.2.47 - - - - - org.projectlombok - lombok - true - - - - com.baomidou - mybatis-plus-boot-starter - 3.1.1 - - - - mysql - mysql-connector-java - 5.1.47 - -``` - -(2)application.properties - -```properties -spring.application.name = lastwhisper-wxlogin -spring.datasource.driver-class-name=com.mysql.jdbc.Driver -spring.datasource.url=jdbc:mysql://127.0.0.1:3306/wxlogin?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false -spring.datasource.username=root -spring.datasource.password=root -``` - -## 3.2 小程序用户表 - -创建一个用户表存储用户的openid等数据。 - -```sql -CREATE TABLE `user` ( - `open_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'open_id', - `skey` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'skey', - `create_time` timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `last_visit_time` timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后登录时间', - `session_key` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'session_key', - `city` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '市', - `province` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '省', - `country` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '国', - `avatar_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '头像', - `gender` tinyint(11) NULL DEFAULT NULL COMMENT '性别', - `nick_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '网名', - PRIMARY KEY (`open_id`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '微信用户信息' ROW_FORMAT = Dynamic; - -``` - -## 3.3 pojo - - - -```java -package cn.lastwhisper.springbootwx.pojo; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.util.Date; - -/** - * @author lastwhisper - * @desc - * @email gaojun56@163.com - */ -@Data -@TableName("user") -public class User { - private static final long serialVersionUID = 1L; - /** - * open_id - */ - @TableId(value = "open_id",type = IdType.INPUT) - private String openId; - /** - * skey - */ - private String skey; - /** - * 创建时间 - */ - @TableField("create_time") - @DateTimeFormat(pattern = "yyyy-MM-dd") - private Date createTime; - /** - * 最后登录时间 - */ - @TableField("last_visit_time") - @DateTimeFormat(pattern = "yyyy-MM-dd") - private Date lastVisitTime; - /** - * session_key - */ - @TableField("session_key") - private String sessionKey; - /** - * 市 - */ - @TableField("city") - private String city; - /** - * 省 - */ - @TableField("province") - private String province; - /** - * 国 - */ - @TableField("country") - private String country; - /** - * 头像 - */ - @TableField("avatar_url") - private String avatarUrl; - /** - * 性别 - */ - @TableField("gender") - private Integer gender; - /** - * 网名 - */ - @TableField("nick_name") - private String nickName; - -} - -``` - -## 3.4 common - -封装一些工具类 - -(1)GlobalResult - -```java -package cn.lastwhisper.springbootwx.common; - -/** - * @Description: 自定义响应数据结构 - * 这个类是提供给门户,ios,安卓,微信商城用的 - * 门户接受此类数据后需要使用本类的方法转换成对于的数据类型格式(类,或者list) - * 其他自行处理 - * 200:表示成功 - * 500:表示错误,错误信息在msg字段中 - * 501:bean验证错误,不管多少个错误都以map形式返回 - * 502:拦截器拦截到用户token出错 - * 555:异常抛出信息 - */ -public class GlobalResult { - - // 响应业务状态 - private Integer status; - - // 响应消息 - private String msg; - - // 响应中的数据 - private Object data; - - private String ok; // 不使用 - - public static GlobalResult build(Integer status, String msg, Object data) { - return new GlobalResult(status, msg, data); - } - - public static GlobalResult ok(Object data) { - return new GlobalResult(data); - } - - public static GlobalResult ok() { - return new GlobalResult(null); - } - - public static GlobalResult errorMsg(String msg) { - return new GlobalResult(500, msg, null); - } - - public static GlobalResult errorMap(Object data) { - return new GlobalResult(501, "error", data); - } - - public static GlobalResult errorTokenMsg(String msg) { - return new GlobalResult(502, msg, null); - } - - public static GlobalResult errorException(String msg) { - return new GlobalResult(555, msg, null); - } - - public GlobalResult() { - - } - - public GlobalResult(Integer status, String msg, Object data) { - this.status = status; - this.msg = msg; - this.data = data; - } - - public GlobalResult(Object data) { - this.status = 200; - this.msg = "OK"; - this.data = data; - } - - public Boolean isOK() { - return this.status == 200; - } - - public Integer getStatus() { - return status; - } - - public void setStatus(Integer status) { - this.status = status; - } - - public String getMsg() { - return msg; - } - - public void setMsg(String msg) { - this.msg = msg; - } - - public Object getData() { - return data; - } - - public void setData(Object data) { - this.data = data; - } - - public String getOk() { - return ok; - } - - public void setOk(String ok) { - this.ok = ok; - } - -} -``` - -(2)HttpClientUtil - -```java -package cn.lastwhisper.springbootwx.common; - -import org.apache.http.NameValuePair; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.util.EntityUtils; - -import java.io.IOException; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class HttpClientUtil { - - public static String doGet(String url, Map param) { - - // 创建Httpclient对象 - CloseableHttpClient httpclient = HttpClients.createDefault(); - - String resultString = ""; - CloseableHttpResponse response = null; - try { - // 创建uri - URIBuilder builder = new URIBuilder(url); - if (param != null) { - for (String key : param.keySet()) { - builder.addParameter(key, param.get(key)); - } - } - URI uri = builder.build(); - - // 创建http GET请求 - HttpGet httpGet = new HttpGet(uri); - - // 执行请求 - response = httpclient.execute(httpGet); - // 判断返回状态是否为200 - if (response.getStatusLine().getStatusCode() == 200) { - resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); - } - } catch (Exception e) { - e.printStackTrace(); - } finally { - try { - if (response != null) { - response.close(); - } - httpclient.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - return resultString; - } - - public static String doGet(String url) { - return doGet(url, null); - } - - public static String doPost(String url, Map param) { - // 创建Httpclient对象 - CloseableHttpClient httpClient = HttpClients.createDefault(); - CloseableHttpResponse response = null; - String resultString = ""; - try { - // 创建Http Post请求 - HttpPost httpPost = new HttpPost(url); - // 创建参数列表 - if (param != null) { - List paramList = new ArrayList<>(); - for (String key : param.keySet()) { - paramList.add(new BasicNameValuePair(key, param.get(key))); - } - // 模拟表单 - UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList); - httpPost.setEntity(entity); - } - // 执行http请求 - response = httpClient.execute(httpPost); - resultString = EntityUtils.toString(response.getEntity(), "utf-8"); - } catch (Exception e) { - e.printStackTrace(); - } finally { - try { - response.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - return resultString; - } - - public static String doPost(String url) { - return doPost(url, null); - } - - public static String doPostJson(String url, String json) { - // 创建Httpclient对象 - CloseableHttpClient httpClient = HttpClients.createDefault(); - CloseableHttpResponse response = null; - String resultString = ""; - try { - // 创建Http Post请求 - HttpPost httpPost = new HttpPost(url); - // 创建请求内容 - StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); - httpPost.setEntity(entity); - // 执行http请求 - response = httpClient.execute(httpPost); - resultString = EntityUtils.toString(response.getEntity(), "utf-8"); - } catch (Exception e) { - e.printStackTrace(); - } finally { - try { - response.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - return resultString; - } -} -``` - -(3)WechatUtil - -```java -package cn.lastwhisper.springbootwx.common;/** - * Create by eval on 2019/3/20 - */ - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import org.apache.shiro.codec.Base64; -import org.bouncycastle.jce.provider.BouncyCastleProvider; - -import javax.crypto.Cipher; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; -import java.security.AlgorithmParameters; -import java.security.Security; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -/** - * @ClassName WechatUtil - * @Description TODO - * @Author eval - * @Date 9:44 2019/3/20 - * @Version 1.0 - */ -public class WechatUtil { - public static JSONObject getSessionKeyOrOpenId(String code) { - String requestUrl = "https://api.weixin.qq.com/sns/jscode2session"; - Map requestUrlParam = new HashMap<>(); - // https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN - //小程序appId - requestUrlParam.put("appid", "小程序appId"); - //小程序secret - requestUrlParam.put("secret", "小程序secret"); - //小程序端返回的code - requestUrlParam.put("js_code", code); - //默认参数 - requestUrlParam.put("grant_type", "authorization_code"); - //发送post请求读取调用微信接口获取openid用户唯一标识 - JSONObject jsonObject = JSON.parseObject(HttpClientUtil.doPost(requestUrl, requestUrlParam)); - return jsonObject; - } - - public static JSONObject getUserInfo(String encryptedData, String sessionKey, String iv) { - // 被加密的数据 - byte[] dataByte = Base64.decode(encryptedData); - // 加密秘钥 - byte[] keyByte = Base64.decode(sessionKey); - // 偏移量 - byte[] ivByte = Base64.decode(iv); - try { - // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要 - int base = 16; - if (keyByte.length % base != 0) { - int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0); - byte[] temp = new byte[groups * base]; - Arrays.fill(temp, (byte) 0); - System.arraycopy(keyByte, 0, temp, 0, keyByte.length); - keyByte = temp; - } - // 初始化 - Security.addProvider(new BouncyCastleProvider()); - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC"); - SecretKeySpec spec = new SecretKeySpec(keyByte, "AES"); - AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES"); - parameters.init(new IvParameterSpec(ivByte)); - cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化 - byte[] resultByte = cipher.doFinal(dataByte); - if (null != resultByte && resultByte.length > 0) { - String result = new String(resultByte, "UTF-8"); - return JSON.parseObject(result); - } - } catch (Exception e) { - } - return null; - } -} - -``` - -## 3.5 mapper - - - -```java -package cn.lastwhisper.springbootwx.mapper; - -import cn.lastwhisper.springbootwx.pojo.User; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; - -/** - * @desc - * - * @author lastwhisper - * @email gaojun56@163.com - */ -public interface UserMapper extends BaseMapper { -} - -``` - -配置SpringBoot扫描mapper - -```java -package cn.lastwhisper.springbootwx; - -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -@MapperScan("cn.lastwhisper.springbootwx.mapper") //设置mapper接口的扫描包 -@SpringBootApplication -public class SpringbootwxApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringbootwxApplication.class, args); - } - -} - -``` - -## 3.6 controller - -用于接收用户请求,校验签名,并生成skey,存储skey、openid等数据 - -```java -package cn.lastwhisper.springbootwx.controller; - -import cn.lastwhisper.springbootwx.common.GlobalResult; -import cn.lastwhisper.springbootwx.mapper.UserMapper; -import cn.lastwhisper.springbootwx.pojo.User; -import cn.lastwhisper.springbootwx.common.WechatUtil; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import org.apache.commons.codec.digest.DigestUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; - -import java.util.Date; -import java.util.UUID; - -/** - * @author lastwhisper - * @desc - * @email gaojun56@163.com - */ -@Controller -public class UserController { - - @Autowired - private UserMapper userMapper; - - /** - * 微信用户登录详情 - */ - @PostMapping("wx/login") - @ResponseBody - public GlobalResult user_login(@RequestParam(value = "code", required = false) String code, - @RequestParam(value = "rawData", required = false) String rawData, - @RequestParam(value = "signature", required = false) String signature, - @RequestParam(value = "encrypteData", required = false) String encrypteData, - @RequestParam(value = "iv", required = false) String iv) { - // 用户非敏感信息:rawData - // 签名:signature - JSONObject rawDataJson = JSON.parseObject(rawData); - // 1.接收小程序发送的code - // 2.开发者服务器 登录凭证校验接口 appi + appsecret + code - JSONObject SessionKeyOpenId = WechatUtil.getSessionKeyOrOpenId(code); - // 3.接收微信接口服务 获取返回的参数 - String openid = SessionKeyOpenId.getString("openid"); - String sessionKey = SessionKeyOpenId.getString("session_key"); - - // 4.校验签名 小程序发送的签名signature与服务器端生成的签名signature2 = sha1(rawData + sessionKey) - String signature2 = DigestUtils.sha1Hex(rawData + sessionKey); - if (!signature.equals(signature2)) { - return GlobalResult.build(500, "签名校验失败", null); - } - // 5.根据返回的User实体类,判断用户是否是新用户,是的话,将用户信息存到数据库;不是的话,更新最新登录时间 - User user = this.userMapper.selectById(openid); - // uuid生成唯一key,用于维护微信小程序用户与服务端的会话 - String skey = UUID.randomUUID().toString(); - if (user == null) { - // 用户信息入库 - String nickName = rawDataJson.getString("nickName"); - String avatarUrl = rawDataJson.getString("avatarUrl"); - String gender = rawDataJson.getString("gender"); - String city = rawDataJson.getString("city"); - String country = rawDataJson.getString("country"); - String province = rawDataJson.getString("province"); - - user = new User(); - user.setOpenId(openid); - user.setSkey(skey); - user.setCreateTime(new Date()); - user.setLastVisitTime(new Date()); - user.setSessionKey(sessionKey); - user.setCity(city); - user.setProvince(province); - user.setCountry(country); - user.setAvatarUrl(avatarUrl); - user.setGender(Integer.parseInt(gender)); - user.setNickName(nickName); - - this.userMapper.insert(user); - } else { - // 已存在,更新用户登录时间 - user.setLastVisitTime(new Date()); - // 重新设置会话skey - user.setSkey(skey); - this.userMapper.updateById(user); - } - //encrypteData比rowData多了appid和openid - //JSONObject userInfo = WechatUtil.getUserInfo(encrypteData, sessionKey, iv); - //6. 把新的skey返回给小程序 - GlobalResult result = GlobalResult.build(200, null, skey); - return result; - } -} - -``` - - -# 4. 微信小程序 - -项目结构: - -![项目结构](https://upload-images.jianshu.io/upload_images/5336514-5d79f5e8685c1451.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -## 4.1 初始配置 - -![初始配置](https://upload-images.jianshu.io/upload_images/5336514-f3c3d1b092e2bc43.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - - - -## 4.2 me.wxml - -```html - - - - - - - - - -``` - -## 4.3 me.wxss - -无 - -## 4.4 me.json - -```javascript -{ - -} -``` - - - -## 4.5 me.js - -```javascript -// pages/me/me.js -Page({ - - /** - * 页面的初始数据 - */ - data: { - hasUserInfo: false, - userInfo: null - }, - - onLoad: function() { - // 页面加载时使用用户授权逻辑,弹出确认的框 - this.userAuthorized() - }, - - userAuthorized() { - wx.getSetting({ - success: data => { - if (data.authSetting['scope.userInfo']) { - wx.getUserInfo({ - success: data => { - this.setData({ - hasUserInfo: true, - userInfo: data.userInfo - }) - } - }) - } else { - this.setData({ - hasUserInfo: false - }) - } - } - }) - }, - - onGetUserInfo(e) { - const userInfo = e.detail.userInfo - if (userInfo) { - // 1. 小程序通过wx.login()获取code - wx.login({ - success: function(login_res) { - //获取用户信息 - wx.getUserInfo({ - success: function(info_res) { - // 2. 小程序通过wx.request()发送code到开发者服务器 - wx.request({ - url: 'http://localhost:8080/wx/login', - method: 'POST', - header: { - 'content-type': 'application/x-www-form-urlencoded' - }, - data: { - code: login_res.code, //临时登录凭证 - rawData: info_res.rawData, //用户非敏感信息 - signature: info_res.signature, //签名 - encrypteData: info_res.encryptedData, //用户敏感信息 - iv: info_res.iv //解密算法的向量 - }, - success: function(res) { - if (res.data.status == 200) { - // 7.小程序存储skey(自定义登录状态)到本地 - wx.setStorageSync('userInfo', userInfo); - wx.setStorageSync('skey', res.data.data); - } else{ - console.log('服务器异常'); - } - }, - fail: function(error) { - //调用服务端登录接口失败 - console.log(error); - } - }) - } - }) - } - }) - this.setData({ - hasUserInfo: true, - userInfo: userInfo - }) - } - } - -}) -``` - -## 4.6 app.json - -设置app.json的pages - -```javascript -{ - "pages":[ - "pages/me/me" - ], - "window":{ - "backgroundTextStyle":"light", - "navigationBarBackgroundColor": "#fff", - "navigationBarTitleText": "WeChat", - "navigationBarTextStyle":"black" - }, - "debug":true -} -``` - - - -# 5. 测试 - -启动开发者服务器,启动SpringBoot的main方法。 - -打开微信小程序开发者工具 - -![清空缓存](https://upload-images.jianshu.io/upload_images/5336514-6390ebbe06fd2966.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -点击授权登录,并允许。 - -![授权登录](https://upload-images.jianshu.io/upload_images/5336514-f91936c2c2506ac1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -登录成功 - -![登录成功](https://upload-images.jianshu.io/upload_images/5336514-b2cbb72779e75f98.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -查看数据库,openid、skey以及用户信息等存入了数据库。 - -![用户信息入库](https://upload-images.jianshu.io/upload_images/5336514-640be1be797a4121.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -同时微信小程序将skey等存储到本地,每次发起请求时都可以携带上。 - -![skey存储本地](https://upload-images.jianshu.io/upload_images/5336514-c37c3231a752219c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) \ No newline at end of file diff --git a/tool/pom.xml b/tool/pom.xml new file mode 100644 index 00000000..adc9b361 --- /dev/null +++ b/tool/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + cn.cunchang + tool + 1.0-SNAPSHOT + + + + + net.java.dev.jna + jna-platform + 5.5.0 + + + + junit + junit + 4.12 + + + + + + \ No newline at end of file diff --git a/tool/src/main/java/cn/cunchang/DeleteFile.java b/tool/src/main/java/cn/cunchang/DeleteFile.java new file mode 100644 index 00000000..94a55139 --- /dev/null +++ b/tool/src/main/java/cn/cunchang/DeleteFile.java @@ -0,0 +1,165 @@ +package cn.cunchang; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Properties; + +/** + * 删除指定文件夹下的 + * + * @author cunchang + * @date 2019/11/22 + */ +public class DeleteFile { + + /** + * 可能的值: + * /Users/cunchang/code/GitRepository + */ + private static HashSet targetDirs; + + /** + * 可能的值: + * .idea + * bin + */ + private static HashSet deleteDirs; + + /** + * 可能的值: + * .war + * .iml + * .jar + */ + private static HashSet deleteFiles; + + private static long count; + + public static void main(String[] args) throws IOException { + init(args); + check(); + delete(); + after(); +// File file = new File("/Users/cunchang/workspace/java/pdf-mark/target/classes/cn/cunchang/itext/test2/ReplaceRegion.class"); +// System.out.println(file.delete()); + } + + private static void init(String[] args) throws IOException { + targetDirs = new HashSet<>(); + deleteDirs = new HashSet<>(); + deleteFiles = new HashSet<>(); + + String configPath = "/config.properties"; + + if (args != null && args.length > 0) { + configPath = args[0]; + } + InputStream inputStream = DeleteFile.class.getResourceAsStream(configPath); + + Properties prop = new Properties(); + prop.load(inputStream); + + String targetDirsStr = prop.getProperty("targetDirs"); + String deleteDirsStr = prop.getProperty("deleteDirs"); + String deleteFilesStr = prop.getProperty("deleteFiles"); + String[] targetDirArr = targetDirsStr.split(";"); + String[] deleteDirsArr = deleteDirsStr.split(";"); + String[] deleteFilesArr = deleteFilesStr.split(";"); + System.out.println("targetDirs:" + Arrays.toString(targetDirArr)); + System.out.println("deleteDirs:" + Arrays.toString(deleteDirsArr)); + System.out.println("deleteFiles:" + Arrays.toString(deleteFilesArr)); + targetDirs.addAll(Arrays.asList(targetDirArr)); + deleteDirs.addAll(Arrays.asList(deleteDirsArr)); + deleteFiles.addAll(Arrays.asList(deleteFilesArr)); + } + + private static void check() { + if (targetDirs.isEmpty()) { + throw new IllegalArgumentException("targetDirs not empty"); + } + if (deleteDirs.isEmpty()) { + throw new IllegalArgumentException("deleteDirs not empty"); + } + if (deleteFiles.isEmpty()) { + throw new IllegalArgumentException("deleteFiles not empty"); + } + } + + private static void after() { + System.out.println("delete count:" + count); + } + + private static void delete() { + for (String targetDir : targetDirs) { + System.out.println("DeleteFile run,target==>" + targetDir); + recursionDelDir(new File(targetDir)); + } + } + + + /** + * 递归找到deleteDirs目录和deleteFiles文件 + * deleteDirs目录递归删除其下所有文件 + * deleteFiles文件直接删除 + */ + public static void recursionDelDir(File file) { + File[] subFiles = file.listFiles(); + if (subFiles == null||subFiles.length == 0) { + return; + } + for (File subFile : subFiles) { + if (subFile.isDirectory()) { + // 删除指定文件夹 + if (deleteDirs.contains(subFile.getName())) { + recursionDelFile(subFile); + } + } else { + // 删除指定后缀文件 + String fileName = subFile.getName(); + int lastIndex = fileName.lastIndexOf("."); + if (lastIndex == -1) { + System.out.println("跳过文件==>" +subFile.getAbsolutePath()); + continue; + } + fileName = fileName.substring(0, lastIndex); + if (deleteFiles.contains(fileName)) { + boolean deleteFlag = subFile.delete(); + System.out.println("delete file==>" + subFile.getAbsolutePath() + " :" + (deleteFlag ? "成功" : "失败")); + count++; + } + } + recursionDelDir(subFile); + } + } + + + /** + * 递归删除file目录下的文件 + */ + public static void recursionDelFile(File file) { + if (file == null) { + return; + } + File[] subFiles = file.listFiles(); + if (subFiles == null) { + return; + } + for (File subFile : subFiles) { + if (subFile.isDirectory()) { + recursionDelFile(subFile); + } else { + boolean deleteFlag = subFile.delete(); + System.out.println("delete file==>" + subFile.getAbsolutePath() + " :" + (deleteFlag ? "成功" : "失败")); + count++; + } + } + // 子目录都删除了,删除当前目录 + boolean deleteFlag = file.delete(); + System.out.println("delete dir==>" + file.getAbsolutePath() + " :" + (deleteFlag ? "成功" : "失败")); + count++; + } + +} diff --git a/tool/src/main/java/cn/cunchang/DeleteFileToTrash.java b/tool/src/main/java/cn/cunchang/DeleteFileToTrash.java new file mode 100644 index 00000000..9cf82a25 --- /dev/null +++ b/tool/src/main/java/cn/cunchang/DeleteFileToTrash.java @@ -0,0 +1,32 @@ +package cn.cunchang; + +import com.sun.jna.platform.FileUtils; +import com.sun.jna.platform.win32.W32FileUtils; + +import java.io.File; +import java.io.IOException; + +/** + * 删除指定文件夹 + * + * @author cunchang + * @date 2020/03/15 + */ +public class DeleteFileToTrash { + + // https://blog.csdn.net/Felix_Dreammaker/article/details/79180471 + public static void main(String[] args) { + + FileUtils fileUtils = W32FileUtils.getInstance(); + boolean flag = fileUtils.hasTrash(); + if (flag) { + try { + fileUtils.moveToTrash(new File[]{new File("C:\\Users\\Administrator\\Desktop\\xxxxx.bmp")}); + } catch (IOException e) { + e.printStackTrace(); + } + } + + } + +} diff --git a/tool/src/main/java/cn/cunchang/KillServer.java b/tool/src/main/java/cn/cunchang/KillServer.java new file mode 100644 index 00000000..251ea2b5 --- /dev/null +++ b/tool/src/main/java/cn/cunchang/KillServer.java @@ -0,0 +1,170 @@ +package cn.cunchang; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class KillServer { + private Set ports; + + // java KillServer 8080 8081 8082 8083 + public static void main(String[] args) throws InterruptedException { + // String os = System.getProperty("os.name"); + System.out.println("请输入要杀掉的" + System.getProperty("os.name") + "进程的端口号,如果有多个,则以空格相隔"); + System.out.println("Please input kill port"); + + Set ports = new HashSet<>(); + for (String port : args) { + try { + ports.add(Integer.parseInt(port)); + } catch (Exception e) { + System.out.println("错误的端口号,请输入一个或者多个端口,以英文逗号隔开"); + try { + Thread.sleep(5000); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + System.exit(0); + } + } + + KillServer kill = new KillServer(); + kill.ports = ports; + System.out.println("need kill " + ports.size() + " num"); + for (Integer pid : ports) { + kill.start(pid); + } + System.out.println("清理完毕,程序即将退出"); + System.out.println("SUCCESS"); + Thread.sleep(5000); + System.exit(0); + + } + + public void start(int port) { + Runtime runtime = Runtime.getRuntime(); + try { + //查找进程号 + Process p = runtime.exec("cmd /c netstat -ano | findstr \"" + port + "\""); + InputStream inputStream = p.getInputStream(); + List read = read(inputStream, StandardCharsets.UTF_8); + if (read.size() == 0) { + System.out.println("找不到该端口的进程"); + try { + Thread.sleep(6000); + System.exit(0); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } else { + for (String string : read) { + System.out.println(string); + } + System.out.println("找到" + read.size() + "个进程,正在准备清理"); + kill(read); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 验证此行是否为指定的端口,因为 findstr命令会是把包含的找出来,例如查找80端口,但是会把8099查找出来 + * @param str + * @return + */ + private boolean validPort(String str) { + Pattern pattern = Pattern.compile("^ *[a-zA-Z]+ +\\S+"); + Matcher matcher = pattern.matcher(str); + + matcher.find(); + String find = matcher.group(); + int spstart = find.lastIndexOf(":"); + find = find.substring(spstart + 1); + + int port = 0; + try { + port = Integer.parseInt(find); + } catch (NumberFormatException e) { + System.out.println("查找到错误的端口:" + find); + return false; + } + if (this.ports.contains(port)) { + return true; + } else { + return false; + } + } + + /** + * 更换为一个Set,去掉重复的pid值 + * @param data + */ + public void kill(List data) { + Set pids = new HashSet<>(); + for (String line : data) { + int offset = line.lastIndexOf(" "); + String spid = line.substring(offset); + spid = spid.replaceAll(" ", ""); + int pid = 0; + try { + pid = Integer.parseInt(spid); + } catch (NumberFormatException e) { + System.out.println("获取的进程号错误:" + spid); + } + pids.add(pid); + } + killWithPid(pids); + } + + /** + * 一次性杀除所有的端口 + * @param pids + */ + public void killWithPid(Set pids) { + for (Integer pid : pids) { + try { + Process process = Runtime.getRuntime().exec("taskkill /F /pid " + pid + ""); + InputStream inputStream = process.getInputStream(); + String txt = readTxt(inputStream, "GBK"); + System.out.println(txt); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private List read(InputStream in, Charset charset) throws IOException { + List data = new ArrayList<>(); + BufferedReader reader = new BufferedReader(new InputStreamReader(in, charset)); + String line; + while ((line = reader.readLine()) != null) { + boolean validPort = validPort(line); + if (validPort) { + data.add(line); + } + } + reader.close(); + return data; + } + + public String readTxt(InputStream in, String charset) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(in, charset)); + StringBuilder sb = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + sb.append(line); + } + reader.close(); + return sb.toString(); + } +} \ No newline at end of file diff --git a/tool/src/main/resources/config.properties b/tool/src/main/resources/config.properties new file mode 100644 index 00000000..437a46ac --- /dev/null +++ b/tool/src/main/resources/config.properties @@ -0,0 +1,3 @@ +targetDirs=/Users/cunchang/workspace +deleteDirs=.idea;target;out +deleteFiles=.iml