本文将编写一个基于jsf标签的名为"locallydefinedbean"插件。jsf标签可以在运行时将bean变量加到jsp-jsf而中,在这里,我们将通过使用jsf el(所谓jsf el就是jsf expression language)来模拟在设计时向jsp-jsf添加变量的过程。下面是具体的实现过程。
1. 首先,使用file->new->project->plug-in project来建立一个空的插件工程,这个工程使用jbuilder2007提供的默认值,并在工程名中输入myplugin。如图1所示:
![]() 图1 |
2. 打开工程浏览器,切换到dependencies标签。并加入如图2所示的依赖库。
![]() 图2 dependencies标签 |
3. 通过file->new->class建立一个java类: locallydeclaredbeanfactory.,并使这个类从org.eclipse.jst.jsf.context.symbol.internal.provisional.source.abstractcontextsymbolfactory继承。如图3所示。
![]() 图3 |
4. 打开java源码编辑器。你将看到两个根据抽象类自动产生的方法。然后将supports方法替换为我们自己的supports方法。代码如下:
| public boolean supports(iadaptable context) { return context.getadapter(istructureddocumentcontext.class) != null; } |
上面的代码表示只能调用istructureddocumentcontext工厂。
5. 使用如下的代码替换internalcreate中的代码
| protected isymbol internalcreate(string symbolname, int scope, iadaptable context, list problems) { //得到上下文 final istructureddocumentcontext scontext =(istructureddocumentcontext) context.getadapter(istructureddocumentcontext.class); // 为上下文建立一个dom上下文 final idomcontextresolver domresolver = istructureddocumentcontextresolverfactory.instance.getdomcontextresolver(scontext); if (domresolver != null) { final node curnode = domresolver.getnode(); // node必须是xml属性 if (curnode instanceof attr) { final attr attr = (attr) curnode; final node owningelement = attr.getownerelement(); if (owningelement != null) { iproject iproject = workspaceresolver.getproject(); if (iproject != null) { return handlesymbolcreation(symbolname, scontext, attr, owningelement, iproject); } } } } return null; } |
6. 下面让我们加一个private方法来建立符号(symbol)。
| private isymbol handlesymbolcreation(final string symbolname, final istructureddocumentcontext context, final attr attr, final node owningelement, final iproject project) { // 建立tab库 final itaglibcontextresolver resolver =istructureddocumentcontextresolverfactory.instance .gettaglibcontextresolver(context); if (resolver == null || !resolver.canresolvecontext(context)) { return null; } final string uri = resolver.gettagurifornodename(owningelement); ibeaninstancesymbol beansymbol = null; // 处理核心标签库 if ("http://oracle.com/tutorial/fake/taglib".equals(uri)) { final string elementname = owningelement.getlocalname(); final string attrname = attr.getname(); if ("locallydeclaredbean".equals(elementname)) { if ("var".equals(attrname)) { final namednodemap attrmap = owningelement.getattributes(); final node basenamenode = attrmap.getnameditem("classname"); if (basenamenode instanceof attr) { // 得到bean的名字 final string classname = ((attr)basenamenode).getvalue(); // 建立一个新的空bean实例符号 beansymbol = symbolfactory.einstance.createibeaninstancesymbol(); beansymbol.setname(attr.getvalue()); try { ijavaproject javaproject = javacore.create(project); itype type = javaproject.findtype(classname); if (type != null) { ijavatypedescriptor2 javatypedescriptor = symbolfactory.einstance.createijavatypedescriptor2(); javatypedescriptor.settype(type); beansymbol.setjavatypedescriptor(javatypedescriptor); } } catch (javamodelexception jme) { } } } } } return beansymbol; } |
7. 加入注释(annotations)元数据
我们的最终目标是加入如下的标签:
| <t:locallydeclaredbean var="x" classname="beans.mybean"/> |
声明一个变量"x"来处理"beans.mybean"。为了通过框架,我们必须使用无数据来注释t::locallydeclaredbean。
首先让我们在工程中建立一个metadata文件夹。在通过file->new->file来建立一个metadata.xml文件,如图4如示。
![]() 图4 |
打开这个文件,在其中输入如下的内容。
| <?xml version="1.0" encoding="utf-8"?> <grammar-annotation xmlns="http://org.eclipse.jsf.core/grammarannotationschema" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://org.eclipse.jsf.core/grammarannotationschema d://eclipsewtplatest//wtpworkspace//org.eclipse.jst.jsf.core//schema//grammar-annotations.xsd "> <cm-element name="locallydeclaredbean"> <cm-attribute name="var"> <property name="contributes-value-binding"> < value>true</value> </property> <property name="value-binding-scope"> <value>request</value> </property> <property name="value-binding-symbol-factory"> <value>tutorial.locallydeclaredbean</value> </property> </cm-attribute> </cm-element> </grammar-annotation> |
8. 实现扩展
为了声明我们的标签工厂,需要使用两个扩展点。首先我们需要扩展注释扩展点,这个扩展点用于声明我们刚才定义框架的元数据。其次,我们将注册这个工厂的id。
打开plugin.xml,并且选择extensions标签,单击"add"按钮,选择org.eclipse.jst.jsf.contentmodel.annotations.annotationfile扩展点。选择这个扩展点后,通过右键菜单new->annotationfile加入一个注释文件。并输入相应的uri和location。如图5所示。
![]() 图5 |
这个扩展点可以通知这个框架当一个标签库使用uri:http://oracle.com/tutorial/fake/taglib查询元数据时查看metadata.xml文件。接下来,我们需要声明一个扩展点:org.eclipse.jst.jsf.context.symbol.contextsymbolfactory,这个扩展点声明了我们的工厂,并且给它一个唯一的id。如图6所示。
![]() 图6 |
我们要注意的是在factory属性中的值要匹配"value-binding-symbol-factory"属性的值。否则这个框架不能发现我们的工厂类。
我们现在已经完成了标签的定义。但我们还需要构造一个动态的web工程,以便测试我们的作品。
为了建立一个动态的web工程,我们首先为这个插件建立一个新的运行时工作台。我们可以通过run->run…来建立这个工作台。如图7所示。
![]() 图7 |
一但这个工作台被装载,就可以使用new->project->other来建立一个dynamic web 工程了。
在建立完动态web工程后,在meta-inf文件夹上通过右键菜单中的new->file新键一个叫tutorial.tld的文件。它的内容如下:
| <?xml version="1.0" encoding="gb2312" ?> <!doctype taglib public "-//sun microsystems, inc.//dtd jsp tag library 1.2//en" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>tutorial</short-name> <uri>http://oracle.com/tutorial/fake/taglib</uri> <tag> <name>locallydeclaredbean</name> <tag-class>foo</tag-class> <tei-class>foo</tei-class> <body-content>empty</body-content> <attribute> <name>var</name> <required>true</required> <rtexprvalue>false</rtexprvalue> </attribute> <attribute> <name>classname</name> <required>true</required> <rtexprvalue>false</rtexprvalue> </attribute> </tag> </taglib> |
最后,在src目录中建立一个叫beans.mybean的文件,它的内容如下:
| package beans;public class mybean { public string getfooproperty() { return "foo!"; } } |
现在让我们在webcontent目录中建立一个用于测试的jsp文件。然后在这个jsp文件中输入如下的内容:
| <%@page contenttype="text/html"%> <%@page pageencoding="gb2312"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@taglib uri="http://java.sun.com/jsf/core" prefix="f"%> <%@taglib uri="http://java.sun.com/jsf/html" prefix="h"%> <%@taglib uri="http://oracle.com/tutorial/fake/taglib" prefix="t" %> <!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=gb2312"> <title>jsp 页</title> </head> <body> <f:view> <h1>jsp 页</h1> <t:locallydeclaredbean var="x" classname="beans.mybean"/> <h:outputtext value="#{}"/> </f:view> </body> </html> |
现在让我们注意几点。首先,我们有一个前缀为"t"的标签库。其次,我们已经使用被定义为"x"的locallydeclaredbean标签声明了一个bean。这就是我们上面所描述的"beans.mybean"。
现在让我们测试它。将你的光标放到outputtext标签的空"{}"中,然后按ctrl-space调用内容助手。你将看到如图8所示的界面。
![]() 图8 |
你可以在bean的属性中在x后加一个".",如图9所界面将被显示。
![]() 图9 |









闽公网安备 35060202000074号