summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryinjiangyi <[email protected]>2020-11-15 13:15:04 +0800
committeryinjiangyi <[email protected]>2020-11-15 13:15:04 +0800
commit5f7c6af5b61657f01b16fdb6c8a7c993cd30e8b7 (patch)
tree38867c0dfea4b4e27bcacb6b289b5ba74bf7790b
parent5b73080eb2a4a84d1ff867a3da9fbdf780a36369 (diff)
commit v2
-rw-r--r--README.md37
-rw-r--r--pom.xml47
-rw-r--r--src/main/java/com/example/ua/analyser/UaAnalyser.java17
-rw-r--r--src/main/java/com/example/ua/analyser/enums/RegexFeatureEnum.java42
-rw-r--r--src/main/java/com/example/ua/analyser/enums/StandardUaList.java38
-rw-r--r--src/main/java/com/example/ua/analyser/enums/UserInfo.java175
-rw-r--r--src/main/java/com/example/ua/analyser/impl/AndroidAnalyser.java101
-rw-r--r--src/main/java/com/example/ua/analyser/impl/AppleAnalyser.java129
-rw-r--r--src/main/java/com/example/ua/analyser/impl/TerminalClassify.java57
-rw-r--r--src/main/java/com/example/ua/analyser/impl/UaAnalyserImpl.java77
-rw-r--r--src/main/java/com/example/ua/analyser/impl/WindowsAnalyser.java73
-rw-r--r--src/main/java/com/example/ua/config/ApplicationConfig.java26
-rw-r--r--src/main/java/com/example/ua/dao/QueryMariaDb.java20
-rw-r--r--src/main/java/com/example/ua/dao/impl/QueryMariaDbImpl.java61
-rw-r--r--src/main/java/com/example/ua/utils/ConfigUtils.java43
-rw-r--r--src/main/java/com/example/ua/utils/MariaDBConnect.java40
-rw-r--r--src/main/resources/application.properties12
-rw-r--r--src/main/resources/log4j.properties26
-rw-r--r--src/test/java/UaAnalyserTest.java34
19 files changed, 1055 insertions, 0 deletions
diff --git a/README.md b/README.md
index a7444c4..9c2c932 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,39 @@
# UaAnalyser
+根据user-agent分析ip对应的终端个数情况及相关信息
+
+## Input
+```
+String inputString = "69765" + "\t" + // userId
+ "192.168.50.13" + "\t" + // ip
+ "1765433230" + "\t" + // timeStamp
+ "'Dalvik/1.6.0 (Linux; U; Android 4.0.3; LG-E612f Build/IML74K)':4, " +
+ "'Dalvik/2.1.0 (Linux; U; Android 10; TNYAL00 Build/HUAWEITNY-AL00)':4" +
+ "'Mozilla/5.0 (iPhone; CPU iPhone OS 11_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15G77 === iOS/11.4.1 Model/iPhone10,1 BundleID/com.xunmeng.pinduoduo AppVersion/5.32.0 AppBuild/2009212125 pversion/1221 cURL/7.48.0':5" +
+ "'com.apple.trustd/1.0':1" +
+ "'server-bag [iPhone OS,13.6.1,17G80,iPhone10,2]':1" +
+ "'Microsoft-CryptoAPI/10.0':1" +
+ "'Mozilla/5.0 (Linux; Android 10; SM-G9600) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.110 Mobile Safari/537.36':10" +
+ "'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36':1"; // uaCntInfo
+```
+
+### Output
+```
+// 相关字段:
+// osCnt, browserCnt, deviceCnt, terminalCnt, terminalCatCnt,
+// osList, browserList, deviceList, terminalList, terminalCatList
+userInfo.getTerminalList(); // 获取terminalList字段值
+```
+* ``osCnt`` -操作系统数
+* ``browserCnt``-浏览器数
+* ``deviceCnt``-设备名数(如 "LG E612F")
+* ``terminalCnt``-终端三元组标识数(os/browser/device)
+* ``terminalCatCnt``-终端类别数(类别包括windows, apple, android三种)
+
+
+## Usage
+
+```
+UaAnalyser uaAnalyser = new UaAnalyserImpl();
+UserInfo userInfo = uaAnalyser.getUserinfo(inputString);
+```
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..e948e2f
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.example</groupId>
+ <artifactId>UaAnalyserV2</artifactId>
+ <version>1.0-SNAPSHOT</version>
+
+ <properties>
+ <maven.compiler.source>15</maven.compiler.source>
+ <maven.compiler.target>15</maven.compiler.target>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.mariadb.jdbc</groupId>
+ <artifactId>mariadb-java-client</artifactId>
+ <version>2.6.2</version>
+ </dependency>
+ <dependency>
+ <groupId>ru.yandex.clickhouse</groupId>
+ <artifactId>clickhouse-jdbc</artifactId>
+ <version>0.2.4</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
+ <!-- log4j support -->
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.17</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>1.6.6</version>
+ </dependency>
+
+
+ </dependencies>
+
+</project> \ No newline at end of file
diff --git a/src/main/java/com/example/ua/analyser/UaAnalyser.java b/src/main/java/com/example/ua/analyser/UaAnalyser.java
new file mode 100644
index 0000000..df06447
--- /dev/null
+++ b/src/main/java/com/example/ua/analyser/UaAnalyser.java
@@ -0,0 +1,17 @@
+package com.example.ua.analyser;
+
+import com.example.ua.analyser.enums.UserInfo;
+
+/**
+ * @author yjy
+ * @version 1.0
+ * @date 2020/11/15 12:20 下午
+ */
+public interface UaAnalyser {
+ /**
+ * 接口函数
+ * @param inputString 输入用户信息
+ * @return 分析结果-UserInfo类
+ */
+ public UserInfo getUserinfo(String inputString);
+}
diff --git a/src/main/java/com/example/ua/analyser/enums/RegexFeatureEnum.java b/src/main/java/com/example/ua/analyser/enums/RegexFeatureEnum.java
new file mode 100644
index 0000000..209664f
--- /dev/null
+++ b/src/main/java/com/example/ua/analyser/enums/RegexFeatureEnum.java
@@ -0,0 +1,42 @@
+package com.example.ua.analyser.enums;
+
+/**
+ * @author yjy
+ * @version 1.0
+ * @date 2020/11/15 12:20 下午
+ */
+public enum RegexFeatureEnum {
+ /* 终端类别名 */
+ TERMINAL_CAT_APPLE("apple", "终端类型名"),
+ TERMINAL_CAT_WINDOWS("windows", "终端类型名"),
+ TERMINAL_CAT_ANDROID("android", "终端类型名"),
+
+ /* 终端类别字符串匹配特征 */
+ TERMINAL_CAT_APPLE_FEATURE("com.apple.trustd", "终端类型特征字符串"),
+ TERMINAL_CAT_WINDOWS_FEATURE("Microsoft-CryptoAPI", "终端类型特征字符串"),
+ TERMINAL_CAT_ANDROID_FEATURE("Dalvik", "终端类型特征字符串");
+
+ private String code;
+ private String desc;
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public String getDesc() {
+ return desc;
+ }
+
+ public void setDesc(String desc) {
+ this.desc = desc;
+ }
+
+ private RegexFeatureEnum(String code, String desc){
+ this.code = code;
+ this.desc = desc;
+ }
+}
diff --git a/src/main/java/com/example/ua/analyser/enums/StandardUaList.java b/src/main/java/com/example/ua/analyser/enums/StandardUaList.java
new file mode 100644
index 0000000..95f43c0
--- /dev/null
+++ b/src/main/java/com/example/ua/analyser/enums/StandardUaList.java
@@ -0,0 +1,38 @@
+package com.example.ua.analyser.enums;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * windows真实浏览器ua
+ * @author yjy
+ * @version 1.0
+ * @date 2020/11/15 12:20 下午
+ */
+public class StandardUaList {
+
+ public List<String> getUaList() {
+ return uaList;
+ }
+
+ private List<String> uaList = Arrays.asList(
+ "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.3",
+ "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3775.400 QQBrowser/10.6.4209.400",
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36 Edg/85.0.564.51",
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0",
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18363",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0",
+ "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; Win64; x64; Trident/7.0; .NET4.0C; .NET4.0E; McAfee)",
+ "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3775.400 QQBrowser/10.6.4209.400"
+ );
+}
diff --git a/src/main/java/com/example/ua/analyser/enums/UserInfo.java b/src/main/java/com/example/ua/analyser/enums/UserInfo.java
new file mode 100644
index 0000000..b56f3bf
--- /dev/null
+++ b/src/main/java/com/example/ua/analyser/enums/UserInfo.java
@@ -0,0 +1,175 @@
+package com.example.ua.analyser.enums;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 用户信息结构
+ * @author yjy
+ * @version 1.0
+ * @date 2020/11/15 12:20 下午
+ */
+public class UserInfo {
+ /**
+ * input info
+ */
+ private String userId;
+ private String ip;
+ private String timeStamp;
+ private String uaCntInfo;
+ private List<String> uaList = new ArrayList<>();
+
+ /**
+ * analyse result info
+ */
+ private Integer osCnt;
+ private Integer browserCnt;
+ private Integer deviceCnt;
+ private Integer terminalCnt;
+ private Integer terminalCatCnt;
+
+ private List<String> osList = new ArrayList<>();
+ private List<String> browserList = new ArrayList<>();
+ private List<String> deviceList = new ArrayList<>();
+ private List<String> terminalCatList = new ArrayList<>();
+ private List<List<String>> terminalList = new ArrayList<>();
+
+ public void update(){
+ for (List<String> terminal : terminalList){
+ if ((terminal.get(0) != null) && !(osList.contains(terminal.get(0)))){
+ osList.add(terminal.get(0));
+ }
+ if ((terminal.get(1) != null) && !(browserList.contains(terminal.get(1)))){
+ browserList.add(terminal.get(1));
+ }
+ if ((terminal.get(2) != null) && !(deviceList.contains(terminal.get(2)))){
+ deviceList.add(terminal.get(2));
+ }
+ }
+ osCnt = osList.size();
+ browserCnt = browserList.size();
+ deviceCnt = deviceList.size();
+ terminalCnt = terminalList.size();
+ terminalCatCnt = terminalCatList.size();
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ public String getTimeStamp() {
+ return timeStamp;
+ }
+
+ public List<String> getUaList() {
+ return uaList;
+ }
+
+ public void setUaList(List<String> uaList) {
+ this.uaList = uaList;
+ }
+
+ public void setTimeStamp(String timeStamp) {
+ this.timeStamp = timeStamp;
+ }
+
+ public String getUaCntInfo() {
+ return uaCntInfo;
+ }
+
+ public void setUaCntInfo(String uaCntInfo) {
+ this.uaCntInfo = uaCntInfo;
+ }
+
+ public Integer getOsCnt() {
+ return osCnt;
+ }
+
+ public void setOsCnt(Integer osCnt) {
+ this.osCnt = osCnt;
+ }
+
+ public Integer getBrowserCnt() {
+ return browserCnt;
+ }
+
+ public void setBrowserCnt(Integer browserCnt) {
+ this.browserCnt = browserCnt;
+ }
+
+ public Integer getDeviceCnt() {
+ return deviceCnt;
+ }
+
+ public void setDeviceCnt(Integer deviceCnt) {
+ this.deviceCnt = deviceCnt;
+ }
+
+ public Integer getTerminalCnt() {
+ return terminalCnt;
+ }
+
+ public void setTerminalCnt(Integer terminalCnt) {
+ this.terminalCnt = terminalCnt;
+ }
+
+ public Integer getTerminalCatCnt() {
+ return terminalCatCnt;
+ }
+
+ public void setTerminalCatCnt(Integer terminalCatCnt) {
+ this.terminalCatCnt = terminalCatCnt;
+ }
+
+ public List<String> getOsList() {
+ return osList;
+ }
+
+ public void setOsList(List<String> osList) {
+ this.osList = osList;
+ }
+
+ public List<String> getBrowserList() {
+ return browserList;
+ }
+
+ public void setBrowserList(List<String> browserList) {
+ this.browserList = browserList;
+ }
+
+ public List<String> getDeviceList() {
+ return deviceList;
+ }
+
+ public void setDeviceList(List<String> deviceList) {
+ this.deviceList = deviceList;
+ }
+
+ public List<List<String>> getTerminalList() {
+ return terminalList;
+ }
+
+ public void setTerminalList(List<List<String>> terminalList) {
+ this.terminalList = terminalList;
+ }
+
+ public List<String> getTerminalCatList() {
+ return terminalCatList;
+ }
+
+ public void setTerminalCatList(List<String> terminalCatList) {
+ this.terminalCatList = terminalCatList;
+ }
+}
diff --git a/src/main/java/com/example/ua/analyser/impl/AndroidAnalyser.java b/src/main/java/com/example/ua/analyser/impl/AndroidAnalyser.java
new file mode 100644
index 0000000..5e8f6a7
--- /dev/null
+++ b/src/main/java/com/example/ua/analyser/impl/AndroidAnalyser.java
@@ -0,0 +1,101 @@
+package com.example.ua.analyser.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.example.ua.analyser.enums.RegexFeatureEnum;
+import com.example.ua.analyser.enums.UserInfo;
+import com.example.ua.dao.QueryMariaDb;
+import com.example.ua.dao.impl.QueryMariaDbImpl;
+import org.mariadb.jdbc.MariaDbStatement;
+
+/**
+ * android类设备分析
+ * @author yjy
+ * @version 1.0
+ * @date 2020/11/15 12:20 下午
+ */
+public class AndroidAnalyser {
+ private UserInfo userInfo;
+ private MariaDbStatement connStatement;
+ private QueryMariaDb queryMariaDb = new QueryMariaDbImpl();
+
+ public AndroidAnalyser(MariaDbStatement connStatement, UserInfo userInfo){
+ this.userInfo = userInfo;
+ this.connStatement = connStatement;
+ }
+
+ public UserInfo getTriples(){
+ List<String> tripleInDatabase;
+ List<String> tripleInRegex;
+ List<List<String>> tripleList = this.userInfo.getTerminalList();
+
+ //筛选androidUA
+ List<String> uaList = selectAndroidUa(this.userInfo.getUaList());
+ if (uaList.size()==0){
+ return null;
+ }
+
+ for (String ua : uaList) {
+ tripleInDatabase = queryMariaDb.getTriple(this.connStatement, ua);
+ if (tripleInDatabase.size() > 0) {
+ if (!(tripleList.contains(tripleInDatabase))){
+ tripleList.add(tripleInDatabase);
+ }
+ } else { //不进行重复解析
+ tripleInRegex = parseAndroidUa(ua);
+ if ((tripleInRegex != null) && !(tripleList.contains(tripleInRegex))){
+ tripleList.add(tripleInRegex);
+ }
+ }
+ }
+ this.userInfo.setTerminalList(tripleList);
+ this.userInfo.update();
+
+ return this.userInfo;
+ }
+
+ private List<String> selectAndroidUa(List<String> uaList){
+ List<String>selectedUaList = new ArrayList<>();
+
+ Pattern android = Pattern.compile(RegexFeatureEnum.TERMINAL_CAT_ANDROID_FEATURE.getCode());
+
+ for (String ua : uaList) {
+ if (android.matcher(ua).find()){
+ selectedUaList.add(ua);
+ }
+ }
+ return selectedUaList;
+ }
+
+ private List<String> parseAndroidUa(String ua){
+ List<String> androidTerminal = Arrays.asList(new String[3]);
+ String dePattern = "; [a-zA-Z0-9\\s]+/";
+ String versionPattern = "; U; [a-zA-Z0-9\\s\\.]+;";
+ Pattern de = Pattern.compile(dePattern);
+ Pattern version = Pattern.compile(versionPattern);
+ Matcher matcher1 = de.matcher(ua);
+ Matcher matcher2 = version.matcher(ua);
+
+ if (matcher1.find() && matcher2.find()) {
+ // os
+ String tmp = matcher2.group(0);
+ androidTerminal.set(0, tmp.substring(5, tmp.length()-1));
+ // TODO browser
+ androidTerminal.set(1, null);
+ // device
+ tmp = matcher1.group(0);
+ androidTerminal.set(2, tmp.substring(2, tmp.length() - 1));
+ } else {
+ return null;
+ }
+ return androidTerminal;
+ }
+
+
+
+
+}
diff --git a/src/main/java/com/example/ua/analyser/impl/AppleAnalyser.java b/src/main/java/com/example/ua/analyser/impl/AppleAnalyser.java
new file mode 100644
index 0000000..1e4f9a2
--- /dev/null
+++ b/src/main/java/com/example/ua/analyser/impl/AppleAnalyser.java
@@ -0,0 +1,129 @@
+package com.example.ua.analyser.impl;
+
+import com.example.ua.analyser.enums.UserInfo;
+import com.example.ua.dao.QueryMariaDb;
+import com.example.ua.dao.impl.QueryMariaDbImpl;
+import org.mariadb.jdbc.MariaDbStatement;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+/**
+ * apple类设备分析
+ * @author yjy
+ * @version 1.0
+ * @date 2020/11/15 12:20 下午
+ */
+public class AppleAnalyser {
+ private UserInfo userInfo;
+ private MariaDbStatement connStatement;
+ private QueryMariaDb queryMariaDb = new QueryMariaDbImpl();
+
+ public AppleAnalyser(MariaDbStatement connStatement, UserInfo userInfo){
+ this.userInfo = userInfo;
+ this.connStatement = connStatement;
+ }
+
+ public UserInfo getTriples(){
+ List<String> tripleInDatabase;
+ List<String> tripleInRegex;
+ List<List<String>> tripleList = this.userInfo.getTerminalList();
+
+ //筛选Apple Ua
+ List<String> uaList = selectAppleUa(this.userInfo.getUaList());
+ if (uaList.size()==0){
+ return null;
+ }
+
+ for (String ua : uaList) {
+ tripleInDatabase = queryMariaDb.getTriple(this.connStatement, ua);
+ if ((tripleInDatabase.size() > 0)) {
+ if (!(tripleList.contains(tripleInDatabase))) {
+ tripleList.add(tripleInDatabase);
+ }
+ } else { //不进行重复解析
+ tripleInRegex = parseAppleUa(ua);
+ if ((tripleInRegex != null) && !(tripleList.contains(tripleInRegex))) {
+ tripleList.add(tripleInRegex);
+ }
+ }
+ }
+ this.userInfo.setTerminalList(tripleList);
+ this.userInfo.update();
+
+ return this.userInfo;
+ }
+
+ public List<String> parseAppleUa(String ua) {
+ List<String> appleTerminal = Arrays.asList(new String[3]);
+
+ String macPattern = "Mozilla.*Mac OS";
+ String ipadPattern = "server-bag .*iPad";
+ String iphoneString = "server-bag .*iPhone";
+ Pattern mac = Pattern.compile(macPattern);
+ Pattern ipad = Pattern.compile(ipadPattern);
+ Pattern iphone1 = Pattern.compile(ipadPattern);
+
+ if (mac.matcher(ua).find()) {
+ Pattern mozilla = Pattern.compile("\\(.*;");
+ Pattern version = Pattern.compile(";.*\\)");
+ Pattern macos = Pattern.compile("Mac OS X\\s.*\\)\\s");
+ Matcher matcher1 = mozilla.matcher(ua);
+ Matcher matcher2 = version.matcher(ua);
+
+ if (matcher1.find() && matcher2.find()) {
+ String tmp = matcher2.group(0);
+ Matcher matcher3 = macos.matcher(tmp);
+ if(matcher3.find()){
+ String macversion = Arrays.asList(matcher3.group(0).split("\\)")).get(0).trim().replace("_",".");
+ appleTerminal.set(0, macversion);
+ appleTerminal.set(2, "Apple Mac");
+ }
+ }
+ } else if (ipad.matcher(ua).find()) {
+ Pattern iPad = Pattern.compile("iPad.*]");
+ Matcher matcher = iPad.matcher(ua);
+ if (matcher.find()) {
+ String tmp = matcher.group();
+ appleTerminal.set(0, "iOS " + tmp.replace(',', '.').substring(4, tmp.length() - 1));
+ appleTerminal.set(2, "Apple iPad");
+ }
+ }
+ else if (iphone1.matcher(ua).find()) {
+ appleTerminal.set(0, "iOS");
+ appleTerminal.set(2, "Apple iPhone");
+ }
+
+ if (Collections.frequency(appleTerminal, null) == 3) {
+ return null;
+ }
+ return appleTerminal;
+ }
+
+ private List<String> selectAppleUa(List<String> uaList){
+ List<String>selectedUaList = new ArrayList<>();
+
+ Pattern pattern1 = Pattern.compile("Mozilla.*Mac OS X\\s");
+ Pattern pattern2 = Pattern.compile("server-bag .*iPad");
+ Pattern pattern3 = Pattern.compile("server-bag .*iPhone");
+
+ for (int i = 0; i < uaList.size(); i++) {
+ String ua = uaList.get(i);
+ if (pattern1.matcher(ua).find() || pattern2.matcher(ua).find() || pattern3.matcher(ua).find()) {
+ selectedUaList.add(ua);
+ }
+ }
+ return selectedUaList;
+ }
+
+
+
+
+
+
+}
diff --git a/src/main/java/com/example/ua/analyser/impl/TerminalClassify.java b/src/main/java/com/example/ua/analyser/impl/TerminalClassify.java
new file mode 100644
index 0000000..83c1e94
--- /dev/null
+++ b/src/main/java/com/example/ua/analyser/impl/TerminalClassify.java
@@ -0,0 +1,57 @@
+package com.example.ua.analyser.impl;
+
+import com.example.ua.analyser.enums.UserInfo;
+import com.example.ua.analyser.enums.RegexFeatureEnum;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * get possible categories of terminal
+ */
+public class TerminalClassify {
+
+ public static void checkSys(UserInfo userInfo){
+ List<String> uaList = userInfo.getUaList();
+ List<String> catList = userInfo.getTerminalCatList();
+
+ Pattern apple = Pattern.compile(RegexFeatureEnum.TERMINAL_CAT_APPLE_FEATURE.getCode());
+ Pattern android = Pattern.compile(RegexFeatureEnum.TERMINAL_CAT_ANDROID_FEATURE.getCode());
+ Pattern win = Pattern.compile(RegexFeatureEnum.TERMINAL_CAT_WINDOWS_FEATURE.getCode());
+
+ Map<String, Integer> catCnt = new HashMap<>();
+ catCnt.put(RegexFeatureEnum.TERMINAL_CAT_APPLE.getCode(), 0);
+ catCnt.put(RegexFeatureEnum.TERMINAL_CAT_ANDROID.getCode(), 0);
+ catCnt.put(RegexFeatureEnum.TERMINAL_CAT_WINDOWS.getCode(), 0);
+
+ for (String s : uaList) {
+ if (apple.matcher(s).find()) {
+ catCnt.put(RegexFeatureEnum.TERMINAL_CAT_APPLE.getCode(),
+ catCnt.get(RegexFeatureEnum.TERMINAL_CAT_APPLE.getCode()) + 1);
+ continue;
+ }
+ if (android.matcher(s).find()) {
+ catCnt.put(RegexFeatureEnum.TERMINAL_CAT_ANDROID.getCode(),
+ catCnt.get(RegexFeatureEnum.TERMINAL_CAT_ANDROID.getCode()) + 1);
+ continue;
+ }
+ if (win.matcher(s).find()) {
+ catCnt.put(RegexFeatureEnum.TERMINAL_CAT_WINDOWS.getCode(),
+ catCnt.get(RegexFeatureEnum.TERMINAL_CAT_WINDOWS.getCode()) + 1);
+ }
+ }
+
+ if (catCnt.get(RegexFeatureEnum.TERMINAL_CAT_WINDOWS.getCode())!=0)
+ catList.add(RegexFeatureEnum.TERMINAL_CAT_WINDOWS.getCode());
+ if (catCnt.get(RegexFeatureEnum.TERMINAL_CAT_ANDROID.getCode())!=0)
+ catList.add(RegexFeatureEnum.TERMINAL_CAT_ANDROID.getCode());
+ if (catCnt.get(RegexFeatureEnum.TERMINAL_CAT_APPLE.getCode())!=0)
+ catList.add(RegexFeatureEnum.TERMINAL_CAT_APPLE.getCode());
+
+ userInfo.setTerminalCatList(catList);
+ }
+}
+
+
diff --git a/src/main/java/com/example/ua/analyser/impl/UaAnalyserImpl.java b/src/main/java/com/example/ua/analyser/impl/UaAnalyserImpl.java
new file mode 100644
index 0000000..50c9131
--- /dev/null
+++ b/src/main/java/com/example/ua/analyser/impl/UaAnalyserImpl.java
@@ -0,0 +1,77 @@
+package com.example.ua.analyser.impl;
+
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.example.ua.analyser.UaAnalyser;
+import com.example.ua.analyser.enums.UserInfo;
+import com.example.ua.utils.MariaDBConnect;
+import com.example.ua.analyser.enums.RegexFeatureEnum;
+
+import org.mariadb.jdbc.MariaDbStatement;
+//import org.slf4j.Logger;
+import org.apache.log4j.Logger;
+
+public class UaAnalyserImpl implements UaAnalyser {
+ final Logger LOG = Logger.getLogger(UaAnalyser.class);
+ MariaDbStatement connStatement = MariaDBConnect.getMariaDB();
+
+ @Override
+ public UserInfo getUserinfo(String inputString){
+ UserInfo userInfo = parseInfo(inputString);
+ List<List<String>> terminalList = userInfo.getTerminalList();
+
+ // get terminalCatInfo in userInfo
+ TerminalClassify.checkSys(userInfo);
+
+ //android
+ if (userInfo.getTerminalCatList().contains(RegexFeatureEnum.TERMINAL_CAT_ANDROID.getCode())){
+ AndroidAnalyser androidAnalyser = new AndroidAnalyser(connStatement, userInfo);
+ userInfo = androidAnalyser.getTriples();
+ }
+ //windows
+ if (userInfo.getTerminalCatList().contains(RegexFeatureEnum.TERMINAL_CAT_WINDOWS.getCode())){
+ WindowsAnalyser windowsAnalyser = new WindowsAnalyser(connStatement, userInfo);
+ userInfo = windowsAnalyser.getTriples();
+ }
+ //apple
+ if (userInfo.getTerminalCatList().contains(RegexFeatureEnum.TERMINAL_CAT_WINDOWS.getCode())){
+ AppleAnalyser appleAnalyser = new AppleAnalyser(connStatement, userInfo);
+ userInfo = appleAnalyser.getTriples();
+ }
+
+// userInfo.setTerminalList(terminalList);
+ userInfo.update();
+ return userInfo;
+ }
+
+ public UserInfo parseInfo(String inputString){
+ UserInfo userInfo = new UserInfo();
+ List<String> uaList = userInfo.getUaList();
+
+ String[] info = inputString.split("\t");
+ try{
+ userInfo.setUserId(info[0]);
+ userInfo.setIp(info[1]);
+ userInfo.setTimeStamp(info[2]);
+ userInfo.setUaCntInfo(info[3]);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ LOG.error("Input Format Error: " + inputString);
+ userInfo.update();
+ return userInfo;
+ }
+
+ Pattern pattern = Pattern.compile("\\'(.*?)\\'");
+ Matcher matcher = pattern.matcher(userInfo.getUaCntInfo());
+ while (matcher.find()) {
+ String tmp = matcher.group(0).replace("\'", "");
+ uaList.add(tmp);
+ }
+ userInfo.setUaList(uaList);
+
+ userInfo.update();
+ return userInfo;
+ }
+
+}
diff --git a/src/main/java/com/example/ua/analyser/impl/WindowsAnalyser.java b/src/main/java/com/example/ua/analyser/impl/WindowsAnalyser.java
new file mode 100644
index 0000000..adafc43
--- /dev/null
+++ b/src/main/java/com/example/ua/analyser/impl/WindowsAnalyser.java
@@ -0,0 +1,73 @@
+package com.example.ua.analyser.impl;
+
+import com.example.ua.analyser.enums.StandardUaList;
+import com.example.ua.analyser.enums.UserInfo;
+import com.example.ua.dao.QueryMariaDb;
+import com.example.ua.dao.impl.QueryMariaDbImpl;
+import org.mariadb.jdbc.MariaDbStatement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+import org.apache.log4j.Logger;
+
+
+/**
+ * windows类设备分析
+ * @author yjy
+ * @version 1.0
+ * @date 2020/11/15 12:20 下午
+ */
+public class WindowsAnalyser {
+ private static final Logger LOG = Logger.getLogger(WindowsAnalyser.class);
+ private UserInfo userInfo;
+ private MariaDbStatement connStatement;
+ private QueryMariaDb queryMariaDb = new QueryMariaDbImpl();
+
+ public WindowsAnalyser(MariaDbStatement connStatement, UserInfo userInfo) {
+ this.userInfo = userInfo;
+ this.connStatement = connStatement;
+ }
+
+ public UserInfo getTriples() {
+ List<String> tripleInDatabase;
+ List<List<String>> tripleList = this.userInfo.getTerminalList();
+
+ // 筛选真实浏览器ua
+ List<String> uaList = selectStandardUa(this.userInfo.getUaList());
+ if (uaList.size() == 0) {
+ return null;
+ }
+
+ // 解析库解析
+ for (String ua : uaList) {
+ tripleInDatabase = queryMariaDb.getTriple(this.connStatement, ua);
+ if ((tripleInDatabase.size() > 0) && !(tripleList.contains(tripleInDatabase))) {
+ tripleList.add(tripleInDatabase);
+ }
+ }
+ this.userInfo.setTerminalList(tripleList);
+ this.userInfo.update();
+
+ return this.userInfo;
+ }
+
+ private List<String> selectStandardUa(List<String> uaList) {
+ List<String> standardUaList = getStandardUa();
+ List<String> selectedUaList = new ArrayList<>();
+ String windowsString = "Mozilla.*Windows";
+ Pattern windows = Pattern.compile(windowsString);
+ for (String ua : uaList) {
+ if (windows.matcher(ua).find() && standardUaList.contains(ua)) {
+ selectedUaList.add(ua);
+ }
+ }
+ return selectedUaList;
+ }
+
+ private List<String> getStandardUa() {
+ List<String> ua;
+ StandardUaList standardUaList = new StandardUaList();
+ ua = standardUaList.getUaList();
+ return ua;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/example/ua/config/ApplicationConfig.java b/src/main/java/com/example/ua/config/ApplicationConfig.java
new file mode 100644
index 0000000..f22e594
--- /dev/null
+++ b/src/main/java/com/example/ua/config/ApplicationConfig.java
@@ -0,0 +1,26 @@
+package com.example.ua.config;
+
+import com.example.ua.utils.ConfigUtils;
+
+
+/**
+ * 配置信息
+ * @author yjy
+ * @version 1.0
+ * @date 2020/11/15 12:20 下午
+ */
+public class ApplicationConfig {
+
+ public static final String MARIADB_HOST = ConfigUtils.getStringProperty( "mariaDB.host");
+ public static final String MARIADB_PORT = ConfigUtils.getStringProperty("mariaDB.port");
+ public static final String MARIADB_USER = ConfigUtils.getStringProperty( "mariaDB.user");
+ public static final String MARIADB_PASSWORD = ConfigUtils.getStringProperty( "mariaDB.password");
+ public static final String MARIADB_DB_NAME = ConfigUtils.getStringProperty( "mariaDB.database");
+ public static final String MARIADB_TABLE = ConfigUtils.getStringProperty( "mariaDB.talbe");
+
+ public static final String MARIA_UA = ConfigUtils.getStringProperty( "mariaDB.user_agent");
+ public static final String MARIA_OS = ConfigUtils.getStringProperty( "mariaDB.os");
+ public static final String MARIA_BROWSER = ConfigUtils.getStringProperty( "mariaDB.browser");
+ public static final String MARIA_DIVECE = ConfigUtils.getStringProperty( "mariaDB.device");
+
+}
diff --git a/src/main/java/com/example/ua/dao/QueryMariaDb.java b/src/main/java/com/example/ua/dao/QueryMariaDb.java
new file mode 100644
index 0000000..f8f9ec9
--- /dev/null
+++ b/src/main/java/com/example/ua/dao/QueryMariaDb.java
@@ -0,0 +1,20 @@
+package com.example.ua.dao;
+
+import org.mariadb.jdbc.MariaDbStatement;
+
+import java.util.List;
+
+/**
+ * @author yjy
+ * @version 1.0
+ * @date 2020/11/15 12:20 下午
+ */
+public interface QueryMariaDb {
+ /**
+ * 接口函数
+ * @param ua 查询ua
+ * @param connStatement conn
+ * @return 三元组(OS,browser device)结果
+ */
+ public List<String> getTriple(MariaDbStatement connStatement, String ua);
+}
diff --git a/src/main/java/com/example/ua/dao/impl/QueryMariaDbImpl.java b/src/main/java/com/example/ua/dao/impl/QueryMariaDbImpl.java
new file mode 100644
index 0000000..3c32049
--- /dev/null
+++ b/src/main/java/com/example/ua/dao/impl/QueryMariaDbImpl.java
@@ -0,0 +1,61 @@
+package com.example.ua.dao.impl;
+
+import com.example.ua.config.ApplicationConfig;
+import com.example.ua.dao.QueryMariaDb;
+import org.mariadb.jdbc.MariaDbStatement;
+import org.apache.log4j.Logger;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author yjy
+ * @version 1.0
+ * @date 2020/11/15 12:20 下午
+ */
+public class QueryMariaDbImpl implements QueryMariaDb {
+ private static final Logger LOG = Logger.getLogger(QueryMariaDbImpl.class);
+
+ @Override
+ public List<String> getTriple(MariaDbStatement connStatement, String ua) {
+ String sql = getSqlPattern(ua);
+ List<String> triple = new ArrayList<>();
+
+ try{
+ long startTime=System.currentTimeMillis();
+ ResultSet results = connStatement.executeQuery(sql);
+ long endTime=System.currentTimeMillis();
+ LOG.debug("QueryMaria.QueryTime " + (endTime-startTime) + "ms");
+
+ if (results.next()) {
+ results.previous();
+ while (results.next()) {
+ triple.add(results.getString(ApplicationConfig.MARIA_OS));
+ triple.add(results.getString(ApplicationConfig.MARIA_BROWSER));
+ triple.add(results.getString(ApplicationConfig.MARIA_DIVECE));
+ }
+ } else {
+ LOG.info("QueryMariaDB.Empty " + ua);
+ }
+ return triple;
+
+ } catch (SQLException e){
+ LOG.info("QueryMariaDB.Fail " + e.toString());
+ return null;
+ }
+ }
+
+ private String getSqlPattern(String ua){
+ String sqlPattern = "SELECT "+ ApplicationConfig.MARIA_UA + ", "
+ + ApplicationConfig.MARIA_BROWSER + ", "
+ + ApplicationConfig.MARIA_OS + ", "
+ + ApplicationConfig.MARIA_DIVECE + " From "
+ + ApplicationConfig.MARIADB_DB_NAME + "."
+ + ApplicationConfig.MARIADB_TABLE + " WHERE user_agent = '%s'";
+ return String.format(sqlPattern, ua);
+ }
+}
+
+
diff --git a/src/main/java/com/example/ua/utils/ConfigUtils.java b/src/main/java/com/example/ua/utils/ConfigUtils.java
new file mode 100644
index 0000000..1a84ee5
--- /dev/null
+++ b/src/main/java/com/example/ua/utils/ConfigUtils.java
@@ -0,0 +1,43 @@
+package com.example.ua.utils;
+
+import org.apache.log4j.Logger;
+import java.util.Properties;
+
+/**
+ * @author yjy
+ * @version 1.0
+ * @date 2020/11/15 12:20 下午
+ */
+public class ConfigUtils {
+ private static final Logger LOG = Logger.getLogger(ConfigUtils.class);
+ private static Properties propCommon = new Properties();
+
+ public static String getStringProperty(String key) {
+ return propCommon.getProperty(key);
+ }
+
+
+ public static Integer getIntProperty(String key) {
+ return Integer.parseInt(propCommon.getProperty(key));
+ }
+
+ public static Long getLongProperty(String key) {
+ return Long.parseLong(propCommon.getProperty(key));
+ }
+
+ public static Boolean getBooleanProperty(String key) {
+ return "true".equals(propCommon.getProperty(key).toLowerCase().trim());
+ }
+
+ static {
+ try {
+ propCommon.load(ConfigUtils.class.getClassLoader().getResourceAsStream("application.properties"));
+ LOG.info("application.properties加载成功");
+
+
+ } catch (Exception e) {
+ propCommon = null;
+ LOG.error("配置加载失败");
+ }
+ }
+}
diff --git a/src/main/java/com/example/ua/utils/MariaDBConnect.java b/src/main/java/com/example/ua/utils/MariaDBConnect.java
new file mode 100644
index 0000000..cb95e51
--- /dev/null
+++ b/src/main/java/com/example/ua/utils/MariaDBConnect.java
@@ -0,0 +1,40 @@
+package com.example.ua.utils;
+
+import com.example.ua.config.ApplicationConfig;
+
+import org.mariadb.jdbc.MariaDbDataSource;
+import org.mariadb.jdbc.MariaDbStatement;
+//import org.slf4j.Logger;
+import org.apache.log4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.mariadb.jdbc.MariaDbConnection;
+import java.sql.SQLException;
+
+/**
+ * 建立连接
+ */
+public class MariaDBConnect{
+ private static final Logger LOG = Logger.getLogger(MariaDBConnect.class);
+
+ public static MariaDbStatement getMariaDB(){
+ String addr = "jdbc:mariadb://"
+ + ApplicationConfig.MARIADB_HOST + ":"
+ + ApplicationConfig.MARIADB_PORT + "/"
+ + ApplicationConfig.MARIADB_DB_NAME;
+
+ MariaDbDataSource dataSource = new MariaDbDataSource(addr);
+ MariaDbStatement statement = null;
+
+ try {
+ MariaDbConnection conn = (MariaDbConnection) dataSource.getConnection(
+ ApplicationConfig.MARIADB_USER,
+ ApplicationConfig.MARIADB_PASSWORD);
+ statement = (MariaDbStatement) conn.createStatement();
+ } catch (SQLException e) {
+ LOG.error("GetMariaDBConnection Faild. " + e.toString());
+ }
+ return statement;
+ }
+
+} \ No newline at end of file
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000..67d7f43
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,12 @@
+# mariaDB参数配置
+mariaDB.host = 192.168.40.193
+mariaDB.port = 3306
+mariaDB.user = tsg_query
+mariaDB.password = ceiec_2018
+mariaDB.database = tsg_galaxy_source
+mariaDB.talbe = whatismybrowser_useragent
+
+mariaDB.user_agent = user_agent
+mariaDB.os = operating_system
+mariaDB.browser = software
+mariaDB.device = simple_operating_platform_string \ No newline at end of file
diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties
new file mode 100644
index 0000000..15202b0
--- /dev/null
+++ b/src/main/resources/log4j.properties
@@ -0,0 +1,26 @@
+########################## logger ##############################
+
+### 设置###
+log4j.rootLogger = debug,stdout,D,E
+
+### 输出信息到控制抬 ###
+#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 = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
+
+### 输出DEBUG 级别以上的日志###
+log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
+log4j.appender.D.File = /Users/joy/work/iie/project/cyber_narrator/multiAccess/UaAnalyserV2/logs/debug.log
+log4j.appender.D.Append = true
+log4j.appender.D.Threshold = DEBUG
+log4j.appender.D.layout = org.apache.log4j.PatternLayout
+log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
+
+### 输出ERROR 级别以上的日志 ###
+log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
+log4j.appender.E.File =/Users/joy/work/iie/project/cyber_narrator/multiAccess/UaAnalyserV2/logs/error.log
+log4j.appender.E.Append = true
+log4j.appender.E.Threshold = ERROR
+log4j.appender.E.layout = org.apache.log4j.PatternLayout
+log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n \ No newline at end of file
diff --git a/src/test/java/UaAnalyserTest.java b/src/test/java/UaAnalyserTest.java
new file mode 100644
index 0000000..b8c73d3
--- /dev/null
+++ b/src/test/java/UaAnalyserTest.java
@@ -0,0 +1,34 @@
+import com.example.ua.analyser.UaAnalyser;
+import com.example.ua.analyser.enums.UserInfo;
+import com.example.ua.analyser.impl.UaAnalyserImpl;
+import com.example.ua.config.ApplicationConfig;
+
+import java.awt.*;
+import java.lang.reflect.Field;
+
+public class UaAnalyserTest {
+
+
+ public static void main(String[] args){
+
+ String inputString = "69765" + "\t" + // userId
+ "192.168.50.13" + "\t" + // ip
+ "1765433230" + "\t" + // timeStamp
+ "'Dalvik/1.6.0 (Linux; U; Android 4.0.3; LG-E612f Build/IML74K)':4, " +
+ "'Dalvik/2.1.0 (Linux; U; Android 10; TNYAL00 Build/HUAWEITNY-AL00)':4" +
+ "'Mozilla/5.0 (iPhone; CPU iPhone OS 11_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15G77 === iOS/11.4.1 Model/iPhone10,1 BundleID/com.xunmeng.pinduoduo AppVersion/5.32.0 AppBuild/2009212125 pversion/1221 cURL/7.48.0':5" +
+ "'com.apple.trustd/1.0':1" +
+ "'server-bag [iPhone OS,13.6.1,17G80,iPhone10,2]':1" +
+ "'Microsoft-CryptoAPI/10.0':1" +
+ "'Mozilla/5.0 (Linux; Android 10; SM-G9600) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.110 Mobile Safari/537.36':10" +
+ "'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36':1"; // uaCntInfo
+
+ UaAnalyser uaAnalyser = new UaAnalyserImpl();
+ UserInfo userInfo = uaAnalyser.getUserinfo(inputString);
+
+ // 获取相关字段:
+ // osCnt, browserCnt, deviceCnt, terminalCnt, terminalCatCnt,
+ // osList, browserList, deviceList, terminalList, terminalCatList
+ System.out.println(userInfo.getTerminalList()); // 获取terminalList字段值
+ }
+}