记一次在webx中velocity新建自定义指令的过程

简介: ### 记一次在webx中velocity新建自定义指令的过程 ![screenshot](http://img2.tbcdn.cn/L1/461/1/b59c6597d3f90168126d63ebc63f967ef1dc348f) webx和velocity就不介绍了。 都很熟悉。本文是记录在webx中增加唉velocity自定义指令的方法。 起因是在velocity渲染模板的时候

记一次在webx中velocity新建自定义指令的过程

screenshot
webx和velocity就不介绍了。 都很熟悉。本文是记录在webx中增加唉velocity自定义指令的方法。
起因是在velocity渲染模板的时候,我们使用了#esc_noesc(variable)做转义,当这个渲染变量未定义时,变量会渲染为${content},而使用$!{variable}渲染简单字符变量时,若未定义则会被渲染为空字符串,这两个场景对于js变量的渲染都会引起js语法错误造成js无法tryCatch, 由于这种后端变量渲染的逻辑大多用于主干代码, 一旦出现错误就会引起白屏,整个页面挂掉(不要问我怎么知道。。) 如下图:
variableError
escError

于是我想到能否将所有针对js的输出变量都赋有一个"''"。 避免页面直接白屏,且写大量的errorLog触发报警。
我们知道, velocity中可以设置自定义指令。
我们定义好一个基于Directive的子类,然后在directive.properties中配置即可。
这是一个简单的自定义指令,作用是获取context某个属性的值:

class CustomVelocityDirective extends Directive{

    static String methodName = 'getValue';

    @Override
    public String getName() {
        return methodName ;  // 指令名 对应到velocity模板中的 methodName()
    }
    @Override
    public int getType() {
        return LINE; // 指令类型 包括 LINE/BLOCK
    }

    @Override
    public void init(RuntimeServices rs, InternalContextAdapter context, Node node) throws TemplateInitException {
        super.init(rs, context, node); // 初始化模板
    }

    @Override
    public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {    
        SimpleNode getChildren = (SimpleNode) node.jjtGetChild(0); //获取指令传参
        String variableName = (String)sn_region.value(context); // 获取到传参的文字 or 对象
        Object value = context.get(variableName).toString();  //获取该key对应到context的属性
        writer.write(value); // 打印输出内容
        return true;  //打印成功
    }
}

配置directive.properties属性,声明这个指令

userdirective=xxx.xxx.YourDirectiveClass  // 可用逗号分隔指定多个

使用时:

// some HTML..   
#getValue("name")   // 打印value  by: context.put("name", "value")
// some HTML..   

参考文章

webx中的做法

以上是Velocity的做法, 看起来还比较容易, 简单明了。 然而现实很骨感, 现实是我们用的是webx。 当我们面对webx,一切都不那么好了。

首先我试着在我们的properties文件中增加userdirective=xxx.xxx.YourDirectiveClass, 当然, 一切并不成功。看来照搬velocity的做法在webx中并不合适。

接着在网上看到一篇文章 (在velocity中自定义标签) 在velocity中自定义标签 应该是唯一一篇提到了webx设置velocity自定义标签的文章。 照着做了一遍, 可是在如何声明Schema文件的地方有点含糊。 想起了我们在webx中用到过escape指令, 于是找相应的声明代码, 最终找到类似的EscapeSupport。 依葫芦画瓢,照着做了,也大致摸清了webx中增加自定义velocity插件的方法。

Velocity:

设置: userdirective=xxx.xxx.YourDirectiveClass

Webx:

新建parser文件的声明

在META-INF下新建services-template-engines-velocity-plugins.bean-definition-parsers 文件,指定Schema文件和Parser, 内容是:

custom-directive=xxxx.xxx.xxx.xxxParser   
新建Schema文件

按照META-INF/services/template/engines/velocity/plugins 目录,新建一个xsd文件,声明Schema,(由于我没有其他属性,所以Schema文件异常简单):

<xsd:element name="variable-parser" type="VariableParserType">
    <xsd:annotation>
        <xsd:documentation><![CDATA[some ducumentation]]></xsd:documentation>
        </xsd:annotation>
    </xsd:element>
    <xsd:complexType name="VariableParserType" />
定义Parser类:
class VariableDefinitionParser extends AbstractSingleBeanDefinitionParser<VariableParserSupport> {
    @Override
    protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
    }
}
定义VelocityPlugin的实现类:
public class VariableParserSupport implements VelocityPlugin {
    public void init(VelocityConfiguration configuration) throws Exception {
        configuration.getProperties().addProperty("userdirective", CustomVelocityDirective.class.getName());
    }
    public Resource[] getMacros() throws IOException {
        return new Resource[] { };
    }
}
在webx-component-and-root.xml中增加声明
<services:template searchExtensions="true">
        <tpl-engines:velocity-engine templateEncoding="UTF-8" strictReference="false" path="/templates/${component}">
            <global-macros>
                <name>global/*.vm</name>
            </global-macros>
            <plugins>
                <vm-plugins:custom-directive />   // 写入我们自定义的标签的
                <vm-plugins:escape-support defaultEscape="html">
                 I   <noescape>
                        <if-matches pattern="^control\." />
                        <if-matches pattern="^screen_placeholder" />
                        <if-matches pattern="^stringEscapeUtil\.escape" />
                        <if-matches pattern="^csrfToken\.(get)?hiddenField" />
                        <if-matches pattern="^tbToken\.(get)?hiddenField" />
                        <if-matches pattern="^securityUtil\.(richtext|jsEncode|ignoretext)" />
                    </noescape>
                </vm-plugins:escape-support>
            </plugins>
        </tpl-engines:velocity-engine>
        <tpl-engines:freemarker-engine templateEncoding="UTF-8" path="/templates/${component}"/>
        <tpl-engines:jsp-engine path="/templates/${component}"/>
    </services:template>

在做到倒数第二不,声明Support类的时候, 我看到画龙点睛的一句:

configuration.getProperties().addProperty("userdirective", CustomVelocityDirective.class.getName());  

而我们做了这么多,就是为了这一句。 对应到velocity就只是这行代码::

userdirective=xxx.xxx.YourDirectiveClass

最后知道真相的我眼泪掉下来。。。。。。

当然,velocity的自定义指令在webx中是作为一个velocity插件的方式使用。 在webx中由于多了一套约定的Schame,导致在webx中增加自定义组件变得复杂数倍,当然功能也有所增强(例如支持宏)。
并且针对我想要的failover场景,也许新增自定义指令的方法并不是最优解,也许有其他成熟的webx解决方案。 也希望有人能指出,一起交流。

最后感谢下 @贾少天 的帮助。

参考资料:

1 WebX文档

  1. velocity自定义标签和指令variableError
目录
相关文章
|
XML Java 编译器
Maven下载与安装
一.下载安装 二.系统配置 三.配置maven项目工程 四.创建新项目
435 0
|
3月前
|
自然语言处理 监控 算法
8款卸载流氓软件推荐,阿香婆卸载,geek、HiBit ninstaller、SoftCnkiller、UninstallTool、RevoUnistaller、Wise Force Deleter,Wise Care 365
在卸载软件时,常会留下残留文件和注册表项,影响系统性能甚至导致安装失败。本文介绍了6款专业卸载工具,包括阿香婆卸载、Geek、HiBit Uninstaller等,能深度清理残留,提升电脑运行效率。
540 0
|
人工智能 算法 新能源
AI在能源管理中的应用:提升能源效率与可持续性
【9月更文挑战第24天】AI技术在能源管理中的应用,正以其独特的优势与潜力,引领着能源行业向更加智能化、高效化和可持续化的方向发展。随着技术的不断进步、政策的持续支持以及应用场景的不断拓展,AI技术将在能源管理中发挥更加重要的作用,为实现全球能源转型与可持续发展贡献更大力量。我们有理由相信,在AI技术的助力下,未来的能源管理将更加高效、智能和可持续。
1180 6
|
供应链 JavaScript API
简化数据迁移:API接口的应用
在现代商业环境中,数据迁移已经成为企业运营中不可或缺的一部分。随着技术的进步和市场的变化,企业需要将商品数据从一个系统迁移到另一个更高效或更具成本效益的系统。这一过程可以借助应用程序编程接口(API)来简化。以下是如何通过使用API接口来简化商品数据迁移过程的详细步骤。
|
定位技术 开发工具 数据安全/隐私保护
GIS数据格式坐标转换(地球坐标WGS84、GCJ-02、火星坐标、百度坐标BD-09、国家大地坐标系CGCS2000)
GIS数据格式坐标转换(地球坐标WGS84、GCJ-02、火星坐标、百度坐标BD-09、国家大地坐标系CGCS2000)
4324 1
|
人工智能 自然语言处理 测试技术
通义灵码多维度体验分享
一文带你多维度了解通义灵码
433 4
|
存储 自然语言处理 Java
速度与敏捷:解密Velocity的奥秘
速度与敏捷:解密Velocity的奥秘
374 0
【Python的魅力】:利用Pygame实现游戏坦克大战——含完整源码
【Python的魅力】:利用Pygame实现游戏坦克大战——含完整源码
|
前端开发 安全 Linux
React Native 打包 App 发布 iOS 及加固混淆过程
本文将介绍如何使用 React Native 打包并发布 iOS 应用到 App Store,并介绍了如何进行应用的加固和混淆过程。
|
Web App开发 存储 Ubuntu
你想在旧Android手机上装Linux系统吗?看这里
你想在旧Android手机上装Linux系统吗?看这里
你想在旧Android手机上装Linux系统吗?看这里