velocity自定义函数_velocity自定义指令不生效问题解决之旅

本文介绍了在使用Velocity自定义`mask`和`substr`指令时遇到的问题,详细描述了背景现象,包括自定义指令的实现。在部署后,发现这些自定义指令未生效。作者通过分析原因,排除了配置问题,并通过查看日志找到了问题根源:全局的Velocity初始化导致自定义指令未被加载。最终,通过改用VelocityEngine实现jar包间的资源隔离,成功解决了问题。
摘要由CSDN通过智能技术生成

一、背景现象

为了支持灵活的、可自定义的脱敏规则,工程拟采用velocity实现该目的,为此,自定义了:

mask、substr两个指令,其中

mask实现

public class MaskDirective extends Directive {

@Override

public String getName() {

return "mask";

}

@Override

public int getType() {

return LINE;

}

@Override

public boolean render(InternalContextAdapter ctx, Writer writer, Node node) throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {

//fieldName

SimpleNode snField = (SimpleNode) node.jjtGetChild(0);

String maskChar = (String)snField.value(ctx);

snField = (SimpleNode) node.jjtGetChild(1);

int count = (int)snField.value(ctx);

StringBuilder buff = new StringBuilder();

for(int i = 0; i < count; i++) {

buff.append(maskChar);

}

writer.write(buff.toString());

return true;

}

}

substr实现

public class SubstrDirective extends Directive {

@Override

public String getName() {

return "substr";

}

@Override

public int getType() {

return LINE;

}

@Override

public boolean render(InternalContextAdapter ctx, Writer writer, Node node) throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {

//fieldName

SimpleNode snField = (SimpleNode) node.jjtGetChild(0);

String fieldValue = (String)snField.value(ctx);

if(fieldValue == null || fieldValue.length() == 0){

return false;

}

int items = node.jjtGetNumChildren();

int startIdx = Integer.MIN_VALUE;

int endIdx = fieldValue.length();

if(items < 1){

return false;

}

try{

snField = (SimpleNode) node.jjtGetChild(1);

startIdx = (int)snField.value(ctx);

if(items > 2){

snField = (SimpleNode) node.jjtGetChild(2);

endIdx = (int)snField.value(ctx);

if(endIdx > fieldValue.length()){

endIdx = fieldValue.length();

}

}

if(startIdx >= endIdx){

return false;

}

StringBuilder buff = new StringBuilder();

if(items > 2){

writer.write(fieldValue.substring(startIdx,endIdx));

}else{

if(startIdx < 0){

startIdx = startIdx + fieldValue.length();

}

writer.write(fieldValue.substring(startIdx));

}

return true;

}catch(Exception e){

return false;

}

}

}

velocity初始化方法:

public final class VelocityHelper {

private Set userExtDirective ;

private final static String K_USERDIRECTIVE = "userdirective";

private final static VelocityHelper VH = new VelocityHelper();

private VelocityHelper(){

}

public static final VelocityHelper getInstance(){

return VH;

}

/**

* 初始化

*/

public void init() throws Exception{

Properties prop = new Properties();

StringBuilder buff = new StringBuilder();

for(String s : userExtDirective){

buff.append(s.trim()).append(",");

}

LogHelper.trace("start VelocityHelper.init[" + buff.toString() + "]");

prop.setProperty(K_USERDIRECTIVE, buff.toString().substring(0, buff.length()-1));

Velocity.init(prop);

LogHelper.trace("end VelocityHelper.init");

}

/**

* 根据报文模板和VelocityContext,渲染出实际的业务报文

*

* @param context 业务上下文信息

* @param template 模板

* @return

* @throws IOException

*/

public String evaluate(String template, final VelocityContext context) throws IOException {

Writer writer = new StringWriter();

try {

Velocity.evaluate(context, writer, StringUtil.EMPTY_STRING, template);

return writer.toString();

} finally {

IOUtils.closeQuietly(writer);

}

}

/**

*

* @param userExtDirective

*

*/

public void setUserExtDirective(Set userExtDirective){

this.userExtDirective = userExtDirective;

}

}

部署到服务器后,以下表达式始终未得到替换:#substr($maskField, 0, 3)#mask('*', 4)#substr($maskField, -4)

二、原因分析

开始怀疑是配置等问题,经过以下方法尝试均为解决问题:

1、怀疑spring xml配置问题----未解决

2、硬编码指令,在构造函数塞入指令----未解决

无奈,登录服务器grep velocity 得到了以下的输出(其中之一),茅塞顿开。

2019-02-02 07:49:52,315 [  - /// - ] INFO  assemble.VMRender - resource=class path resource [velocity/velocity.properties]

Velocity.ini及Velocity.evalute均是全局单一模式,既然有人捷足先登,自然不在做第二次初始化。

三、解决方案

采用VelocityEngine替换Velocity,实现jar包间隔离,独立管理自己的资源。

private VelocityEngine velocityEngine = null;

velocityEngine = new VelocityEngine(prop);

velocityEngine.evaluate(context, writer, StringUtil.EMPTY_STRING, template);

标签:return,自定义,之旅,int,snField,writer,velocity,public,String

来源: https://www.cnblogs.com/frazeworld/p/10347496.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值