JSF 1.2 的开源实现好像还不多。MyFaces 刚出了 1.2.0 Core,扩展组件方面,Oracle ADF 捐了一些组件给 apache,名字叫 Trinidad,看了一下,好像还不错的样子,但风格不大合口味,需要修改。
金蝶也来凑热闹,把 ExtJS 包装了一下,做成 JSF 组件,就叫 OperaMasks。稳定性不知如何,前段时间玩了下它的在线demo,没多久就见它的 Apusic 服务器抛了个 OutOfMemoryError...
公司有个项目打算改用 JSF 1.2,界面用 Yui-Ext。JSF 的实现使用 Sun RI,另外使用 Seam + Facelets。不过 Sun 的实现实在没什么组件,需要自己写一些。于是和另外一个同事做了些工作,把 Ext 的组件包装成 JSF 组件。
每个 Ext 组件除了输出HTML 代码之外,还要输出Ext 的 JavaScript代码,
以做一个 UIInput 的组件为例,定义两个方法,用于产生 JavaScript代码,如下:
- public abstract class ExtInput extends UIInput {
- /**
- * encodeBegin 时产生 JavaScript代码
- */
- public String String getBeginningScript() {
- return null;
- }
- /**
- * encodeEnd 时产生 JavaScript代码
- */
- public String String getEndingScript() {
- return null;
- }
- @Override
- public void encodeBegin(FacesContext context) throws IOException {
- super.encodeBegin(context);
- ScriptManager.register(getBeginningScript());
- }
- @Override
- public void encodeEnd(FacesContext context) throws IOException {
- super.encodeEnd(context);
- ScriptManager.register(getEndingScript());
- }
- }
继承 ExtInput 类的组件,要输出JavaScript,
只需重写 getBeginningScript() 和 getEndingScript() 方法。
为什么要把输出 JavaScript 代码的功能写在 Component 里面而不是放在 Renderer 呢?
没特别的原因,其实放在Renderer效果是一样的......
上面的代码中使用了一个类 ScriptManager,
它的作用是把所有Ext 组件的 JavaScript 存起来,页面结束时再输出(不知会不会很耗内存...)。
当然,在 encodeBegin 和 encodeEnd 中直接输出 JavaScript 也可
但这样的话,页面的HTML 代码中会穿插很多 Ext 的 JavaScript 代码,不大好看。
ScriptManager:
- /**
- * JavaScript 管理器
- *
- * @author Tendy
- *
- */
- public final class ScriptManager {
- private static ThreadLocal<stringbuilder></stringbuilder> scriptBuffer = new ThreadLocal<stringbuilder></stringbuilder>() {
- @Override
- protected StringBuilder initialValue() {
- return new StringBuilder(128);
- }
- };
- /**
- * 注册 JavaScript
- * @param script - JavaScript 代码
- */
- public static void register(String script) {
- if (script != null && script.length() > 0)
- scriptBuffer.get().append(script);
- }
- /**
- * 获取 JavaScript 代码
- * @return
- */
- public static String getRegisteredScript() {
- return scriptBuffer.get().toString();
- }
- /**
- * 清除 JavaScript
- */
- public static void clear() {
- scriptBuffer.remove();
- }
- }
如果使用这个 ScriptManager,需要写一个简单的组件,在页面最后输出 ScriptManager 所存的 JavaScript 代码,
并清空这些代码。
有了ExtInput 这个基类,就可以开始包装那些 input 类的组件了,例如 Ext 的 DateField。