用JBuilder2007開發擴展JSF標簽的插件
本文將編寫一個基于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所示:
2. 打開工程瀏覽器,切換到dependencies標簽。并加入如圖2所示的依賴庫。
3. 通過File->New->Class建立一個Java類: LocallyDeclaredBeanFactory.,并使這個類從org.eclipse.jst.jsf.context.symbol.internal.provisional.source.AbstractContextSymbolFactory繼承。如圖3所示。
4. 打開Java源碼編輯器。你將看到兩個根據抽象類自動產生的方法。然后將supports方法替換為我們自己的supports方法。代碼如下:
上面的代碼表示只能調用IstructuredDocumentContext工廠。
5. 使用如下的代碼替換internalCreate中的代碼
6. 下面讓我們加一個private方法來建立符號(Symbol)。
7. 加入注釋(annotations)元數據
我們的最終目標是加入如下的標簽:
聲明一個變量"x"來處理"beans.MyBean"。為了通過框架,我們必須使用無數據來注釋t::locallyDeclaredBean。
首先讓我們在工程中建立一個metadata文件夾。在通過File->New->File來建立一個metadata.xml文件,如圖4如示。
打開這個文件,在其中輸入如下的內容。
8. 實現擴展
為了聲明我們的標簽工廠,需要使用兩個擴展點。首先我們需要擴展注釋擴展點,這個擴展點用于聲明我們剛才定義框架的元數據。其次,我們將注冊這個工廠的ID。
打開plugin.xml,并且選擇Extensions標簽,單擊"Add"按鈕,選擇org.eclipse.jst.jsf.contentmodel.annotations.annotationFile擴展點。選擇這個擴展點后,通過右鍵菜單New->annotationFile加入一個注釋文件。并輸入相應的uri和location。如圖5所示。
這個擴展點可以通知這個框架當一個標簽庫使用uri:http://oracle.com/tutorial/fake/taglib查詢元數據時查看metadata.xml文件。接下來,我們需要聲明一個擴展點:org.eclipse.jst.jsf.context.symbol.contextSymbolFactory,這個擴展點聲明了我們的工廠,并且給它一個唯一的ID。如圖6所示。
我們要注意的是在factory屬性中的值要匹配"value-binding-symbol-factory"屬性的值。否則這個框架不能發現我們的工廠類。
我們現在已經完成了標簽的定義。但我們還需要構造一個動態的Web工程,以便測試我們的作品。
為了建立一個動態的Web工程,我們首先為這個插件建立一個新的運行時工作臺。我們可以通過Run->Run…來建立這個工作臺。如圖7所示。
一但這個工作臺被裝載,就可以使用New->Project->Other來建立一個Dynamic Web 工程了。
在建立完動態Web工程后,在META-INF文件夾上通過右鍵菜單中的New->File新鍵一個叫tutorial.tld的文件。它的內容如下:
最后,在src目錄中建立一個叫beans.MyBean的文件,它的內容如下:
建立一個測試JSP
現在讓我們在WebContent目錄中建立一個用于測試的JSP文件。然后在這個JSP文件中輸入如下的內容:
現在讓我們注意幾點。首先,我們有一個前綴為"t"的標簽庫。其次,我們已經使用被定義為"x"的locallyDeclaredBean標簽聲明了一個Bean。這就是我們上面所描述的"beans.MyBean"。
現在讓我們測試它。將你的光標放到outputText標簽的空"{}"中,然后按Ctrl-Space調用內容助手。你將看到如圖8所示的界面。
你可以在Bean的屬性中在x后加一個".",如圖9所界面將被顯示。
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!"; } } |
建立一個測試JSP
現在讓我們在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 |