下午,试用了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" );