首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> JSP 程式設計 >> 關於JSP

JSP 解析客戶端 User-Agent 獲取瀏覽器、作業系統、語言資訊完整元件

     編輯:關於JSP

元件設計目標

封裝 HttpServletRequest.getHeader("User-Agent") 解析邏輯,提供結構化物件:

  • 廠商 (company):Microsoft, Opera Software, Netscape Communications, unknown
  • 瀏覽器名稱 (name):Microsoft Internet Explorer, Netscape Navigator, Opera, unknown
  • 完整版本 (version)、主版本 (mainVersion)、次版本 (minorVersion)
  • 作業系統 (os):Windows 95/98/NT/3.x (舊版範例,現代需擴充)
  • 偏好語言 (language):依 Accept-Language Header 解析
  • Locale 物件:供國際化使用

完整 JavaBean 原始碼 (Browser.java)

package com.example.util;

import java.util.*;
import javax.servlet.http.*;

public class Browser {
    private HttpServletRequest request;
    private HttpSession session;
    private String userAgent;

    private String company;
    private String name;
    private String version;
    private String mainVersion;
    private String minorVersion;
    private String os;
    private String language = "zh-TW"; // 預設繁體中文
    private Locale locale;

    private final Map<String, String> supportedLanguages = new HashMap<>();

    public Browser(HttpServletRequest request, HttpSession session) {
        this.request = request;
        this.session = session;
        initSupportedLanguages();
        parseUserAgent();
        parseLanguage();
        buildLocale();
    }

    private void initSupportedLanguages() {
        supportedLanguages.put("en", "English");
        supportedLanguages.put("zh-TW", "繁體中文");
        supportedLanguages.put("zh-CN", "简体中文");
        supportedLanguages.put("ja", "日本語");
        supportedLanguages.put("ko", "한국어");
    }

    private void parseUserAgent() {
        userAgent = request.getHeader("User-Agent");
        if (userAgent == null) userAgent = "";
        userAgent = userAgent.toLowerCase();

        // 廠商與瀏覽器判斷 (順序重要:較特定者優先)
        if (userAgent.contains("edg/")) {            // Microsoft Edge (Chromium)
            company = "Microsoft"; name = "Microsoft Edge";
            extractVersion("edg/");
        } else if (userAgent.contains("msie") || userAgent.contains("trident/")) { // IE 11-
            company = "Microsoft"; name = "Microsoft Internet Explorer";
            extractVersion(userAgent.contains("msie") ? "msie" : "rv:");
        } else if (userAgent.contains("opera") || userAgent.contains("opr/")) {
            company = "Opera Software"; name = "Opera";
            extractVersion(userAgent.contains("opr/") ? "opr/" : "opera");
        } else if (userAgent.contains("chrome")) {
            company = "Google"; name = "Chrome";
            extractVersion("chrome/");
        } else if (userAgent.contains("firefox")) {
            company = "Mozilla Foundation"; name = "Firefox";
            extractVersion("firefox/");
        } else if (userAgent.contains("safari")) {
            company = "Apple"; name = "Safari";
            extractVersion("version/");
        } else if (userAgent.contains("mozilla")) {
            company = "Netscape Communications"; name = "Netscape Navigator";
            extractVersion("mozilla/");
        } else {
            company = "unknown"; name = "unknown"; version = "0";
        }

        parseOS();
        splitVersion();
    }

    private void extractVersion(String key) {
        int idx = userAgent.indexOf(key);
        if (idx != -1) {
            String sub = userAgent.substring(idx + key.length());
            int end = sub.indexOf(' ');
            if (end == -1) end = sub.indexOf(';');
            if (end == -1) end = sub.length();
            version = sub.substring(0, end).trim();
        } else {
            version = "0";
        }
    }

    private void splitVersion() {
        int dot = version.indexOf('.');
        if (dot != -1) {
            mainVersion = version.substring(0, dot);
            minorVersion = version.substring(dot + 1);
        } else {
            mainVersion = version;
            minorVersion = "0";
        }
    }

    private void parseOS() {
        if (userAgent.contains("windows nt 10.0") || userAgent.contains("windows nt 6.3")) os = "Windows 10/11";
        else if (userAgent.contains("windows nt 6.2")) os = "Windows 8";
        else if (userAgent.contains("windows nt 6.1")) os = "Windows 7";
        else if (userAgent.contains("windows nt 6.0")) os = "Windows Vista";
        else if (userAgent.contains("windows nt 5.1") || userAgent.contains("windows nt 5.2")) os = "Windows XP/Server 2003";
        else if (userAgent.contains("win98")) os = "Windows 98";
        else if (userAgent.contains("win95")) os = "Windows 95";
        else if (userAgent.contains("win16") || userAgent.contains("windows 3.")) os = "Windows 3.x";
        else if (userAgent.contains("mac os x")) os = "macOS";
        else if (userAgent.contains("linux")) os = "Linux";
        else if (userAgent.contains("android")) os = "Android";
        else if (userAgent.contains("iphone") || userAgent.contains("ipad")) os = "iOS";
        else os = "unknown";
    }

    private void parseLanguage() {
        String acceptLang = request.getHeader("Accept-Language");
        if (acceptLang != null) {
            String[] parts = acceptLang.split(",");
            for (String part : parts) {
                String lang = part.split(";")[0].trim().toLowerCase(); // 取 q-value 前
                if (supportedLanguages.containsKey(lang)) {
                    language = lang;
                    break; // 取優先度最高的支援語言
                }
            }
        }
    }

    private void buildLocale() {
        String[] seg = language.split("-");
        locale = (seg.length == 2) ? new Locale(seg[0], seg[1]) : new Locale(language);
    }

    // ---- Getters ----
    public String getCompany() { return company; }
    public String getName() { return name; }
    public String getVersion() { return version; }
    public String getMainVersion() { return mainVersion; }
    public String getMinorVersion() { return minorVersion; }
    public String getOs() { return os; }
    public String getLanguage() { return language; }
    public Locale getLocale() { return locale; }
}

JSP 頁面使用範例

<%@ page import="com.example.util.Browser" %>
<%
    Browser browser = new Browser(request, session);
%>
<html><body>
<h2>客戶端環境資訊</h2>
<table border="1">
    <tr><th>屬性</th><th>值</th></tr>
    <tr><td>廠商</td><td><%=browser.getCompany()%></td></tr>
    <tr><td>瀏覽器</td><td><%=browser.getName()%></td></tr>
    <tr><td>版本</td><td><%=browser.getVersion()%> (主: <%=browser.getMainVersion()%>, 次: <%=browser.getMinorVersion()%>)</td></tr>
    <tr><td>作業系統</td><td><%=browser.getOs()%></td></tr>
    <tr><td>偏好語言</td><td><%=browser.getLanguage()%></td></tr>
    <tr><td>Locale</td><td><%=browser.getLocale()%></td></tr>
    <tr><td>原始 User-Agent</td><td><%=request.getHeader("User-Agent")%></td></tr>
</table>
</body></html>

現代化改進建議

  1. 引入成熟解析庫:UAParser、user-agent-utils,支援數千種 UA 模式、定期更新、準確度高。
  2. 快取解析結果:UA 字串重複率高,可用 ConcurrentHashMap<String, Browser> 或 Guava Cache 緩存。
  3. 擴充 OS/裝置偵測:整合 DeviceDetector 判斷行動裝置/平板/桌機、品牌/型號。
  4. Spring 整合:做成 @Component 或 HandlerInterceptor 將 Browser 物件放入 request 屬性,Controller 直接注入使用。

結語

解析 User-Agent 是 Web 分析、相容性處理、個性化內容的基礎需求。雖然手寫解析器可理解原理,但 生產環境強烈建議使用成熟開源庫,避免瀏覽器版本迭代導致邏輯失效。本文提供的 Browser Bean 結構清晰、擴充性佳,可作為整合第三方庫的介面適配層。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved