將圖片、聲音等資源打包進 JAR,並在 <APPLET ARCHIVE="test.jar"> 中載入。直覺寫法 new ImageIcon("/img/Logo.gif") 會拋出 AccessControlException: java.io.FilePermission,因為 Applet 沙箱禁止直接存取檔案系統路徑。
| 做法 | 程式碼 | 結果 |
|---|---|---|
| ❌ 絕對/相對路徑 | new ImageIcon("/img/Logo.gif") | 嘗試從檔案系統讀取,被沙箱阻擋 |
| ❌ getResourceAsStream 但路徑錯誤 | getClass().getResourceAsStream("img/Logo.gif") | 相對路徑從類別套件目錄查找,找不到資源 |
| ✅ Class.getResource (絕對路徑) | getClass().getResource("/img/Logo.gif") | 從 JAR 根目錄查找,**正確** |
| ✅ ClassLoader.getResource | getClass().getClassLoader().getResource("img/Logo.gif") | 從 Classpath 根目錄查找,同樣正確 |
public URL getResource(String name) {
// name 以 '/' 開頭:從 classpath 根目錄查找 (JAR 內部根目錄)
// name 不以 '/' 開頭:從當前類別的 package 目錄查找
}
public class ImageButtonApplet extends JApplet {
private String resourcePath = "/img/Logo.gif"; // 絕對路徑,從 JAR 根目錄
public void init() {
try {
// 關鍵:使用 getClass().getResource() 取得 JAR 內資源 URL
URL imgUrl = getClass().getResource(resourcePath);
if (imgUrl == null) throw new Exception("資源不存在: " + resourcePath);
ImageIcon icon = new ImageIcon(imgUrl);
JButton btn = new JButton(icon);
getContentPane().add(btn);
} catch (Exception e) {
e.printStackTrace();
}
}
}
<APPLET CODE="ImageButtonApplet.class"
CODEBASE="."
ARCHIVE="test.jar"
WIDTH="200" HEIGHT="200">
</APPLET>
CODEBASE=".":類別檔與 JAR 同目錄ARCHIVE="test.jar":瀏覽器下載並快取 JARHTMLConverter 轉換後可支援 Java Plug-intest.jar
├── ImageButtonApplet.class
└── img/
└── Logo.gif
使用 jar tf test.jar 確認結構,資源路徑必須與程式碼 getResource("/img/Logo.gif") 完全一致(區分大小寫)。
public class ResourceUtil {
public static URL getResource(Class> clazz, String path) {
// 支援絕對/相對路徑,自動處理前綴
String normalized = path.startsWith("/") ? path : "/" + path;
URL url = clazz.getResource(normalized);
if (url == null) {
// 嘗試 ClassLoader (適合模組化環境)
url = clazz.getClassLoader().getResource(normalized.substring(1));
}
return url;
}
public static ImageIcon loadImageIcon(Class> clazz, String path) {
URL url = getResource(clazz, path);
return (url != null) ? new ImageIcon(url) : null;
}
}
ImageIO.read(url):載入 BufferedImage 進行像素處理AudioClip clip = Applet.newAudioClip(url):載入音效getResourceAsStream():讀取文字設定檔、屬性檔、JSON 等Font.createFont(Font.TRUETYPE_FONT, url.openStream()):載入自訂字型jar tf 驗證)/ 代表 JAR 根目錄,無 / 代表類別套件目錄module-info.java 宣告 opens package