From 383a82e530f8e98499527648191cbc85f9c2ad8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9B=BE=E6=96=87=E8=B1=AA?= <980287353@qq.com> Date: Thu, 10 Oct 2024 16:20:14 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E5=A2=9E=E5=8A=A0useragent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/tiesheng/util/useragent/Browser.java | 140 +++++++++++++ .../com/tiesheng/util/useragent/Engine.java | 62 ++++++ .../java/com/tiesheng/util/useragent/OS.java | 107 ++++++++++ .../com/tiesheng/util/useragent/Platform.java | 147 +++++++++++++ .../tiesheng/util/useragent/UserAgent.java | 196 ++++++++++++++++++ .../util/useragent/UserAgentInfo.java | 114 ++++++++++ .../util/useragent/UserAgentParser.java | 108 ++++++++++ 7 files changed, 874 insertions(+) create mode 100644 springboot-util/src/main/java/com/tiesheng/util/useragent/Browser.java create mode 100644 springboot-util/src/main/java/com/tiesheng/util/useragent/Engine.java create mode 100644 springboot-util/src/main/java/com/tiesheng/util/useragent/OS.java create mode 100644 springboot-util/src/main/java/com/tiesheng/util/useragent/Platform.java create mode 100644 springboot-util/src/main/java/com/tiesheng/util/useragent/UserAgent.java create mode 100644 springboot-util/src/main/java/com/tiesheng/util/useragent/UserAgentInfo.java create mode 100644 springboot-util/src/main/java/com/tiesheng/util/useragent/UserAgentParser.java diff --git a/springboot-util/src/main/java/com/tiesheng/util/useragent/Browser.java b/springboot-util/src/main/java/com/tiesheng/util/useragent/Browser.java new file mode 100644 index 0000000..44fd9e2 --- /dev/null +++ b/springboot-util/src/main/java/com/tiesheng/util/useragent/Browser.java @@ -0,0 +1,140 @@ +package com.tiesheng.util.useragent; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ReUtil; + +import java.util.List; +import java.util.regex.Pattern; + +/** + * 浏览器对象 + * + * @author looly + * @since 4.2.1 + */ +public class Browser extends UserAgentInfo { + private static final long serialVersionUID = 1L; + + /** + * 未知 + */ + public static final Browser Unknown = new Browser(NameUnknown, null, null); + /** + * 其它版本 + */ + public static final String Other_Version = "[\\/ ]([\\d\\w\\.\\-]+)"; + + /** + * 支持的浏览器类型 + */ + public static final List browers = CollUtil.newArrayList( + // 部分特殊浏览器是基于安卓、Iphone等的,需要优先判断 + // 企业微信 企业微信使用微信浏览器内核,会包含 MicroMessenger 所以要放在前面 + new Browser("wxwork", "wxwork", "wxwork\\/([\\d\\w\\.\\-]+)"), + // 微信 + new Browser("MicroMessenger", "MicroMessenger", Other_Version), + // 微信小程序 + new Browser("miniProgram", "miniProgram", Other_Version), + // QQ浏览器 + new Browser("QQBrowser", "MQQBrowser", "MQQBrowser\\/([\\d\\w\\.\\-]+)"), + // 钉钉PC端浏览器 + new Browser("DingTalk-win", "dingtalk-win", "DingTalk\\(([\\d\\w\\.\\-]+)\\)"), + // 钉钉内置浏览器 + new Browser("DingTalk", "DingTalk", "AliApp\\(DingTalk\\/([\\d\\w\\.\\-]+)\\)"), + // 支付宝内置浏览器 + new Browser("Alipay", "AlipayClient", "AliApp\\(AP\\/([\\d\\w\\.\\-]+)\\)"), + // 淘宝内置浏览器 + new Browser("Taobao", "taobao", "AliApp\\(TB\\/([\\d\\w\\.\\-]+)\\)"), + // UC浏览器 + new Browser("UCBrowser", "UC?Browser", "UC?Browser\\/([\\d\\w\\.\\-]+)"), + // XiaoMi 浏览器 + new Browser("MiuiBrowser", "MiuiBrowser|mibrowser", "MiuiBrowser\\/([\\d\\w\\.\\-]+)"), + // 夸克浏览器 + new Browser("Quark", "Quark", Other_Version), + // 联想浏览器 + new Browser("Lenovo", "SLBrowser", "SLBrowser/([\\d\\w\\.\\-]+)"), + new Browser("MSEdge", "Edge|Edg", "(?:edge|Edg|EdgA)\\/([\\d\\w\\.\\-]+)"), + new Browser("Chrome", "chrome", Other_Version), + new Browser("Firefox", "firefox", Other_Version), + new Browser("IEMobile", "iemobile", Other_Version), + new Browser("Android Browser", "android", "version\\/([\\d\\w\\.\\-]+)"), + new Browser("Safari", "safari", "version\\/([\\d\\w\\.\\-]+)"), + new Browser("Opera", "opera", Other_Version), + new Browser("Konqueror", "konqueror", Other_Version), + new Browser("PS3", "playstation 3", "([\\d\\w\\.\\-]+)\\)\\s*$"), + new Browser("PSP", "playstation portable", "([\\d\\w\\.\\-]+)\\)?\\s*$"), + new Browser("Lotus", "lotus.notes", "Lotus-Notes\\/([\\w.]+)"), + new Browser("Thunderbird", "thunderbird", Other_Version), + new Browser("Netscape", "netscape", Other_Version), + new Browser("Seamonkey", "seamonkey", Other_Version), + new Browser("Outlook", "microsoft.outlook", Other_Version), + new Browser("Evolution", "evolution", Other_Version), + new Browser("MSIE", "msie", "msie ([\\d\\w\\.\\-]+)"), + new Browser("MSIE11", "rv:11", "rv:([\\d\\w\\.\\-]+)"), + new Browser("Gabble", "Gabble", Other_Version), + new Browser("Yammer Desktop", "AdobeAir", "([\\d\\w\\.\\-]+)\\/Yammer"), + new Browser("Yammer Mobile", "Yammer[\\s]+([\\d\\w\\.\\-]+)", "Yammer[\\s]+([\\d\\w\\.\\-]+)"), + new Browser("Apache HTTP Client", "Apache\\\\-HttpClient", "Apache\\-HttpClient\\/([\\d\\w\\.\\-]+)"), + new Browser("BlackBerry", "BlackBerry", "BlackBerry[\\d]+\\/([\\d\\w\\.\\-]+)") + ); + + /** + * 添加自定义的浏览器类型 + * + * @param name 浏览器名称 + * @param regex 关键字或表达式 + * @param versionRegex 匹配版本的正则 + * @since 5.7.4 + */ + synchronized public static void addCustomBrowser(String name, String regex, String versionRegex) { + browers.add(new Browser(name, regex, versionRegex)); + } + + private Pattern versionPattern; + + /** + * 构造 + * + * @param name 浏览器名称 + * @param regex 关键字或表达式 + * @param versionRegex 匹配版本的正则 + */ + public Browser(String name, String regex, String versionRegex) { + super(name, regex); + if (Other_Version.equals(versionRegex)) { + versionRegex = name + versionRegex; + } + if (null != versionRegex) { + this.versionPattern = Pattern.compile(versionRegex, Pattern.CASE_INSENSITIVE); + } + } + + /** + * 获取浏览器版本 + * + * @param userAgentString User-Agent字符串 + * @return 版本 + */ + public String getVersion(String userAgentString) { + if(isUnknown()){ + return null; + } + return ReUtil.getGroup1(this.versionPattern, userAgentString); + } + + /** + * 是否移动浏览器 + * + * @return 是否移动浏览器 + */ + public boolean isMobile() { + final String name = this.getName(); + return "PSP".equals(name) || + "Yammer Mobile".equals(name) || + "Android Browser".equals(name) || + "IEMobile".equals(name) || + "MicroMessenger".equals(name) || + "miniProgram".equals(name) || + "DingTalk".equals(name); + } +} diff --git a/springboot-util/src/main/java/com/tiesheng/util/useragent/Engine.java b/springboot-util/src/main/java/com/tiesheng/util/useragent/Engine.java new file mode 100644 index 0000000..04946f7 --- /dev/null +++ b/springboot-util/src/main/java/com/tiesheng/util/useragent/Engine.java @@ -0,0 +1,62 @@ +package com.tiesheng.util.useragent; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ReUtil; + +import java.util.List; +import java.util.regex.Pattern; + +/** + * 引擎对象 + * + * @author looly + * @since 4.2.1 + */ +public class Engine extends UserAgentInfo { + private static final long serialVersionUID = 1L; + + /** 未知 */ + public static final Engine Unknown = new Engine(NameUnknown, null); + + /** + * 支持的引擎类型 + */ + public static final List engines = CollUtil.newArrayList( + new Engine("Trident", "trident"), + new Engine("Webkit", "webkit"), + new Engine("Chrome", "chrome"), + new Engine("Opera", "opera"), + new Engine("Presto", "presto"), + new Engine("Gecko", "gecko"), + new Engine("KHTML", "khtml"), + new Engine("Konqueror", "konqueror"), + new Engine("MIDP", "MIDP") + ); + + private final Pattern versionPattern; + + /** + * 构造 + * + * @param name 引擎名称 + * @param regex 关键字或表达式 + */ + public Engine(String name, String regex) { + super(name, regex); + this.versionPattern = Pattern.compile(name + "[/\\- ]([\\d\\w.\\-]+)", Pattern.CASE_INSENSITIVE); + } + + /** + * 获取引擎版本 + * + * @param userAgentString User-Agent字符串 + * @return 版本 + * @since 5.7.4 + */ + public String getVersion(String userAgentString) { + if(isUnknown()){ + return null; + } + return ReUtil.getGroup1(this.versionPattern, userAgentString); + } +} diff --git a/springboot-util/src/main/java/com/tiesheng/util/useragent/OS.java b/springboot-util/src/main/java/com/tiesheng/util/useragent/OS.java new file mode 100644 index 0000000..6e0bb41 --- /dev/null +++ b/springboot-util/src/main/java/com/tiesheng/util/useragent/OS.java @@ -0,0 +1,107 @@ +package com.tiesheng.util.useragent; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ReUtil; + +import java.util.List; +import java.util.regex.Pattern; + +/** + * 系统对象 + * + * @author looly + * @since 4.2.1 + */ +public class OS extends UserAgentInfo { + private static final long serialVersionUID = 1L; + + /** + * 未知 + */ + public static final OS Unknown = new OS(NameUnknown, null); + + /** + * 支持的引擎类型 + */ + public static final List oses = CollUtil.newArrayList(// + new OS("Windows 10 or Windows Server 2016", "windows nt 10\\.0", "windows nt (10\\.0)"),// + new OS("Windows 8.1 or Windows Server 2012R2", "windows nt 6\\.3", "windows nt (6\\.3)"),// + new OS("Windows 8 or Windows Server 2012", "windows nt 6\\.2", "windows nt (6\\.2)"),// + new OS("Windows Vista", "windows nt 6\\.0", "windows nt (6\\.0)"), // + new OS("Windows 7 or Windows Server 2008R2", "windows nt 6\\.1", "windows nt (6\\.1)"), // + new OS("Windows 2003", "windows nt 5\\.2", "windows nt (5\\.2)"), // + new OS("Windows XP", "windows nt 5\\.1", "windows nt (5\\.1)"), // + new OS("Windows 2000", "windows nt 5\\.0", "windows nt (5\\.0)"), // + new OS("Windows Phone", "windows (ce|phone|mobile)( os)?", "windows (?:ce|phone|mobile) (\\d+([._]\\d+)*)"), // + new OS("Windows", "windows"), // + new OS("OSX", "os x (\\d+)[._](\\d+)", "os x (\\d+([._]\\d+)*)"), // + new OS("Android", "Android", "Android (\\d+([._]\\d+)*)"),// + new OS("Android", "XiaoMi|MI\\s+", "\\(X(\\d+([._]\\d+)*)"),// + new OS("Linux", "linux"), // + new OS("Wii", "wii", "wii libnup/(\\d+([._]\\d+)*)"), // + new OS("PS3", "playstation 3", "playstation 3; (\\d+([._]\\d+)*)"), // + new OS("PSP", "playstation portable", "Portable\\); (\\d+([._]\\d+)*)"), // + new OS("iPad", "\\(iPad.*os (\\d+)[._](\\d+)", "\\(iPad.*os (\\d+([._]\\d+)*)"), // + new OS("iPhone", "\\(iPhone.*os (\\d+)[._](\\d+)", "\\(iPhone.*os (\\d+([._]\\d+)*)"), // + new OS("YPod", "iPod touch[\\s\\;]+iPhone.*os (\\d+)[._](\\d+)", "iPod touch[\\s\\;]+iPhone.*os (\\d+([._]\\d+)*)"), // + new OS("YPad", "iPad[\\s\\;]+iPhone.*os (\\d+)[._](\\d+)", "iPad[\\s\\;]+iPhone.*os (\\d+([._]\\d+)*)"), // + new OS("YPhone", "iPhone[\\s\\;]+iPhone.*os (\\d+)[._](\\d+)", "iPhone[\\s\\;]+iPhone.*os (\\d+([._]\\d+)*)"), // + new OS("Symbian", "symbian(os)?"), // + new OS("Darwin", "Darwin\\/([\\d\\w\\.\\-]+)", "Darwin\\/([\\d\\w\\.\\-]+)"), // + new OS("Adobe Air", "AdobeAir\\/([\\d\\w\\.\\-]+)", "AdobeAir\\/([\\d\\w\\.\\-]+)"), // + new OS("Java", "Java[\\s]+([\\d\\w\\.\\-]+)", "Java[\\s]+([\\d\\w\\.\\-]+)")// + ); + + /** + * 添加自定义的系统类型 + * + * @param name 浏览器名称 + * @param regex 关键字或表达式 + * @param versionRegex 匹配版本的正则 + * @since 5.7.4 + */ + synchronized public static void addCustomOs(String name, String regex, String versionRegex) { + oses.add(new OS(name, regex, versionRegex)); + } + + private Pattern versionPattern; + + /** + * 构造 + * + * @param name 系统名称 + * @param regex 关键字或表达式 + */ + public OS(String name, String regex) { + this(name, regex, null); + } + + /** + * 构造 + * + * @param name 系统名称 + * @param regex 关键字或表达式 + * @param versionRegex 版本正则表达式 + * @since 5.7.4 + */ + public OS(String name, String regex, String versionRegex) { + super(name, regex); + if (null != versionRegex) { + this.versionPattern = Pattern.compile(versionRegex, Pattern.CASE_INSENSITIVE); + } + } + + /** + * 获取浏览器版本 + * + * @param userAgentString User-Agent字符串 + * @return 版本 + */ + public String getVersion(String userAgentString) { + if(isUnknown() || null == this.versionPattern){ + // 无版本信息 + return null; + } + return ReUtil.getGroup1(this.versionPattern, userAgentString); + } +} diff --git a/springboot-util/src/main/java/com/tiesheng/util/useragent/Platform.java b/springboot-util/src/main/java/com/tiesheng/util/useragent/Platform.java new file mode 100644 index 0000000..46aa055 --- /dev/null +++ b/springboot-util/src/main/java/com/tiesheng/util/useragent/Platform.java @@ -0,0 +1,147 @@ +package com.tiesheng.util.useragent; + +import cn.hutool.core.collection.CollUtil; + +import java.util.ArrayList; +import java.util.List; + +/** + * 平台对象 + * + * @author looly + * @since 4.2.1 + */ +public class Platform extends UserAgentInfo { + private static final long serialVersionUID = 1L; + + /** + * 未知 + */ + public static final Platform Unknown = new Platform(NameUnknown, null); + + /** + * Iphone + */ + public static final Platform IPHONE = new Platform("iPhone", "iphone"); + /** + * ipod + */ + public static final Platform IPOD = new Platform("iPod", "ipod"); + /** + * ipad + */ + public static final Platform IPAD = new Platform("iPad", "ipad"); + + /** + * android + */ + public static final Platform ANDROID = new Platform("Android", "android"); + /** + * android + */ + public static final Platform GOOGLE_TV = new Platform("GoogleTV", "googletv"); + + /** + * Windows Phone + */ + public static final Platform WINDOWS_PHONE = new Platform("Windows Phone", "windows (ce|phone|mobile)( os)?"); + + /** + * 支持的移动平台类型 + */ + public static final List mobilePlatforms = CollUtil.newArrayList(// + WINDOWS_PHONE, // + IPAD, // + IPOD, // + IPHONE, // + new Platform("Android", "XiaoMi|MI\\s+"), // + ANDROID, // + GOOGLE_TV, // + new Platform("htcFlyer", "htc_flyer"), // + new Platform("Symbian", "symbian(os)?"), // + new Platform("Blackberry", "blackberry") // + ); + + /** + * 支持的桌面平台类型 + */ + public static final List desktopPlatforms = CollUtil.newArrayList(// + new Platform("Windows", "windows"), // + new Platform("Mac", "(macintosh|darwin)"), // + new Platform("Linux", "linux"), // + new Platform("Wii", "wii"), // + new Platform("Playstation", "playstation"), // + new Platform("Java", "java") // + ); + + /** + * 支持的平台类型 + */ + public static final List platforms; + + static { + platforms = new ArrayList<>(13); + platforms.addAll(mobilePlatforms); + platforms.addAll(desktopPlatforms); + } + + /** + * 构造 + * + * @param name 平台名称 + * @param regex 关键字或表达式 + */ + public Platform(String name, String regex) { + super(name, regex); + } + + /** + * 是否为移动平台 + * + * @return 是否为移动平台 + */ + public boolean isMobile() { + return mobilePlatforms.contains(this); + } + + /** + * 是否为Iphone或者iPod设备 + * + * @return 是否为Iphone或者iPod设备 + * @since 5.2.3 + */ + public boolean isIPhoneOrIPod() { + return this.equals(IPHONE) || this.equals(IPOD); + } + + /** + * 是否为Iphone或者iPod设备 + * + * @return 是否为Iphone或者iPod设备 + * @since 5.2.3 + */ + public boolean isIPad() { + return this.equals(IPAD); + } + + /** + * 是否为IOS平台,包括IPhone、IPod、IPad + * + * @return 是否为IOS平台,包括IPhone、IPod、IPad + * @since 5.2.3 + */ + public boolean isIos() { + return isIPhoneOrIPod() || isIPad(); + } + + /** + * 是否为Android平台,包括Android和Google TV + * + * @return 是否为Android平台,包括Android和Google TV + * @since 5.2.3 + */ + public boolean isAndroid() { + return this.equals(ANDROID) || this.equals(GOOGLE_TV); + } + +} diff --git a/springboot-util/src/main/java/com/tiesheng/util/useragent/UserAgent.java b/springboot-util/src/main/java/com/tiesheng/util/useragent/UserAgent.java new file mode 100644 index 0000000..dc25251 --- /dev/null +++ b/springboot-util/src/main/java/com/tiesheng/util/useragent/UserAgent.java @@ -0,0 +1,196 @@ +package com.tiesheng.util.useragent; + +import java.io.Serializable; + +/** + * User-Agent信息对象 + * + * @author looly + * @since 4.2.1 + */ +public class UserAgent implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 是否为移动平台 + */ + private boolean mobile; + /** + * 浏览器类型 + */ + private Browser browser; + /** + * 浏览器版本 + */ + private String version; + + /** + * 平台类型 + */ + private Platform platform; + + /** + * 系统类型 + */ + private OS os; + /** + * 系统版本 + */ + private String osVersion; + + /** + * 引擎类型 + */ + private Engine engine; + /** + * 引擎版本 + */ + private String engineVersion; + + /** + * 是否为移动平台 + * + * @return 是否为移动平台 + */ + public boolean isMobile() { + return mobile; + } + + /** + * 设置是否为移动平台 + * + * @param mobile 是否为移动平台 + */ + public void setMobile(boolean mobile) { + this.mobile = mobile; + } + + /** + * 获取浏览器类型 + * + * @return 浏览器类型 + */ + public Browser getBrowser() { + return browser; + } + + /** + * 设置浏览器类型 + * + * @param browser 浏览器类型 + */ + public void setBrowser(Browser browser) { + this.browser = browser; + } + + /** + * 获取平台类型 + * + * @return 平台类型 + */ + public Platform getPlatform() { + return platform; + } + + /** + * 设置平台类型 + * + * @param platform 平台类型 + */ + public void setPlatform(Platform platform) { + this.platform = platform; + } + + /** + * 获取系统类型 + * + * @return 系统类型 + */ + public OS getOs() { + return os; + } + + /** + * 设置系统类型 + * + * @param os 系统类型 + */ + public void setOs(OS os) { + this.os = os; + } + + /** + * 获取系统版本 + * + * @return 系统版本 + * @since 5.7.4 + */ + public String getOsVersion() { + return this.osVersion; + } + + /** + * 设置系统版本 + * + * @param osVersion 系统版本 + * @since 5.7.4 + */ + public void setOsVersion(String osVersion) { + this.osVersion = osVersion; + } + + /** + * 获取引擎类型 + * + * @return 引擎类型 + */ + public Engine getEngine() { + return engine; + } + + /** + * 设置引擎类型 + * + * @param engine 引擎类型 + */ + public void setEngine(Engine engine) { + this.engine = engine; + } + + /** + * 获取浏览器版本 + * + * @return 浏览器版本 + */ + public String getVersion() { + return version; + } + + /** + * 设置浏览器版本 + * + * @param version 浏览器版本 + */ + public void setVersion(String version) { + this.version = version; + } + + /** + * 获取引擎版本 + * + * @return 引擎版本 + */ + public String getEngineVersion() { + return engineVersion; + } + + /** + * 设置引擎版本 + * + * @param engineVersion 引擎版本 + */ + public void setEngineVersion(String engineVersion) { + this.engineVersion = engineVersion; + } + +} diff --git a/springboot-util/src/main/java/com/tiesheng/util/useragent/UserAgentInfo.java b/springboot-util/src/main/java/com/tiesheng/util/useragent/UserAgentInfo.java new file mode 100644 index 0000000..7c6ea1b --- /dev/null +++ b/springboot-util/src/main/java/com/tiesheng/util/useragent/UserAgentInfo.java @@ -0,0 +1,114 @@ +package com.tiesheng.util.useragent; + +import cn.hutool.core.util.ReUtil; + +import java.io.Serializable; +import java.util.regex.Pattern; + +/** + * User-agent信息 + * + * @author looly + * @since 4.2.1 + */ +public class UserAgentInfo implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 未知类型 + */ + public static final String NameUnknown = "Unknown"; + + /** 信息名称 */ + private final String name; + /** 信息匹配模式 */ + private final Pattern pattern; + + /** + * 构造 + * + * @param name 名字 + * @param regex 表达式 + */ + public UserAgentInfo(String name, String regex) { + this(name, (null == regex) ? null : Pattern.compile(regex, Pattern.CASE_INSENSITIVE)); + } + + /** + * 构造 + * + * @param name 名字 + * @param pattern 匹配模式 + */ + public UserAgentInfo(String name, Pattern pattern) { + this.name = name; + this.pattern = pattern; + } + + /** + * 获取信息名称 + * + * @return 信息名称 + */ + public String getName() { + return name; + } + + /** + * 获取匹配模式 + * + * @return 匹配模式 + */ + public Pattern getPattern() { + return pattern; + } + + /** + * 指定内容中是否包含匹配此信息的内容 + * + * @param content User-Agent字符串 + * @return 是否包含匹配此信息的内容 + */ + public boolean isMatch(String content) { + return ReUtil.contains(this.pattern, content); + } + + /** + * 是否为Unknown + * + * @return 是否为Unknown + */ + public boolean isUnknown() { + return NameUnknown.equals(this.name); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final UserAgentInfo other = (UserAgentInfo) obj; + if (name == null) { + return other.name == null; + } else return name.equals(other.name); + } + + @Override + public String toString() { + return this.name; + } +} diff --git a/springboot-util/src/main/java/com/tiesheng/util/useragent/UserAgentParser.java b/springboot-util/src/main/java/com/tiesheng/util/useragent/UserAgentParser.java new file mode 100644 index 0000000..84efc99 --- /dev/null +++ b/springboot-util/src/main/java/com/tiesheng/util/useragent/UserAgentParser.java @@ -0,0 +1,108 @@ +package com.tiesheng.util.useragent; + +import cn.hutool.core.util.StrUtil; + +/** + * User-Agent解析器 + * + * @author looly + * @since 4.2.1 + */ +public class UserAgentParser { + + /** + * 解析User-Agent + * + * @param userAgentString User-Agent字符串 + * @return {@link UserAgent} + */ + public static UserAgent parse(String userAgentString) { + if(StrUtil.isBlank(userAgentString)){ + return null; + } + final UserAgent userAgent = new UserAgent(); + + // 浏览器 + final Browser browser = parseBrowser(userAgentString); + userAgent.setBrowser(browser); + userAgent.setVersion(browser.getVersion(userAgentString)); + + // 浏览器引擎 + final Engine engine = parseEngine(userAgentString); + userAgent.setEngine(engine); + userAgent.setEngineVersion(engine.getVersion(userAgentString)); + + // 操作系统 + final OS os = parseOS(userAgentString); + userAgent.setOs(os); + userAgent.setOsVersion(os.getVersion(userAgentString)); + + // 平台 + final Platform platform = parsePlatform(userAgentString); + userAgent.setPlatform(platform); + userAgent.setMobile(platform.isMobile() || browser.isMobile()); + + + return userAgent; + } + + /** + * 解析浏览器类型 + * + * @param userAgentString User-Agent字符串 + * @return 浏览器类型 + */ + private static Browser parseBrowser(String userAgentString) { + for (Browser browser : Browser.browers) { + if (browser.isMatch(userAgentString)) { + return browser; + } + } + return Browser.Unknown; + } + + /** + * 解析引擎类型 + * + * @param userAgentString User-Agent字符串 + * @return 引擎类型 + */ + private static Engine parseEngine(String userAgentString) { + for (Engine engine : Engine.engines) { + if (engine.isMatch(userAgentString)) { + return engine; + } + } + return Engine.Unknown; + } + + /** + * 解析系统类型 + * + * @param userAgentString User-Agent字符串 + * @return 系统类型 + */ + private static OS parseOS(String userAgentString) { + for (OS os : OS.oses) { + if (os.isMatch(userAgentString)) { + return os; + } + } + return OS.Unknown; + } + + /** + * 解析平台类型 + * + * @param userAgentString User-Agent字符串 + * @return 平台类型 + */ + private static Platform parsePlatform(String userAgentString) { + for (Platform platform : Platform.platforms) { + if (platform.isMatch(userAgentString)) { + return platform; + } + } + return Platform.Unknown; + } +}