• 29 由表达式求值器


    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
  • 相关阅读:
    calendar.getTimeInMillis() 和 System.currentTimeMillis() 的区别
    微信小程序中使用 <web-view> 内嵌 H5 时,登录问题的处理方法
    小程序 TabBar 定制
    webpack 代码优化压缩方法
    react-router v4 按需加载的配置方法
    axios发送post请求,如何提交表单数据?
    react中键盘enter事件处理
    常用证件正则表达式
    react中input自动聚焦问题
    React Router v4 页面传值的三种方法
  • 原文地址:https://www.cnblogs.com/yangh2016/p/6343415.html
Copyright © 2020-2023  润新知