我在使用带有自定义DownloadServiceListener的JNLP applet以及同时版本化的jar文件时遇到了问题 .

项目结构如下:

/
+ WEB-INF/
|        + lib/
|        |    + jnlp-servlet.jar
|        + web.xml
+ lib/
|    + progress-0.1.jar
|    + MyApplet-1.0.jar
|    + applet.jnlp
|    + version.xml
+ index.jsp

我的web.xml的内容:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
          http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
           version="2.5">

    <!-- JNLP download servlet-->
    <servlet>
        <servlet-name>JnlpDownloadServlet</servlet-name>
        <servlet-class>jnlp.sample.servlet.JnlpDownloadServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>JnlpDownloadServlet</servlet-name>
        <url-pattern>/lib/*</url-pattern>
    </servlet-mapping>

</web-app>

我的applet.jnlp文件如下所示:

<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="6.0+" codebase="$$codebase" href="$$name">
    <information>
        <title>MyApplet</title>
        <vendor>My AG</vendor>
        <homepage href="http://www.nowhere.com"/>
        <description>XYZ</description>
    </information>
    <update check="always" policy="always"/>
    <resources>
        <j2se href="http://java.sun.com/products/autodl/j2se" version="1.6+" initial-heap-size="128m" max-heap-size="128m"/>
        <property name="jnlp.versionEnabled" value="true"/>

    <jar href="progress.jar" version="0.1" download="progress"/>
    <jar href="MyApplet.jar" version="1.0" main="true"/>

    </resources>
    <applet-desc name="MyApplet"
                 main-class="test.MyApplet"
                 width="800" height="600"
                 progress-class="progress.CustomProgress">
        <param name="bgcolor" value="28,28,28"/>
        <param name="textcolor" value="255,222,123"/>
    </applet-desc>
</jnlp>

要显示applet,我使用以下JSP-File(index.jsp):

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head><title>Simple jsp page</title></head>
  <body style="margin: 0;">

    <object width="100%" vspace="0" hspace="0" height="100%" align="top" name="MyApplet"
            classid="clsid:CAFEEFAC-0016-0000-0026-ABCDEFFEDCBA" onerror="alert('Invalid Java Version..')">
        <param value="MyApplet" name="name">
        <param value="application/x-java-applet;jpi-version=1.6.0_26" name="type">
        <param value="test.MyApplet.class" name="code">
        <param value="lib/MyApplet-1.0.jar" name="archive">
        <param value="true" name="mayscript">
        <param value="false" name="scriptable">
        <param value="lib/applet.jnlp" name="jnlp_href">
        <param value="true" name="progressbar">
        <param value="238,244,248" name="boxbgcolor">
        <param value="255,255,255" name="boxfgcolor">
        <param value="255,255,227" name="progresscolor">
        <param value="Loading MyApplet - please wait" name="boxmessage">
        <param value="-Djnlp.versionEnabled=true -Xms256m -Xmx256m" name="java_arguments">
        <param value="false" name="classloader_cache">
        <param value="true" name="separate_jvm">
        <comment>
            <embed width="100%" vspace="0" hspace="0" height="100%" align="top" separate_jvm="true"
                   classloader_cache="false" java_arguments="-Djnlp.packEnabled -Xms256m -Xmx256m"
                   boxmessage="Loading MyApplet - please wait" boxfgcolor="255,255,255"
                   boxbgcolor="238,244,248" progressbar="true"
                   pluginspage="http://java.sun.com/products/plugin/index.html#download"
                   jnlp_href="lib/applet.jnlp" scriptable="false" mayscript="true"
                   archive="lib/MyApplet-1.0.jar" code="test.MyApplet.class"
                   type="application/x-java-applet;jpi-version=1.6.0_26"
                   name="MyApplet" onerror="alert('Invalid Java version')">
        </comment>
    </object>
</body>
</html>

以及版本映射的文件(version.xml):

<?xml version="1.0"?>
<jnlp-versions>
  <resource>
    <pattern>
      <name>MyApplet.jar</name>
      <version-id>1.0</version-id>
    </pattern>
    <file>MyApplet-1.0.jar</file>
  </resource>
  <resource>
    <pattern>
      <name>progress.jar</name>
      <version-id>0.1</version-id>
    </pattern>
    <file>progress-0.1.jar</file>
  </resource>
</jnlp-versions>

DownloadServiceListener的实现(它是/(Sun)示例的精确副本(除了没有使用图像):

package progress;

import javax.jnlp.DownloadServiceListener;
import java.awt.Container;
import java.awt.Color;
import java.awt.BorderLayout;
import javax.swing.*;
import java.net.URL;
import java.applet.AppletStub;

public class CustomProgress implements DownloadServiceListener {
    Container surfaceContainer = null;
    AppletStub appletStub = null;
    JProgressBar progressBar = null;
    JLabel statusLabel = null;
    boolean uiCreated = false;

    public CustomProgress(Object surface) {
       init(surface, null);
    }

    public CustomProgress(Object surface, Object stub) {
        init(surface, stub);
    }

    public void init(Object surface, Object stub) {
        try {
            surfaceContainer = (Container) surface;
            appletStub = (AppletStub) stub;
        } catch (ClassCastException cce) {
            cce.printStackTrace();
        }
    }

    public void downloadFailed(java.net.URL url, java.lang.String version) {        
    }

    public void progress(URL url, String version, long readSoFar, long total, int overallPercent) {
        // check progress of download and update display
        updateProgressUI(overallPercent);

    }

    public void upgradingArchive(java.net.URL url, java.lang.String version, int patchPercent, int overallPercent) {
        updateProgressUI(overallPercent);
    }

    public  void validating(java.net.URL url, java.lang.String version, long entry, long total, int overallPercent) {
        updateProgressUI(overallPercent);
    }

    private void updateProgressUI(int overallPercent) {
        if (!uiCreated && overallPercent > 0 && overallPercent < 100) {
            // create custom progress indicator's UI only if 
            // there is more work to do, meaning overallPercent > 0 and < 100
            // this prevents flashing when RIA is loaded from cache
            create(); 
            uiCreated = true;            
        }
        if (uiCreated) {
            progressBar.setValue(overallPercent);
        }
    }

    private void create() {
        JPanel top = createComponents();
        if (surfaceContainer != null) {
            // lay out the loading progress indicator UI in the given Container
            surfaceContainer.add(top, BorderLayout.NORTH);
            surfaceContainer.invalidate();
            surfaceContainer.validate();
        }
    }

    private JPanel createComponents() {
        JPanel top = new JPanel();
        top.setBackground(Color.WHITE);
        top.setLayout(new BorderLayout(20, 20));

        // get applet parameter using an instance of the AppletStub class
        // "tagLine" parameter specified in applet's JNLP file
        String tagLine = "";
        if (appletStub != null) {
            tagLine = appletStub.getParameter("tagLine");
        }
        String lblText = "<html><font color=red size=+2>JDK Documentation</font>
" + tagLine + "
</html>"; JLabel lbl = new JLabel(lblText); top.add(lbl, BorderLayout.NORTH); // use JSObject.getWindow(null) method to retrieve a reference to // the web page and make JavaScript calls. Duke logo displayed if // displayLogo variable set to "true" in the web page // String displayLogo = "true"; // if (displayLogo.equals("true")) { // lbl = new JLabel(); // ImageIcon logo = createImageIcon("images/DukeWave.gif", "logo"); // lbl.setIcon(logo); // top.add(lbl, BorderLayout.EAST); // } statusLabel = new JLabel("<html><font color=green size=-2>Loading applet...</font></html>"); top.add(statusLabel, BorderLayout.CENTER); progressBar = new JProgressBar(0, 100); progressBar.setValue(0); progressBar.setStringPainted(true); top.add(progressBar, BorderLayout.SOUTH); return top; } /** Returns an ImageIcon, or null if the path was invalid. */ protected static ImageIcon createImageIcon(String path, String description) { java.net.URL imgURL = CustomProgress.class.getResource(path); if (imgURL != null) { return new ImageIcon(imgURL, description); } else { System.err.println("Couldn't find file: " + path); return null; } } }

最后但并非最不重要的是,我的(非常基本的)小程序:

package test;

import javax.swing.*;

public class MyApplet extends JApplet {
    @Override
    public void init() {
        add(new JLabel("This is an applet .. "));
    }
}

如您所见,一切都尽可能简单.. :)

现在,如果我部署Web应用程序,然后访问文件index.jsp,则会发生以下情况:有两个可用的Java控制台,一个用于“DownloadServiceListener”,另一个用于“真实”小程序 . 在第一个,可以找到以下消息:

生成自定义进度时出错:java.lang.ClassNotFoundException:progress.CustomProgress

第二个控制台为空,小程序正确显示,显示文本:“这是一个小程序......” .

我的访问日志中有以下条目:(请注意,在每次测试之前已清除整个java缓存) .

24/08/2011:14:57:09 +0200 'GET /AppletTest/ HTTP/1.1' 200 - 24/08/2011:14:57:09 +0200
127.0.0.1 24/08/2011:14:57:12 +0200 'GET /AppletTest/lib/applet.jnlp HTTP/1.1' 200 1041 24/08/2011:14:57:12 +0200
127.0.0.1 24/08/2011:14:57:13 +0200 'GET /AppletTest/lib/MyApplet__V1.0.jar HTTP/1.1' 404 - 24/08/2011:14:57:13 +0200
127.0.0.1 24/08/2011:14:57:13 +0200 'GET /AppletTest/lib/progress__V0.1.jar HTTP/1.1' 404 - 24/08/2011:14:57:13 +0200
127.0.0.1 24/08/2011:14:57:13 +0200 'GET /AppletTest/lib/progress.jar?version-id=0.1 HTTP/1.1' 200 3987 24/08/2011:14:57:13 +0200
127.0.0.1 24/08/2011:14:57:13 +0200 'GET /AppletTest/lib/MyApplet.jar?version-id=1.0 HTTP/1.1' 200 2460484 24/08/2011:14:57:13 +0200
127.0.0.1 24/08/2011:14:57:13 +0200 'GET /AppletTest/lib/progress.jar HTTP/1.1' 404 - 24/08/2011:14:57:13 +0200
127.0.0.1 24/08/2011:14:57:13 +0200 'GET /AppletTest/lib/progress.jar HTTP/1.1' 404 - 24/08/2011:14:57:13 +0200
127.0.0.1 24/08/2011:14:57:13 +0200 'GET /AppletTest/lib/MyApplet.jar HTTP/1.1' 404 - 24/08/2011:14:57:13 +0200
127.0.0.1 24/08/2011:14:57:13 +0200 'GET /AppletTest/lib/MyApplet.jar HTTP/1.1' 404 - 24/08/2011:14:57:13 +0200
127.0.0.1 24/08/2011:14:57:13 +0200 'GET /AppletTest/lib/progress.jar HTTP/1.1' 404 - 24/08/2011:14:57:13 +0200
127.0.0.1 24/08/2011:14:57:13 +0200 'GET /AppletTest/lib/progress.jar HTTP/1.1' 404 - 24/08/2011:14:57:13 +0200
127.0.0.1 24/08/2011:14:57:13 +0200 'GET /AppletTest/lib/MyApplet.jar HTTP/1.1' 404 - 24/08/2011:14:57:13 +0200
127.0.0.1 24/08/2011:14:57:13 +0200 'GET /AppletTest/lib/MyApplet.jar HTTP/1.1' 404 - 24/08/2011:14:57:13 +0200
127.0.0.1 24/08/2011:14:57:14 +0200 'GET /AppletTest/lib/applet.jnlp HTTP/1.1' 304 - 24/08/2011:14:57:14 +0200

当我查看“Java控制面板”时,会出现小程序“MyApplet”,并且所有jar文件都按预期加载 .

当我删除“jnlp.versionEnabled”-property时,跳过jar-entries的版本参数,并将版本号添加到jar-file-names,然后自定义DownloadServiceListener完美地工作 .

有可能,这两件事(版本化的jar文件和自定义DSL)不能一起使用吗?我错过了什么?有任何想法吗?