下午,试用了SkinLF(http://www.l2fprod.com),感觉非常好,程序的外观得到了很大的改善,还可以根据自己的需要随意调整得到自己想要的外观,但是要将SkinLF应用到Web Start中还有点问题。这是因为,web start使用到的资源必须包装成jar文件,以的形式定义到jnlp资源文件中,而SkinLF的外观配置文件是zip形式的。也许有人会说,把zip转化成jar文件就可以了。是的,想象中这应当是可以的,可是实际情况不是如此,你会发现使用ClassLoader.getResourceStream("themepack.jar")的时候返回了Null,SkinLookAndFeel.loadLookAndFeel()会异常Stream closed.
  调试之后发现,即使是在客户端,在Eclipse中运行的时候,如果不把themepack.jar定义到ClassPath中,也是无法加载的。
  我想这是一个普遍的问题,根据我的理解,如果其他资源,比如图片、xml文件、属性文件等等能够被加载,themepack.jar也应该被加载。事实上应该是这样,但是关键在于SkinLF需要采用ZipInputStream解析zip(jar)文件,这时情况就不一样了。具体的原因目前没有搞清楚。
  在网上找了半天,终于发现一个Open Source的组件:Rachel,使用它很轻易就可以解决上面提到的问题。
  Rachel(http://rachel.sourceforge.net)是一个为解决Web start装载资源困难而开发的组件。它提供了两种方法解决资源装载问题。
     方法一,使用class://URL Handler。
      这个方法采用新的URL协议:class://从jar文件中获取资源。
     Step 1,注册新的URL Handler,以支持class://协议(protocal)。
     例子:java.net.URL.setURLStreamHandlerFactory( new RachelUrlFactory() );
     Step 2,采用class://协议构造URL,从jar文件中读取资源。
  语法:class:///
  例子:
class://test.LookAndFeelTest/themepack.zip
class://com.l2fprod.gui.plaf.skin.SkinLookAndFeel/themepack.zip
 
  注意:这里,是Rachel用来定义资源文件所在的jar的,后面的相对于jar中的根目录而言。上述例子中的jar的结构如下:
      test.jar:
      test/LookAndFeelTest.class
      com/l2fprod/gui/plaf/skin/SkinLookAndFeel.class
      themepack.zip
      images/example.png
      html/index.htm
 
  Step 3,采用java.net.URL获取资源。
      例子:
    URL url = new URL("class://test.LookAndFeelTest/themepack.zip");
    URL url = new URL("class://test.LookAndFeelTest/html/index.html");
    URL url = new URL("class://test.LookAndFeelTest/images/example.png");
    URL url = new URL("class://com.l2fprod.gui.plaf.skin.SkinLookAndFeel/themepack.zip");
    SkinLookAndFeel.setSkin( SkinLookAndFeel.loadThemePack(url) );
 
  方法二,在程序中嵌入多线程的,小型的http server。
  Step 1,把你的资源放到jar中。
  Step 2,在每一个jar中增加一个anchor class,帮组server定位资源所在的jar文件,这点类似于方法一class:///的的。
  例子:
   public class CrossRefAnchor
   {
     public CrossRefAnchor() {}
   }
 
  CrossRefAnchor没有任何的实际意义,只是为了帮组定义资源所在的jar。
  Step 3,为每一个包含资源的jar用ClassResourceLoader注册到WebResourceManager。
  例子:
   WebResourceManager roots = WebResourceManager.getInstance();
   roots.addResourceLoader( new ClassResourceLoader( CrossRefAnchor.class ) );
   roots.addResourceLoader( new ClassResourceLoader( JavaDocAnchor.class ) );
 
  Step 4,启动Server。
  例子:
   try
   {
     WebServer http = new WebServer( 7272, roots );
     http.start();
   }
   catch( IOException e )
   {
     e.printStackTrace();
   }
 
  Step 5,采用URL从server获取资源。
  例子:
   URL crossRefUrl = new URL( "http://localhost:7272/crossref/index.html" );
   URL url = new URL( "http://localhost:7272/test.LookAndFeelTest/themepack.zip" );
   URL url = new URL( "http://localhost:7272/test.LookAndFeelTest/html/index.html" );
   URL url = new URL( "http://localhost:7272/test.LookAndFeelTest/images/example.png" );