一、概述
JAF(JavaBeans Activation Framework)JavaBeans活动框架的目的在于统一处理不同数据格式的方法(不管数据格式为简单文本还是由图片、声音、视频甚至其它”活动"内容共同组成的复合文档)。在这个意义上,JAF对Java的作用正如插件对Web浏览器的作用。JAF使得Java对象与编码数据流之间的映射变得非常容易。
JAF完成于1998年,当时JavaBean非常流行,Swing非常热门,Servlet刚刚出现,J2EE平台还没有。那时Sun需要一个用于文件浏览器和JavaMail的标准发现API,此需要推动了JAF的创建。“发现”指可以动态找到正确的组件以处理任意但类型化了的数据的机制。特别是作为发现API来开发JAF,以便使GUI开发人员能够为文档和图像数据动态地发现浏览器和编辑器。
发现取决于注册的类型,注册可以将每一文件类型与对应的应用程序建立关联。简单的说,JAF提供了用于动态发现可视窗口部件以处理由MIME文件头描述的各种数据的架构。当用于SAAJ这样的非可视系统时,JAF可以将Java类型映射到将它们无缝转换到数据流的特殊处理程序,从而允许SAAJ将Java对象自动转换成由SWA MIME部分包含的原始数据。
二、核心框架
1. 资源类型DataSource类
资源至少要知道自己的类型,当然我们可以通过后缀简单直接获取类型(参考MIME Types介绍)。类似:
text/html html htm HTML HTM
text/plain txt text TXT TEXT java c c++ pl cc h
image/gif gif GIF
image/ief ief
image/jpeg jpeg jpg jpe JPG
image/tiff tiff tif
也可以直接设置类型,接口如下:
String | getContentType() | This method returns the MIME type of the data in the form of a string. |
InputStream | getInputStream() | This method returns an InputStream representing the data and throws the appropriate exception if it can not do so. |
String | getName() | Return the name of this object where the name of the object is dependant on the nature of the underlying objects. |
OutputStream | getOutputStream() |
DataSource类拥有完成委托操作所需要的全部功能。当使用DataSource或URL参数构造DataHandler时,DataHandler要使用DataSource而不是DCH。
JAF定义了两个标准的DataSource对象,即FileDataSource对象和URLDataSource对象。某些DataSource实现用于动态发现它们的MIME类型。例如,FileDataSource用MIME类型注册表发现它的MIME类型。JAF中的默认MIME类型注册表是mimetypes.default文件,该文件包含在JAF二进制JAR文件中。
2.资源对应的处理程序DataHandler类
资源对应的处理程序意思是:只有该处理程序能够理解和处理资源数据(首选处理)。但在JAF中一个设计理念是如何让JAF向JavaBean靠拢(JavaBean相关内容参考http://java.sun.com/javase/technologies/desktop/javabeans/ ,这也是为什么叫JavaBean Activation Framewor的缘故),所以在设计中会发现很多资源<——>对象之间的转化的内容,不过大家要分清楚JAF主要是干什么的——一个数据处理的框架。核心就是:JAF是一个资源<——>处理程序关联的框架。
JAF架构的核心是javax.activation.DataHandler类。DataHandler类定义了三个构造函数:
1)Public DataHandler(DataSource ds)
2)Public DataHandler(java.net.URL url)
3)Public DataHandler(Object obj, String mimeType)
当使用前两个构造函数时,数据处理会委托到DataSource接口的一个子类型,使用第三个构造函数时,数据处理委托到一个动态发现的内容处理程序并使用此处理程序。
如果DataHandler是用DataSource对象构造的,那么它将首先试图试图将getContent()方法委托到一个DCH,如果它没有找到DCH,会返回一个从DataSource中得到的InputStream。有趣的是,DataHandler总是试图首先委托到一个DCH,即便是用DataSource创建DataHandler也是如此。
上述说明的问题看似简单,但实际上非常重要,它说明了getContent()方法的作用。getContent()方法要返回一个表示附件的Java对象,DataSource的InputStream只作为最后一种手段来返回。从DCH中返回的对象类型取决于DCH的编码方式。
3.具体处理细节DataContentHandler类
谈到规范都是一些接口、抽象类和框架类,但具体实现究竟是什么呢?此接口用于实现将Java对象流转换成数据流,或将数据流转换成Java对象。
DataContentHandler类的每一个子类(即每一个DCH)均用于自动将Java对象的专用类型转换为流,以及将流转换成Java对象。如某个DCH能够将java.awt.Image对象转换为JPEG或GIF编码流,或者进行反向转换。DCH的缺点是它们的使用范围通常受到很大的限制,每一个DCH只能将一个对象类型转换成一种类型的数据流。
与DCH不同,DataSource对象只处理数据流。用户要用DataSource从某种类型的资源中读数据流,并将数据流写入DataSource。此时重点放在了流上而不是Java对象类型上。从而DataSource具有很大的通用性,其缺点为不易使用,因为用户直接处理的是流而不是Java对象。
典型代码如下:
FileDataSource fds = new FileDataSource(filename);
DataHandler dh = new DataHandler(fds);
//DataHandler dh = new DataHandler(new URL(filename));
//view是什么意思,为什么通过view能够拿到特定的资源操作JavaBean?
CommandInfo bi = dh.getCommand("view");
if (bi == null) {
System.out.println("no viewer found, exiting");
System.exit(1);
}
frame = new Frame("Viewer");
frame.add((Component)dh.getBean(bi));
frame.setSize(new Dimension(400,300));
frame.show();
这里的设计模式就是Command模式,Command模式就是通过命名来查找服务类和实例化的一种模式,其实如何查找、如何配置Command命名和实现类之间的映射是JAF实现的关键内容。javax.activation.CommandMap类就是这个关键查找的类,目前默认的实现是javax.activation.MailcapCommandMap,而这在Sun的参考实现中已经出现com.sun的信息,并且默认是从配置文件中检索。我们自己的实现可以通过DataHandler.setCommandMap直接注入自己的CommandMap。
另外为什么View就代表显示组件呢?典型的配置如下:
application/x-wombat;
\x-java-View=com.foo.WombatViewBean;
\x-java-edit=com.foo.WombatEditBean;
\x-java-print=com.foo.WombatPrintBean;
\x-java-content-handler=com.foo.WombatDataContentHan;
参考:http://blog.csdn.net/kissqw/article/details/6555860
http://blog.sina.com.cn/s/blog_61583c540100dw42.html