velocity自定义指令不生效问题解决之旅
一、背景现象
为了支持灵活的、可自定义的脱敏规则,工程拟采用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<String> 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");
}
/**
* 根据报文模板和<code>VelocityContext</code>,渲染出实际的业务报文
*
* @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<String> 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);
velocity自定义指令不生效问题解决之旅的更多相关文章
- vue自定义指令导致的内存泄漏问题解决
vue的自定义指令是一个比较容易引起内存泄漏的地方,原因就在于指令通常给元素绑定了事件,但是如果忘记了解绑,就会产生内存泄漏的问题. 看下面代码: directives: { scroll: { in ...
- android中ListView点击和里边按钮点击不能同时生效问题解决
今天遇到一个问题:android中ListView点击和里边button点击不能同时生效问题解决. 原因是: listView 在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得 ...
- Angularjs进阶笔记(2)-自定义指令中的数据绑定
有关自定义指令的scope参数,网上很多文章都在讲这3种绑定方式实现的效果是什么,但几乎没有人讲到底怎么使用,本篇希望聊聊到底怎么用这个话题. 一. 自定义指令 自定义指令,是Angularjs用来实 ...
- 浅析AngularJS自定义指令之嵌入(transclude)
AngularJS自定义指令的嵌入功能与vue的插槽十分类似,都可以实现一些自定义内容展现.在开始之前先简单介绍下自定义指令的transclude属性和AngularJS的内置指令ng-transcl ...
- 从零开始学 Web 之 Vue.js(二)过滤器,按键修饰符,自定义指令
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- angular自定义指令命名的那个坑
Directive 先从定义一个简单的指令开始. 定义一个指令本质上是在HTML中通过元素.属性.类或注释来添加功能.AngularJS的内置指令都是以ng开头,如果想自定义指令,建议自定义一个前缀代 ...
- 移动端H5长按事件 vue自定义指令
import Vue from 'vue' Vue.directive('longpress', function (el, binding){ var timer = null; var start ...
- vue 自定义指令的魅力
[第1103期]vue 自定义指令的魅力 点点 前端早读课 2017-11-08 前言 很多事情不能做过多的计划,因为计划赶不上变化.今日早读文章由富途@点点翻译分享. 正文从这开始- 在你初次接触一 ...
- vue之自定义指令
1.自定义指令的作用 除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令.注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件.然而,有的情况下,你仍 ...
随机推荐
- 关于jeesite的陷阱需要注意
jeesite,其框架主要为: 后端 核心框架:Spring Framework 4.0 安全框架:Apache Shiro 1.2 视图框架:Spring MVC 4.0 服务端验证:Hiberna ...
- centos7系统优化-转载
禁用SELINUX # grep -i ^selinux /etc/selinux/config SELINUX=enforcing SELINUXTYPE=targeted 注释掉上面2行,并增加 ...
- IDEA 代码生成插件 CodeMaker
Java 开发过程中经常会遇到编写重复代码的事情,例如说:编写领域类和持久类的时候,大部分时候它们的变量名称,类型是一样的,在编写领域类的时候常常要重复写类似的代码.类似的问题太多……这里介绍一个 I ...
- Django的安装和启动以及第一个工程的建立
---恢复内容开始--- 前提:已经安装了python和Anaconda (windows系统) 在Anaconda安装好之后,其文件夹下有一个叫做Anaconda Prompt的工具,类似windo ...
- [ZZ]新手学 appium-合集第一季度
原文地址: https://testerhome.com/topics/2599 新手学appium-合集第一季度地址如下: 1.新手学 appium-GUI 端搞起来:http://testerho ...
- nginx1.14.0版本location路径配置四种方式
假设下面四种情况分别用 http://192.168.1.1/proxy/test.html 进行访问. 第一种:location /proxy/ { proxy_pass http:// 12 ...
- 微服务与Spring Cloud资料
Microservices Using Spring Boot and Spring Cloud 微服务注册中心 Eureka 架构深入解读 50+ 顶级开源 Kubernetes 工具列表 Apol ...
- 负载均衡器技术Nginx和F5的优缺点对比
负载均衡器技术Nginx和F5的优缺点对比 博客分类: 应用服务 F5nginx 对于数据流量过大的网络中,往往单一设备无法承担,需要多台设备进行数据分流,而负载均衡器就是用来将数据分流到多台设备的 ...
- Linux安装python3.6
Linux安装python3.6 原地址:https://www.cnblogs.com/kimyeee/p/7250560.html Linux下安装Python3.6和第三方库 如果本机安装 ...
- java9 Local-variable type inference
var ls = Arrays.asList("1","2"); System.out.println(ls);