maven依赖
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <surefire.redirectTestOutputToFile>true</surefire.redirectTestOutputToFile> <groovy.version>2.1.6</groovy.version> <slf4j.version>1.7.5</slf4j.version> </properties> <dependencies> <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>${groovy.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> </dependencies>
代码:1、接口
package com.da.tool.util.expression; import java.util.Map; /** * 表达式处理器接口 */ public interface IExpressionProcessor { /** * 配置项 * @return */ IExpressionProcessor withConf(Map<String,Object> map); /** * 设置表达式 * @param expression * @return */ IExpressionProcessor withExpression(String expression); /** * 设置数据 名称:值 * @param data * @return */ IExpressionProcessor withData(Map<String,Object> data); /** * 根据表达式和值计算表达是的值 * @param <T> * @return */ <T> T calculationExpression(); }
2、实现类
package com.da.tool.util.expression.impl; import com.da.tool.util.expression.IExpressionProcessor; import groovy.lang.Binding; import groovy.lang.GroovyShell; import groovy.lang.Script; import org.codehaus.groovy.control.CompilerConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; /** * 表达式处理器类 */ public class ExpressionProcessor implements IExpressionProcessor{ private static final Logger LOGGER = LoggerFactory.getLogger(ExpressionProcessor.class); /** * 配置属性 */ private Map<String, Object> map; /** * 表达式 */ private String expression; /** * 数据 名称:值 * @param data * @return */ private Map<String, Object> data; private static final GroovyShell shell; private Script expressionScript; static { CompilerConfiguration cfg = new CompilerConfiguration(); cfg.setScriptBaseClass(Expression.class.getName()); shell = new GroovyShell(ExpressionProcessor.class.getClassLoader(), new Binding(), cfg); } /** * 无参构造方法 */ public ExpressionProcessor() { } @Override public ExpressionProcessor withConf(Map<String, Object> map) { this.map = map; return this; } @Override public ExpressionProcessor withExpression(String expression) { if(null == expression || expression.trim().equals("")){ LOGGER.error("expression is null or blank,can not generate rowkey"); return null; } this.expression = expression; try { expressionScript = shell.parse(expression); } catch (Exception e) { LOGGER.error("Parser expression [{}] error", expression, e); throw e; } return this; } @Override public ExpressionProcessor withData(Map<String, Object> data) { this.data = data; if(null == data){ LOGGER.error("data is null,can not generate rowkey"); return null; } return this; } @Override public String calculationExpression() { String rowkey = null; try { expressionScript.setBinding(new Binding(data)); rowkey = (String) expressionScript.run(); } catch (Exception e){ LOGGER.error("生成主键发生错误,请检查数据是否合法:{} ", data); return rowkey; } if (rowkey == null) LOGGER.error("存在一行数据无法生成rowkey,原始数据为:{}", data); return rowkey; } public Map<String, Object> getMap() { return map; } public String getExpression() { return expression; } public Map<String, Object> getData() { return data; } }
3、支持的表达式类
package com.da.tool.util.expression.impl; import groovy.lang.Script; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.Serializable; import java.lang.reflect.Method; import java.sql.Timestamp; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** */ public class Expression extends Script implements Serializable { private static final Logger LOGGER = LoggerFactory.getLogger(Expression.class); /** * 格式化时间类型 * * @author zhuchao 2016年1月25日 下午4:39:15 * @param time * @param pattern * @return */ public static String formatString(Object time, String pattern) { return String.format(pattern, time); } /** * 求hash值,并对hash取模,取模范围有rang和start确定 * * @author zhuchao 2016年1月25日 下午4:41:54 * @param s * @param rang * @param start * @return */ public static int hash(String s, int rang, int start) { return Math.abs(s.hashCode()) % rang + 1 + start; } /** * 对传入字符串进行hash并将hash得到的值按指定格式进行格式化并插入到字符串指定位置中 * * @author zhuchao 2016年1月26日 下午1:58:23 * @param s * @param rang * @param start * @param pattern * @param offset * @return */ public static String hashFormatAndInsert(String s, int rang, int start, String pattern, int offset) { return insert(offset, formatString(hash(s, rang, start), pattern), s); } /** * 字符串截取 * * @author zhuchao 2016年1月25日 下午6:50:24 * @param s * @param beginIndex * @param endIndex * @return */ public static String substring(String s, int beginIndex, int endIndex) { if(null==s || s.isEmpty()){ return ""; } String result = null; try{ result=s.substring(beginIndex,endIndex); }catch (StringIndexOutOfBoundsException e){ LOGGER.error("获取字符串{}的substring出现异常,异常信息为:{}",s,e.getMessage()); } return result; } /** * str为null或者“”是返回“” * @param str 字符串 * @param defaultValue 默认值 * @return str为null或者“”是返回“” 其它情况返回str本身 */ public static String emptyDefault(String str,String defaultValue){ if(null==str || str.isEmpty()){ return defaultValue; } return str; } /** * 插入s到src指定位置 * * @author zhuchao 2016年1月26日 上午11:40:47 * @param offset * @param s * @param src * @return */ public static String insert(int offset, String s, String src) { StringBuilder sb = new StringBuilder(src); sb.insert(offset, s); return sb.toString(); } /** * 去除两边的空格 * @param str * @return */ public static String trim(String str){return str.trim();} /** * 添加前缀 * @param srcStr * @param prefix * @return */ public static String addPrefix(String srcStr, String prefix){ return prefix+srcStr; } /** * 将rowkey表达式中的数据转换为string * @param obj * @return */ public static String toString(Object obj){ if(null==obj){ return ""; } return obj.toString(); } /** * 添加后缀 * @return */ public static String addSuffix(String srcStr, String suffix){ return srcStr+suffix; } /** * 求hash值,并对hash取模,取模范围有rang和start确定 * @param rang 取模范围 * @param start 开始值 * @param num 输出位数 * @param s 根据column数组哈希 * @return hash值 */ public static String hashStringArray(int rang, int start,int num,Object... s) { int hashValue=0; for (Object object : s) { hashValue=hashValue+object.hashCode(); } String hashStringValue= Math.abs(hashValue) % rang + start+""; int size = hashStringValue.length(); while (size < num) { size++; hashStringValue = "0" + hashStringValue; } return hashStringValue; } /** * 交通rowKey生成规则定制函数,通过时间字段获取年月,目前不支持字段类型为String,字段值为空时返回null * @param time 时间字段,一般为pass_time * @return 返回格式为yyMM的字符串 */ public static String transDate(Object time){ if(time==null ) return null; if(time instanceof String){ LOGGER.error("主键函数中transDate的入参不能是String类型,请确认json中的字段类型!"); } DateFormat sdf = new SimpleDateFormat("yyMM"); return sdf.format(time); } /** * 交通rowKey生成规则定制函数,将日期类型转换为long型 * @param time 时间字段,一般为pass_time * @return 返回格式为long */ public static Long dateToLong(Object time){ Long date= Timestamp.valueOf(String.valueOf(time)).getTime(); return date; } /** * fieldStrs 字符串拼接一起,然后获取hash值,再对remainder取余 * 散列值 3位,(年月+数据类型+日+全局ID)的哈希值除999取余 * @param remainder * @param fieldStrs * @return */ public static String hashRemainder(int remainder,String ...fieldStrs){ String sumStr = ""; for (String fieldStr : fieldStrs) { sumStr=sumStr+fieldStr; } int remainderHash=sumStr.hashCode()%remainder; remainderHash=(remainderHash<0)? -remainderHash:remainderHash; String result=String.valueOf(remainderHash); int num=result.length(); int size = String.valueOf(remainder).length(); while (num < size) { num++; result = "0" + result; } return result; } /** * 把字符串转化成指定位数size * 不足,前面补充supplementValue * 超出,isCutFront为true截取前面的size位 * @param original * @param size * @param supplementValue * @return */ public static String supplementStringFront(String original,int size,String supplementValue){ return cutString(original,size,true,supplementValue,true); } /** * @param original * @param size * @param supplementValue * @param front * @return */ /** * 把字符串转化成指定位数size * 不足,isFrontSupplement为true,前面补充supplementValue,isFrontSupplement为false,后面补充supplementValue * 超出,isCutFront为true截取前面的size位,isCutFront为false,截取后面的size位 * @param original * @param size * @param isFrontSupplement * @param supplementValue * @param isCutFront * @return */ public static String cutString(String original,int size,Boolean isFrontSupplement,String supplementValue,Boolean isCutFront){ int length=original.length(); String result = null; if(length==size){ result=original; }else if(length<size){ if(isFrontSupplement){ result=supplementValue+original; while(result.length()<size){ result=supplementValue+result; } }else{ result=original+supplementValue; while(result.length()<size){ result=result+supplementValue; } } } //length>size else{ if(isCutFront){ result=original.substring(0,size); }else { result=original.substring(original.length()-size,original.length()); } } return result; } //rowKey需要的类型转换(智能算法组实现) public static String transformRowKey(String date){ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd"); Date date1 = null; try { date1 = sdf.parse(date); } catch (ParseException e) { LOGGER.error("transformRowKey生成rowkey失败,日期格式转换出错!"); } return sdf1.format(date1); } /* * (non-Javadoc) * * @see groovy.lang.Script#run() */ @Override public Object run() { // show usage Method[] methods = Expression.class.getDeclaredMethods(); StringBuilder sb = new StringBuilder(); for (Method method : methods) { sb.append(method); } return sb.substring(0, sb.length() - 1); } }
4、测试类
package com.da.tool.util.expression;
import com.da.tool.util.expression.impl.ExpressionProcessor;
import java.util.HashMap;
import java.util.Map;
/**
* 表达式生成器例子
*/
public class ExpressionProcessorExample {
public static void main(String[] args) {
//表达式
String expression="addSuffix(A,'_suffix') + 123";
//数据
Map<String,Object> data= new HashMap<>();
data.put("A", "preffix");
String rowKey;
IExpressionProcessor expressionProcessor = new ExpressionProcessor()
.withExpression(expression)
.withData(data);
rowKey = expressionProcessor.calculationExpression();
System.out.println(rowKey);
}
}
执行结果: preffix_suffix123