方案一:Runtime.exec 傳統呼叫 (僅限 Windows)
// 簡單粗暴,Windows 專用
Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler https://www.example.com");
- 優點:程式碼極簡單,無依賴
- 缺點:僅限 Windows,Linux/macOS 無效,安全性較低
方案二:Desktop API 標準跨平台方案 (推薦)
import java.awt.Desktop;
import java.net.URI;
public class BrowserLauncher {
public static void openUrl(String url) {
// 1. 檢查平台支援性
if (!Desktop.isDesktopSupported()) {
System.err.println("當前平台不支援 Desktop API");
return;
}
Desktop desktop = Desktop.getDesktop();
// 2. 檢查 BROWSE 動作支援性
if (!desktop.isSupported(Desktop.Action.BROWSE)) {
System.err.println("當前環境不支援瀏覽器啟動功能");
return;
}
try {
// 3. 建立 URI (非 URL,注意差異)
URI uri = URI.create(url);
// 4. 啟動預設瀏覽器
desktop.browse(uri);
System.out.println("成功啟動瀏覽器開啟: " + url);
} catch (NullPointerException e) {
System.err.println("URI 為空: " + e.getMessage());
} catch (IOException e) {
System.err.println("無法啟動瀏覽器: " + e.getMessage());
// 降級策略:嘗試方案一或提示用戶手動複製連結
}
}
public static void main(String[] args) {
openUrl("https://www.example.com");
}
}
關鍵差異比較
| 特性 | Runtime.exec | Desktop API |
| 跨平台 | ❌ 僅 Windows | ✅ Windows/Linux/macOS |
| 標準化 | ❌ 平台特定指令 | ✅ Java SE 6+ 標準 API |
| 錯誤處理 | 困難 | 完善的異常體系 |
| 安全性 | 命令注入風險 | 無殼層注入風險 |
| 功能豐富度 | 單一功能 | 支援 OPEN/EDIT/MAIL/PRINT |
Desktop API 完整功能矩陣
Desktop.Action.BROWSE // 開啟 URL (瀏覽器)
Desktop.Action.MAIL // 開啟郵件客戶端 (mailto:)
Desktop.Action.OPEN // 開啟檔案 (關聯應用程式)
Desktop.Action.EDIT // 編輯檔案
Desktop.Action.PRINT // 列印檔案
實戰最佳實踐
public class CrossPlatformBrowser {
public static boolean open(String url) {
// 策略 1: Desktop API (優先)
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
try {
Desktop.getDesktop().browse(URI.create(url));
return true;
} catch (Exception e) {
// 記錄日誌,嘗試降級
}
}
// 策略 2: 平台特定降級
String os = System.getProperty("os.name").toLowerCase();
try {
if (os.contains("win")) {
Runtime.getRuntime().exec(new String[]{"cmd", "/c", "start", "", url});
} else if (os.contains("mac")) {
Runtime.getRuntime().exec(new String[]{"/usr/bin/open", url});
} else if (os.contains("nix") || os.contains("nux")) {
// 嘗試常見 Linux 瀏覽器啟動器
String[] browsers = {"xdg-open", "gnome-open", "kde-open", "firefox", "chrome"};
for (String browser : browsers) {
try {
Runtime.getRuntime().exec(new String[]{browser, url});
return true;
} catch (Exception ignored) {}
}
}
} catch (Exception e) {
// 全部失敗
}
return false;
}
}
注意事項總結
- URI vs URL:Desktop.browse() 接受 URI,使用
URI.create() 而非 new URL()
- 無頭環境:伺服器端無圖形介面時 Desktop API 不支援,需替代方案
- 編碼處理:URL 中的中文等特殊字元需預先編碼
URLEncoder.encode()
- 安全性:避免直接拼接用戶輸入到命令字串,防止命令注入