`
sunshineman
  • 浏览: 5065 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

使用webx3 templateService渲染内容

 
阅读更多

   工作中我们经常会遇到这样的需求:

   1.发送一段消息并在web前端展示(例如工作台就是一个很好的场景)

 

   solution 1:

 

 

  String message="xx";
  sender.send(message);

 

   这个方法第一个硬伤,如果xx包含中文或者其他字符呢?

   前端看到的内容可能会出现乱码。

 

   第二个问题,如果message内容更很长,代码的可读性就变得很差了。

 

  solution 2:

 

String message=MessageResultCode.SHORT_MESSAGE.getMessage();
sender.send(message); 

  既然有中文的问题,我们就使用配置文件,ResultCode可以帮助我们解决这个问题,虽然如果内容长了配置文件

  会有些难看,但也还可以接受。甚至如果内容含有样式,链接,等等,我们也可以通过CDATA来解决。

 

  这个方法暂时看起来不错,不过pd似乎不让我们这么容易的完成任务。“那么我想在消息里显示下链路信息,比如链路名”。这个需求很合理,但是我们的solution 2似乎办不到。

 

   solution 3:

 

  我们知道webx3使用了velocity作为模板渲染引擎,所以何不把消息像velocity模板一样的渲染出来

 

   

       String template="message.vm"; 
       TemplateContext context = new MappedTemplateContext();
        context.put("link", link);
        context.put("chain", chain);
        //merge模板
        String message = templateService.getText(template, context);
        sender.send(message);

 代码其实很简单,新建一个模板,把所有变量放到context中去,再使用templateService渲染出来。

 我们看看供应链服务一个任务模板的例子:

 

  请审核供应链<a href="$!{link}">[$!{chain.name}]</a>编号[$!{chain.id}]-商家[$!{chain.supplierName}]-商品[$!{chain.productTitle}]
 
  那么template路径到底怎么指定呢?这是一个问题。在回答这个问题之前我们看看templateService是如何配置的

 

  

<services:template xmlns="http://www.alibaba.com/schema/services/template/engines" searchExtensions="true">
		<velocity-engine templateEncoding="UTF-8" strictReference="false" path="/templates/${component}">
			<global-macros>
				<name>macros.vm</name>
			</global-macros>
			<plugins>
				<vm-plugins:fasttext-support />
				<vm-plugins:renderable-support />
			</plugins>
		</velocity-engine>
	</services:template>

 

   事实上templateService 在渲染vm模板的时候使用velocity引擎来完成的

   我们看看templateService实现类的这个方法

   

private boolean findTemplateInTemplateEngine(TemplateMatcher matcher) {
        TemplateEngine engine = getTemplateEngine(matcher.getExtension());

        matcher.setEngine(engine);

        if (engine == null) {
            return false;
        }

        String templateName = matcher.getTemplateName();

        getLogger().trace("Searching for template \"{}\" using {}", templateName, engine);

        return engine.exists(templateName);
    }
 

   所以路径如何设置取决      于TemplateEngine 的path参数。我们看到path="/templates/${component}",${component}这个变量是webx3

 给每个子容器的名字,例如供应链服务叫chain。我们看下pipeline的配置

 

 

				<when>
					<pl-conditions:target-extension-condition extension="null, vm, jsp" />
					<performAction />
					<performTemplateScreen />
					<renderTemplate />
				</when>

 

   renderTemplate这个valve也是使用templateService来渲染模板。

   例如输入的模板名叫screen/detail.vm

   那么 templateService就会找/template/chain/screen/detail.vm这个文件。

   webx3的资源加载使用ResourceLoadingService

    而由于resources.xml文件里有如下配置

 

     

               <resource pattern="/templates">
			<res-loaders:file-loader basedir="${alibaba_lp_lpscm_templates}" />
		</resource>
 

   

   因此这个地址也就变成了${alibaba_lp_lpscm_templates}/template/chain/screen/detail.vm,

   ${alibaba_lp_lpscm_templates}是我们antx文件里配置的模板路径。

   这个工作原理适用于web层的东西,biz层使用templateService稍微有点区别,

   因为biz层使用了root容器的templateService因此,$component 的值取决于这段配置

 

   

   

  <services:property-placeholder>
        <services:property key="component">common</services:property>
    </services:property-placeholder>

  因此刚刚那个例子,我们需要把文件放在 ${alibaba_lp_lpscm_templates}/template/common/message.vm.

  当然你也可以修改配置以改变模板的位置,例如把common改成message

 

  

   <services:property-placeholder>
        <services:property key="component">message</services:property>
    </services:property-placeholder>

 

     那么文件需要放在 ${alibaba_lp_lpscm_templates}/template/mesage/message.vm.

 

     结束语

 

    pd说:“我想要显示下链路的创建时间,这个需要多少时间"

    开发说:"没问题,修改的话两分钟就够!"

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics