天道不一定酬所有勤
但是,天道只酬勤

Webx PullService分析

写在前面:上周在做项目的时候遇到这样一种情况,就是我在vm模板里面接收到后端传过来的数据,数据格式是一个字符串,字符串是使用逗号隔开的一些监控点信息的名字,我需要在前端将这个字符串分割,然后分别对每一个监控点信息名字加上链接。当时第一想法是使用js实现,但是发现js没办法实现我的需求(至少我做不到),因为本身我拿到的字符串就是在一个对象的某一个属性,而这个对象我又是从List里面遍历出来的。代码如下:

#foreach ( $defination in $data )                   
    <tr>
        <!--<td>$velocityCount</td>-->
        <td ><!--此处使用$!defination.monitors获取监控描述字符串--></td>
   </tr>
#end

有人会说,为什么不在后台直接将字符串分割,然后拼接上超链接在传到前端直接输出呢,我没这么做的原因是:第一、这么做是有风险的、第二、我也没办法这么做。首先看看我的另外一篇博文解决webx的xss和csrf漏洞,文中我们提到,将html、js、css代码传到前端,前端不做任何处理就输出这是有安全漏洞的。所以,只能想办法在前端进行超链接的拼接,好在集团有关于这个的解决方案:pull service

一、 概述

pull service的功能是将对象置入模板中。被pull service放到模板中的对象,不需要应用程序的干预即可直接使用。如果模板没有用到某个对象,则不会产生创建该对象的开销。看起来,这些对象像是被模板主动“拉”进context的,而不是由应用程序push进context中的。这就是pull service名称的来源。

1.1. 为什么需要pull service? 通常我们在做一个页面时,需要处理一些常见的操作,如:日期转换字符串处理生成动态URL生成CSRF Tooken获取上下文状态表单验证等。要完这些操作,我们通常使用JEE设计模式中的视图助手(view helper)来完成,如:在JSP中是通过java bean的方式来封装这些处理逻辑,并在需要的地方引用这个java bean的相应方法,从而实现这些操作的重用。 java bean虽然解决了我们碰到的这些问题,但缺少统一的配置以及这些对象实例的生命周期管理(如:单例、request、session等级别)。这时,我们就需要引入一个类似于java bean的机制来辅助我们页面的开发,并增加统一配置与生命周期管理。

二、设计

Pull service的最终表现是由一组具有不同功能与作用域的pull tool,并为这些pull tool提供统一的配置、生命周期管理,使之可以方便的注入的我们的view层上下文,从而满足我们view层的渲染辅助。

2.1. Pull tools作用域 global :就是singleton,在系统启动时创建实例 request :在每个request的第一次访问该tool时,自动创建实例

注意,ToolFactoryToolSetFactory本身一定是singleton的。但他们所创建的tool对象的作用域,是由ToolFactoryToolSetFactory.isSingleton方法决定的。

2.2. 单个tool和tool set 单个tool,由ToolFactory创建,每个factory创建一个tool tool集合,由ToolSetFactory创建,每个factory创建一组tool。这种接口赋予ToolSetFactory自主决定将创建哪些对象的权力。例如在webx中,uri broker tool将一组URI brokers对象放到模板中。

2.3. 延迟创建实例 对于global tooltool set,全部实例均在系统启动时创建。 对于非global tooltool set,所有实例均在每次request时,第一次访问该tool时创建。如果一个tool set将创建一组tools,那么每一个tool都是延迟创建的。

2.4. RuntimeToolSetFactory 这是一个特殊的tool set factory接口,主要用于兼容以前的pull service实现。这个factory会在每次request中,都调用createToolSet方法生成toolset实例。因此它的性能不如tool set factory。正常情况下不推荐使用它。

2.5. Pull tools全局性 parent context中的tools被所有子context中的tools共享。但子context可以覆盖父context中的同名tools(注:只是以当前context的tool的引用为优先,不影响父context中的实例)。

三、使用

3.1 配置: 在webx.xml文件中加入:

3.2 ID命名约定

<tool id="xxx">,(明确指定)此时id=xxx
<tool class="com....HelloTool>,此时id=hello
<tool class="com....Hello>,此时id=hello
<hello-tool > 此时id=hello

3.3 由以下的内置工具tool构成:

arrayUtil ==>> ArrayUtil
classLoaderUtil ==>> ClassLoaderUtil
classUtil ==>> ClassUtil
enumUtil ==>> EnumUtil
exceptionUtil ==>> ExceptionUtil
fileUtil ==>> FileUtil
localeUtil ==>> LocaleUtil
mathUtil ==>> MathUtil
messageUtil ==>> MessageUtil
objectUtil ==>> ObjectUtil
streamUtil ==>> StreamUtil
stringEscapeUtil ==>> StringEscapeUtil
stringUtil ==>> StringUtil
systemUtil ==>> SystemUtil

四、使用方式:

了解完了pull service,我们回到刚开始那个问题,如何解决我的需求:

#foreach ( $defination in $data )                   
    <tr>
        <!--<td>$velocityCount</td>-->
        <td>
            #foreach ($monitor in $!stringUtil.split($!defination.monitors,","))
      <a href="/monitor/businessLin/globalViewCommon.htm?appName=$monitor">$monitor,</a>
    #end
        </td>
   </tr>
#end

看到 中的那段代码了么,首先我们使用stringUtil类的split方法将字符串按照逗号进行拆解,拆解之后返回的是一个字符串数组,然后我们用foreach遍历这个数组,拿到每一个元素进行字符串的拼接。这段代码:$!stringUtil.split($!defination.monitors,",")就是使用pull service代码。上面我们介绍过得哪些内置工具都可以拿过来直接使用。

五、自定义

定义工具类:

public class IconTool {

    public String getIconCodeByKey(String key){
        String iconCode = "";
        if(StringUtil.isNotBlank(key)){

            switch (key) {
            case "site":
                iconCode ="xe629;";
                break;
            default:
                iconCode ="xe63b;";
                break;
            }
            return iconCode;
        }
        return "xe65e;";
    }
}

配置文件:

<services:pull xmlns="http://www.alibaba.com/schema/services/pull/factories">
        <utils />
        <csrfToken />
        <page-tool />
        <control-tool />
        <uris-tool />
        <bean-tool id="iconTool" class="com.alibaba.intl.apaas.common.util.IconTool" scope="global" />
        <factory id="unicornTool" class="com.alibaba.intl.web.unicorn.pull.webx3.UnicornPullTool" />
    </services:pull>

使用: 在vm文件中调用: $!iconTool.getIconCodeByKey($page.iconCode)

(全文完)
欢迎关注HollisChuang微信公众账号
打赏

如未加特殊说明,此网站文章均为原创,转载必须注明出处。HollisChuang's Blog » Webx PullService分析

分享到:更多 ()

HollisChuang's Blog

联系我关于我