文档章节

MVEL实现java直接根据公式计算结果

V
 ValSong
发布于 2017/09/06 22:53
字数 651
阅读 106
收藏 3

工具类

import java.math.BigDecimal;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import org.mvel2.CompileException;
import org.mvel2.MVEL;
import org.mvel2.PropertyAccessException;


/**
 * 计算工具
 * 
 * @author valsong
 * @date Jul 24, 2017
 *
 */
public class CalculateUtils {

	/**
	 * 根据传入的公式和参数进行计算
	 * 
	 * @param formula
	 * @param variables
	 * @return
	 */
	public static <T> BigDecimal calculate(String formula, Map<String, T> variables) {
		if (SimpleStringUtils.isBlank(formula)) {
			throw new CalculateException("MVEL formula can't be null! formula : " + formula); // 公式不能为空
		}
		if (variables == null || variables.size() == 0) {
			throw new CalculateException("MVEL variables can't be null! variables : " + String.valueOf(variables)); // 参数不能为空
		}
	
		try {
			// 将公式中的变量全部转化为BigDecimal类型
			variables.entrySet().stream().filter(e -> e != null && e.getKey() != null && e.getValue() != null)
					.map(CalculateUtils::convert).collect(Collectors.toMap(Entry::getKey, Entry::getValue));

		} catch (NumberFormatException e) {
			throw new CalculateException(
					"MVEL can't convert to BigDecimal, please check the variables : " + String.valueOf(variables) + "!",
					e);
		} catch (Exception e) {
			throw e;
		}
		BigDecimal result = null;
		try {
			result = (BigDecimal) MVEL.eval(formula, variables);
		} catch (PropertyAccessException pae) {
			throw new CalculateException(
					"MVEL please check the formula :" + formula + " & variables : " + String.valueOf(variables) + "!",
					pae);
		} catch (CompileException ce) {
			throw new CalculateException("MVEL calculate error! ", ce);
		} catch (Exception e) {
			throw e;
		}
		return result;
	}


	/**
	 * 将参数转化为Bigdecimal类型
	 * 
	 * @param entry
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> Entry<String, T> convert(Entry<String, T> entry) {
		if (entry != null) {
			BigDecimal value = null;
			if (entry.getValue() instanceof BigDecimal) {
				value = (BigDecimal) entry.getValue();
			} else {
				value = NumberUtils.getNum(NumberUtils.getNum(entry.getValue()));
			}
			entry.setValue((T) value);
		}
		return entry;
	}

}

异常类


/**
 * 计算异常
 * 
 * @author Val Song
 * @date   Jul 28, 2017
 *
 */
public class CalculateException extends RuntimeException {
	private static final long serialVersionUID = 5162710183389028792L;

	/**
	 * Constructs a {@code CalculateException} with no detail message.
	 */
	public CalculateException() {
		super();
	}

	/**
	 * Constructs a {@code CalculateException} with the specified detail
	 * message.
	 *
	 * @param message
	 *            the detail message.
	 */
	public CalculateException(String message) {
		super(message);
	}

	/**
	 * Constructs a {@code CalculateException} with the specified detail
	 * message & cause
	 * 
	 * @param message
	 * @param cause
	 */
	public CalculateException(String message, Throwable cause) {
		super(message, cause);
	}

}

字符串工具类


/**
 * 字符串工具
 * 
 * @author valsong
 *
 */
public class SimpleStringUtils {

	/**
	 * 判断字符串不为空
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isNotBlank(String str) {
		return !isBlank(str);
	}

	/**
	 * 判断字符串为空
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isBlank(String str) {
		if (str == null || "".equals(str.trim())) {
			return true;
		}
		return false;
	}

	/**
	 *  去首尾空格
	 * 
	 * @param s
	 * @return
	 */
	public static <T> String trim(T s) {
		if (s instanceof String) {
			return s == null ? null : ((String) s).trim();
		} else {
			return s == null ? null : String.valueOf(s).trim();
		}
	}

	/**
	 * 下划线命名转驼峰式
	 * 
	 * @param str
	 * @return
	 */
	public static String toCamel(String str) {
		if (SimpleStringUtils.isBlank(str)) {
			return str;
		}
		StringBuffer buffer = new StringBuffer();
		str = str.toLowerCase().trim();
		char[] charArray = str.toCharArray();
		if (charArray != null) {
			for (int i = 0; i < charArray.length; i++) {
				if ('_' == charArray[i]) {
					i = i + 1;
					buffer.append(Character.toUpperCase(charArray[i]));
				} else {
					buffer.append(charArray[i]);
				}
			}
		}
		return buffer.toString();
	}

	/**
	 * 驼峰转下划线
	 * 
	 * @param str
	 * @return
	 */
	public static String toUnderline(String str) {
		if (SimpleStringUtils.isBlank(str)) {
			return str;
		}
		StringBuffer buffer = new StringBuffer();
		str = str.trim();
		char[] charArray = str.toCharArray();
		if (charArray != null) {
			for (int i = 0; i < charArray.length; i++) {
				if (Character.isUpperCase(charArray[i])) {
					buffer.append("_");
					buffer.append(Character.toLowerCase(charArray[i]));
				} else {
					buffer.append(charArray[i]);
				}
			}
		}
		return buffer.toString();
	}

}


测试类简单粗暴String Double Integer Bigdecimal 都能支持


public class CalculateUtilsTest {

    /**	
     * 20 * 100 - ( 30 -20 ) + 20 ^ 3 + 20/2
     */
    @Test
    public void calculateTest4() {

        String formula = "A * B - (C -D) + E.pow(F) + G / H";

        Map<String, Object> variables = new HashMap<>();
        variables.put("A", "20");
        variables.put("B", 100L);
        variables.put("C", 30.0D);
        variables.put("D", 20);
        variables.put("E", new BigDecimal("20"));
        variables.put("F", "3");
        variables.put("G", "20");
        variables.put("H", "2");

        BigDecimal result = CalculateUtils.calculate(formula, variables);
        Assert.assertTrue(new BigDecimal("10000.0").compareTo(result) == 0);
    }

}

© 著作权归作者所有

共有 人打赏支持
V
粉丝 0
博文 12
码字总数 7647
作品 0
黄浦
程序员
【Java】Fel计算引擎学习

一、前言 最近的项目中,有一个这种需求,系统中配置很多的公式,每个公式中都会有因子。比如:,计算的时候,把这两个因子替换掉,如,,然后通过java来计算出结果。 二、实现的方式 为了解...

kisscatforever
05/23
0
0
有关 SoftReference 的一些事实

Java 的 SoftReference 有很多年都没有被人惦记了。在 Javadoc 里, 它的描述是这样: ”虚拟机在抛出 OutOfMemoryError 之前会保证所有的软引用对象已被清除。此外,没有任何约束保证软引用将...

长源
2013/08/12
0
0
OutOfMemoryError: unable to create new native t...

一、认识问题: 首先我们通过下面这个 测试程序 来认识这个问题: 运行的环境 (有必要说明一下,不同环境会有不同的结果):32位 Windows XP,Sun JDK 1.6.0_18, eclipse 3.4, 测试程序: ...

Yohance
2013/06/07
0
1
解决 - java.lang.OutOfMemoryError: unable to crea...

工作中碰到过这个问题好几次了,觉得有必要总结一下,所以有了这篇文章,这篇文章分为三个部分:认识问题、分析问题、解决问题。 一、认识问题: 首先我们通过下面这个测试程序来认识这个问题...

Mr&Cheng
2013/02/28
0
0
3月14日圆周率日—使用并行计算求圆周率π

关于圆周率大家再熟悉不过了: 我们从课本上学习到早在一千多年前,祖冲之将圆周率计算到3.1415926到3.1415927之间…计算机诞生后,计算圆周率被用来检测计算机的硬件性能,昼夜燃烧cpu看会不...

fourinone
2013/03/14
0
25

没有更多内容

加载失败,请刷新页面

加载更多

OSX | SafariBookmarksSyncAgent意外退出解决方法

1. 启动系统, 按住⌘-R不松手2. 在实用工具(Utilities)下打开终端,输入csrutil disable, 然后回车; 你就看到提示系统完整性保护(SIP: System Integrity Protection)已禁用3. 输入reboot回车...

云迹
今天
4
0
面向对象类之间的关系

面向对象类之间的关系:is-a、has-a、use-a is-a关系也叫继承或泛化,比如大雁和鸟类之间的关系就是继承。 has-a关系称为关联关系,例如企鹅在气候寒冷的地方生活,“企鹅”和“气候”就是关...

gackey
今天
4
0
读书(附电子书)|小狗钱钱之白色的拉布拉多

关注公众号,在公众号中回复“小狗钱钱”可免费获得电子书。 一、背景 之前写了一篇文章 《小狗钱钱》 理财小白应该读的一本书,那时候我才看那本书,现在看了一大半了,发现这本书确实不错,...

tiankonguse
今天
4
0
Permissions 0777 for ‘***’ are too open

异常显示: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ......

李玉长
今天
5
0
区块链10年了,还未落地,它失败了吗?

导读 几乎每个人,甚至是对通证持怀疑态度的人,都对区块链的技术有积极的看法,因为它有可能改变世界。然而,区块链技术问世已经10年了,我们仍然没有真正的用上区块链技术。 几乎每个人,甚...

问题终结者
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部