Skip to content

UserAgent 解析工具 ​

UserAgentUtil 是一个 User-Agent 字符串解析工具,可以识别浏览器类型、版本、操作系统和设备类型。

类信息 ​

  • 包名: com.molandev.core.util
  • 类名: UserAgentUtil
  • 类型: 静态工具类
  • 依赖: 无(纯 Java 实现)

核心特性 ​

✅ 浏览器识别 ​

支持主流浏览器:

  • Chrome、Edge、Firefox、Safari
  • Opera、Vivaldi、Yandex Browser
  • UC Browser、微信内置浏览器
  • Internet Explorer

✅ 操作系统识别 ​

支持主流操作系统:

  • Windows (10/8.1/8/7/Vista/XP/2000)
  • macOS / Mac OS X
  • Android、iOS (iPhone/iPad/iPod)
  • Linux、Ubuntu、FreeBSD 等

✅ 设备类型识别 ​

  • Desktop(桌面设备)
  • Mobile(手机)
  • Tablet(平板)

✅ 高性能 ​

  • 基于正则表达式匹配
  • 无外部依赖
  • 线程安全

核心方法 ​

1. parse ​

解析 User-Agent 字符串,返回完整信息。

java
public static UserAgentInfo parse(String userAgent)
参数类型说明
userAgentStringUser-Agent 字符串
返回值UserAgentInfo包含浏览器、版本、操作系统、设备类型的对象

示例:

java
String ua = request.getHeader("User-Agent");
UserAgentUtil.UserAgentInfo info = UserAgentUtil.parse(ua);

System.out.println("浏览器: " + info.getBrowser());
System.out.println("版本: " + info.getBrowserVersion());
System.out.println("操作系统: " + info.getOs());
System.out.println("设备类型: " + info.getDeviceType());

2. detectBrowser ​

检测浏览器名称。

java
public static String detectBrowser(String userAgent)

示例:

java
String browser = UserAgentUtil.detectBrowser(userAgent);
// "Chrome", "Firefox", "Safari", ...

3. detectBrowserVersion ​

检测浏览器版本。

java
public static String detectBrowserVersion(String userAgent, String browser)

示例:

java
String browser = UserAgentUtil.detectBrowser(userAgent);
String version = UserAgentUtil.detectBrowserVersion(userAgent, browser);
// "120.0.6099.109"

4. detectOperatingSystem ​

检测操作系统。

java
public static String detectOperatingSystem(String userAgent)

示例:

java
String os = UserAgentUtil.detectOperatingSystem(userAgent);
// "Windows 10", "macOS", "Android", ...

5. detectDeviceType ​

检测设备类型。

java
public static String detectDeviceType(String userAgent)

返回值: "mobile", "tablet", "desktop"

示例:

java
String deviceType = UserAgentUtil.detectDeviceType(userAgent);
if ("mobile".equals(deviceType)) {
    // 返回移动端页面
}

6. isMobile ​

判断是否为移动设备。

java
public static boolean isMobile(String userAgent)

示例:

java
if (UserAgentUtil.isMobile(userAgent)) {
    // 移动设备逻辑
}

7. isTablet ​

判断是否为平板设备。

java
public static boolean isTablet(String userAgent)

8. isDesktop ​

判断是否为桌面设备。

java
public static boolean isDesktop(String userAgent)

UserAgentInfo 类 ​

解析结果封装类。

java
public static class UserAgentInfo {
    private final String browser;         // 浏览器名称
    private final String browserVersion;  // 浏览器版本
    private final String os;              // 操作系统
    private final String deviceType;      // 设备类型
    
    // Getter 方法
    public String getBrowser() { ... }
    public String getBrowserVersion() { ... }
    public String getOs() { ... }
    public String getDeviceType() { ... }
}

完整示例 ​

示例 1: 访问统计 ​

java
@RestController
@RequestMapping("/api")
public class StatisticsController {
    
    @Autowired
    private VisitLogService visitLogService;
    
    @GetMapping("/track")
    public Result trackVisit(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        String ip = request.getRemoteAddr();
        
        // 解析 User-Agent
        UserAgentUtil.UserAgentInfo info = UserAgentUtil.parse(userAgent);
        
        // 记录访问日志
        VisitLog log = new VisitLog();
        log.setIp(ip);
        log.setBrowser(info.getBrowser());
        log.setBrowserVersion(info.getBrowserVersion());
        log.setOs(info.getOs());
        log.setDeviceType(info.getDeviceType());
        log.setVisitTime(LocalDateTime.now());
        
        visitLogService.save(log);
        
        return Result.success();
    }
}

示例 2: 响应式页面选择 ​

java
@Controller
public class HomeController {
    
    @GetMapping("/")
    public String index(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        
        // 根据设备类型返回不同页面
        if (UserAgentUtil.isMobile(userAgent)) {
            return "mobile/index";
        } else if (UserAgentUtil.isTablet(userAgent)) {
            return "tablet/index";
        } else {
            return "desktop/index";
        }
    }
}

示例 3: API 版本控制 ​

java
@RestController
@RequestMapping("/api")
public class ApiController {
    
    @GetMapping("/data")
    public Result getData(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        UserAgentUtil.UserAgentInfo info = UserAgentUtil.parse(userAgent);
        
        // 根据浏览器版本返回不同的数据格式
        if ("Internet Explorer".equals(info.getBrowser())) {
            // IE 浏览器返回兼容格式
            return Result.success(legacyData);
        } else {
            // 现代浏览器返回标准格式
            return Result.success(modernData);
        }
    }
}

示例 4: 移动端重定向 ​

java
@Component
public class MobileRedirectInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                            HttpServletResponse response, 
                            Object handler) throws Exception {
        String userAgent = request.getHeader("User-Agent");
        String uri = request.getRequestURI();
        
        // 移动设备访问 PC 站点,重定向到移动站
        if (UserAgentUtil.isMobile(userAgent) && !uri.startsWith("/m/")) {
            response.sendRedirect("/m" + uri);
            return false;
        }
        
        return true;
    }
}

示例 5: 浏览器兼容性检查 ​

java
@RestController
@RequestMapping("/api")
public class CompatibilityController {
    
    @GetMapping("/check")
    public Result checkCompatibility(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        UserAgentUtil.UserAgentInfo info = UserAgentUtil.parse(userAgent);
        
        // 检查浏览器兼容性
        if ("Internet Explorer".equals(info.getBrowser())) {
            String version = info.getBrowserVersion();
            int majorVersion = Integer.parseInt(version.split("\\.")[0]);
            
            if (majorVersion < 11) {
                return Result.error("您的浏览器版本过低,请升级到 IE11 或使用现代浏览器");
            }
        }
        
        return Result.success("浏览器兼容");
    }
}

支持的浏览器 ​

浏览器识别名称说明
EdgeEdgeMicrosoft Edge
ChromeChromeGoogle Chrome
FirefoxFirefoxMozilla Firefox
SafariSafariApple Safari
Internet ExplorerInternet ExplorerIE 浏览器
OperaOperaOpera 浏览器
VivaldiVivaldiVivaldi 浏览器
YandexYandexYandex Browser
UC BrowserUC BrowserUC 浏览器
WeChatWeChat微信内置浏览器

支持的操作系统 ​

操作系统识别名称
Windows 10Windows 10
Windows 8.1Windows 8.1
Windows 7Windows 7
macOSmacOS
AndroidAndroid
iOS (iPhone)iPhone iOS
iOS (iPad)iPad iOS
LinuxLinux
UbuntuUbuntu
Chrome OSChrome OS

技术细节 ​

正则表达式匹配 ​

UserAgentUtil 使用预编译的正则表达式进行高效匹配:

java
private static final Pattern BROWSER_PATTERNS[] = {
    Pattern.compile("(?i)Edg/([\\d.]+)"),
    Pattern.compile("(?i)Chrome/([\\d.]+)"),
    Pattern.compile("(?i)Firefox/([\\d.]+)"),
    // ...
};

匹配顺序 ​

浏览器匹配有特定顺序(重要):

  1. Edge(必须在 Chrome 之前,因为 Edge 包含 Chrome 标识)
  2. Chrome
  3. Firefox
  4. Safari
  5. ...

User-Agent 示例 ​

text
# Chrome on Windows
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36

# Firefox on Mac
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0

# Safari on iPhone
Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Mobile/15E148 Safari/604.1

# Edge on Windows
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.2210.121

注意事项 ​

⚠️ User-Agent 可伪造 ​

User-Agent 是客户端发送的字符串,可以被伪造。不要用于安全验证,仅用于统计和用户体验优化。

⚠️ 新版本识别 ​

新版本的浏览器可能无法识别,会返回 "Unknown"。

⚠️ 性能 ​

正则匹配有一定性能开销,但对单次请求影响很小(微秒级)。如需频繁调用,建议缓存结果。

⚠️ 移动端判断 ​

部分平板设备可能被识别为桌面设备,建议结合屏幕尺寸判断。

常见问题 ​

Q1: 如何处理 "Unknown" 结果? ​

A: 返回 "Unknown" 说明无法识别该 User-Agent,可以:

  1. 使用默认值
  2. 记录日志,后续更新正则表达式
  3. 降级处理
java
UserAgentUtil.UserAgentInfo info = UserAgentUtil.parse(userAgent);
if ("Unknown".equals(info.getBrowser())) {
    // 使用默认处理
}

Q2: 如何添加新的浏览器支持? ​

A: 需要修改源码中的正则表达式数组。建议提交 PR 到开源项目。

Q3: 性能如何? ​

A:

  • 单次解析:约 0.1-0.5 毫秒
  • 线程安全
  • 正则表达式已预编译

Q4: 支持机器人识别吗? ​

A: 当前版本不支持。如需识别爬虫,可以检查 User-Agent 中是否包含 "bot"、"spider" 等关键词。

Q5: 为什么 iPad 被识别为桌面? ​

A: 某些 iPad 的 User-Agent 不包含 "Mobile" 标识,可能被误判。可以结合其他信息(如屏幕尺寸、触摸事件)综合判断。

最佳实践 ​

1. 缓存解析结果 ​

java
@Component
public class UserAgentCache {
    
    private final LoadingCache<String, UserAgentUtil.UserAgentInfo> cache = 
        CacheBuilder.newBuilder()
            .maximumSize(1000)
            .expireAfterWrite(1, TimeUnit.HOURS)
            .build(new CacheLoader<String, UserAgentUtil.UserAgentInfo>() {
                @Override
                public UserAgentUtil.UserAgentInfo load(String ua) {
                    return UserAgentUtil.parse(ua);
                }
            });
    
    public UserAgentUtil.UserAgentInfo parse(String userAgent) {
        return cache.getUnchecked(userAgent);
    }
}

2. 结合前端判断 ​

javascript
// 前端传递屏幕信息
const deviceInfo = {
    screenWidth: window.screen.width,
    screenHeight: window.screen.height,
    isTouchDevice: 'ontouchstart' in window
};

fetch('/api/track', {
    method: 'POST',
    body: JSON.stringify(deviceInfo)
});

3. 日志记录 ​

java
log.info("访问信息 - IP: {}, Browser: {}, OS: {}, Device: {}", 
    ip, info.getBrowser(), info.getOs(), info.getDeviceType());

相关工具 ​

参考资料 ​