简单的自定义 JSF 标签

时间:2022-11-05 20:01:28

最近在琢磨金蝶 EAS BOS 的结构,顺带温习了一下 xml 配置的东西;又看到金蝶终于推出了用于移动界面的 Yun UI,于是脑洞略开,看看能不能做一个 Yun UI 的 JSF 标签库封装。
参照 https://www.tutorialspoint.com/jsf/jsf_custom_tag.htm 的说法,最重要的步骤,是在工程的 web.xml 中,为定义了标签的文件,新建一个 context-param 标签来存放。web.xml 的代码大概是这样的:

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
   <display-name>Archetype Created Web Application</display-name>
   <context-param>
      <param-name>javax.faces.PROJECT_STAGE</param-name>
      <param-value>Development</param-value>
   </context-param> 
   <!-- 重点在下面 -->
   <!-- 为自定义标签单独开设的 context-param -->
   <context-param>
      <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
      <!-- 这里指明了自定义标签文件相对于 web.xml 的存放位置 -->
      <param-value>/WEB-INF/tutorialspoint.taglib.xml</param-value>
   </context-param>
   <servlet>
      <servlet-name>Faces Servlet</servlet-name>
      <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
   </servlet>
   <servlet-mapping>
      <servlet-name>Faces Servlet</servlet-name>
      <url-pattern>*.jsf</url-pattern>
   </servlet-mapping>
</web-app>

然后就是写好自定义标签的声明文件,用来直接引用标签模板。按照上面的声明,我们把这个文件叫做 tutorialspoint.taglib.xml

<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">
<facelet-taglib>
   <!-- 在使用这些自定义标签的 JSF 页面中,需要将这些标签的 namespace 声明为下面的自定义网址 -->
   <namespace>http://tutorialspoint.com/facelets</namespace>
   <!-- 每个自定义标签,都需要一个单独的 tag -->
   <tag>
      <tag-name>buttonPanel</tag-name>
      <!-- 标签对应的模板文件的存放位置 -->
      <source>com/tutorialspoint/buttonPanel.xhtml</source>
   </tag>
</facelet-taglib>

然后就是标签模板,用来定义这个标签真正的内容。主要用了 ui:composition 标签来封装:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets">
   <h:body>
      <ui:composition> 
      <!-- 这里定义的 buttonPanel ,实际是2个 commandButton -->
      <!-- #{okLabel} 当作按钮的 value 使用,#{cancelLabel} 同理 -->
      <!-- 至于是否需要把布局、样式也一并封装到 buttonPanel 待定 -->
         <h:commandButton type="submit" value="#{okLabel}" />
         <h:commandButton type="reset" value="#{cancelLabel}" /> 
      </ui:composition>
   </h:body>
</html>

然后在下面客户要访问的 JSF 页面中,分别声明各标签所属的 namespace ,并且为自定义标签的属性赋值,就可以愉快地使用了:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- 给自定义标签库起个名字,比如这里叫做 tp,然后将自定义标签声明为 html xmlns 的下级标签 -->
<!-- 注意与其他标签库的冲突 -->
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:tp="http://tutorialspoint.com/facelets">
   <h:head>
      <title>JSF tutorial</title>           
   </h:head>
   <h:body>
      <h1>Custom Tags Example</h1>
      <!-- 生成的部件和定义的一样,由两个按钮组成 -->
      <!-- 两个按钮上的文字分别是 OK 和 Cancel -->
      <tp:buttonPanel okLabel="Ok" cancelLabel="Cancel" />
   </h:body>
</html>

贴个原网址的图,后续的文章就要讲怎么移植 Yun UI ,还有解析顺序和速度的问题了。
简单的自定义 JSF 标签

顺带…发现 08-09年那段时间的前端开发真是百花(fa)齐放啊,或者说越是“和平年代”其实可以选/ 想的更少,估计做完这个封装,后面会转向其他方面了