利用ScriptEngineManager实现字符串公式灵活计算

简介: 在开发中我们可能会出现大量的公式计算,而这些公式可能并不确定。比如用户今天说a=b+c 然而下次说公式不正确 应该是a=d+e如果单纯的在代码中把这些公式写死 实现,后期修改维护工作量显然会增加好多。

在开发中我们可能会出现大量的公式计算,而这些公式可能并不确定。

比如用户今天说a=b+c 然而下次说公式不正确 应该是a=d+e

如果单纯的在代码中把这些公式写死 实现,后期修改维护工作量显然会增加好多。

下面就简单的介绍一种实现方法的思路:

我们知道js的eval()方法可以执行字符串的代码 而恰好jdk6增加了对脚本语言的支持 我们可以利用这个特性对计算实现简单化的处理 

下面举个例子

例如有个公式  A+B*C  其中A=1,B=2,C=3

我们可以将公式的A B C替换成数字 转换为 1+2*3 最后就可以得到结果了

刚刚接触到ScriptEngine这个东西的时候仅仅了解其eval()方法 ,于是我利用了上述例子的思路去实现将字母替换成相应的数字去得到数字公式进而得到运算结果。

那么替换的方法当然是用正则去替换了,java中String对象有个replaceAll()方法可以实现。

当时想这个正则可是琢么了一会儿呢。然而我这种实现却白忙活了,因为后期发现没有必要这么麻烦

具体怎么实现大家可以想想看,我就不具体介绍了,有了思路比什么都重要。

然而过了一段时间,我在面试的时候和一个前辈聊天时,前辈告诉我不用自己写正则去替换,js中本来就有对象,也支持对象的运算,所以直接往里放对象就可以。

后来我自己查了查资料,发现果然可以:

为了可以实现打印出中间参与计算的变量,我利用反射实现了获取值的方法

下面就是代码的实现:

    public static void Calculation(){
        Student stu=new Student();
        stu.setAge(10);
        stu.setName("zhangsan");
        stu.setSex(false);

        // 上边是student对象


        Class claz=stu.getClass();
        String className= claz.getSimpleName();
        //String formula="Student.name+Student.age+10";  //1
        String formula="function test(){ if(Student.age==10){ return 12;} }"; //2
        System.out.println("the formula is:"+formula);

        //获取对象名称和值
        for(Field field: claz.getDeclaredFields()){
            try {
                //打开私有访问
                //field.setAccessible(true);
                String fieldName = field.getName();
                Method m = (Method) claz.getMethod("get" +getMethodName(fieldName));  
                System.out.println(getMethodName(fieldName));
                System.out.println(field.getGenericType()+"-"+"fieldName:"+fieldName+"="+m.invoke(stu));
            } catch (Exception e) {
                e.printStackTrace();
            } 
        }
        Object result=null;  //计算结果
        ScriptEngineManager manager = new ScriptEngineManager();   //创建一个ScriptEngineManager对象
        ScriptEngine engine = manager.getEngineByName("js");  //通过ScriptEngineManager获得ScriptEngine对象
        engine.put(className, stu);  //将student对象放到ScriptEngine 中为计算变量提供值
        
        try {
            //result =engine.eval(formula);  //1 用ScriptEngine的eval方法执行脚本  String formula="Student.name+Student.age+10";
            

            engine.eval(formula);            //2
            Invocable inv = (Invocable) engine; //2
            result=inv.invokeFunction("test");  //2   执行字符串 js test()
            System.out.println("the result is :"+result.toString());
        } catch (Exception e) {
            System.out.println("错误");
            e.printStackTrace();
        } 
    }
    
     // 把一个字符串的第一个字母大写 
     private static String getMethodName(String fildeName) throws Exception{  
             byte[] items = fildeName.getBytes();  
             items[0] = (byte) ((char) items[0] - 'a' + 'A');  
             return new String(items);  
     }

 

上述代码 还可注释2 打开注释1 试试 一样可以的 不过方式不同而已 

有了这个思想 我们就可以把公式维护到数据库或文件中 方便我们后期对公式的维护修改 这样利用这个工具应该可以减少计算代码编写的复杂度 

后期我也发现了好多表达式引擎如:Aviator、IKExpression等。

 

相关文章
|
存储 Cloud Native 数据库
云原生多模数据库Lindorm权威指南|从入门到精通(持续更新 v2021.2)
Lindorm是阿里云发布的业界首款云原生多模数据库,支持宽表、时序、文件等多种类型海量数据的低成本存储、检索与分析,兼容HBase/Cassandra、OpenTSDB、Solr、SQL、HDFS等多种开源标准接口,希望通过本指南,可以给开发者给更多的了解和使用指导,本文将持续更新
12340 2
云原生多模数据库Lindorm权威指南|从入门到精通(持续更新 v2021.2)
|
10月前
|
人工智能 自然语言处理 并行计算
MeteoRA:多任务AI框架革新!动态切换+MoE架构,推理效率提升200%
MeteoRA 是南京大学推出的多任务嵌入框架,基于 LoRA 和 MoE 架构,支持动态任务切换与高效推理。
492 3
|
Java Spring
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
446 3
|
9月前
|
Java 微服务 Spring
微服务——SpringBoot使用归纳——Spring Boot中使用拦截器——拦截器使用实例
本文主要讲解了Spring Boot中拦截器的使用实例,包括判断用户是否登录和取消特定拦截操作两大场景。通过token验证实现登录状态检查,未登录则拦截请求;定义自定义注解@UnInterception实现灵活取消拦截功能。最后总结了拦截器的创建、配置及对静态资源的影响,并提供两种配置方式供选择,帮助读者掌握拦截器的实际应用。
355 0
|
Docker Windows Python
Windows-Docker学习笔记(一)
本文介绍了Windows环境下Docker的安装与使用方法。首先通过链接下载Windows版本的Docker,然后按步骤配置:启用Windows功能、设置默认WSL版本为2,并检查Docker及其组件是否正常工作。接着详细列出了Docker的基础命令及其用法,包括搜索、下载镜像、管理容器等。同时介绍了Dockerfile的编写方法及其构建过程,以及docker-compose.yml文件的用途。最后提供了运行和管理容器的具体示例。
Windows-Docker学习笔记(一)
|
存储 人工智能 搜索推荐
揭秘LangChain+RAG如何重塑行业未来?保姆级实战演练,解锁大模型在各领域应用场景的神秘面纱!
【10月更文挑战第4天】随着AI技术的发展,大型语言模型在各行各业的应用愈发广泛,检索增强生成(RAG)技术成为推动企业智能化转型的关键。本文通过实战演练,展示了如何在LangChain框架内实施RAG技术,涵盖金融(智能风控与投资决策)、医疗(辅助诊断与病历分析)及教育(个性化学习推荐与智能答疑)三大领域。通过具体示例和部署方案,如整合金融数据、医疗信息以及学生学习资料,并利用RAG技术生成精准报告、诊断建议及个性化学习计划,为企业提供了切实可行的智能化解决方案。
552 5
|
JSON Kubernetes Linux
k8s备份恢复实践--velero
使用Velero备份k8资源到minio,阿里云oss,七牛云Kodo
763 8
|
SQL 数据挖掘 大数据
如何在 SQL Server 中使用 `OFFSET` 和 `FETCH`
【8月更文挑战第10天】
3074 8
|
敏捷开发 缓存 弹性计算
阿里云云效产品使用合集之如何通过API接口往附件中上传文件
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
JSON JavaScript 前端开发
若依修改,若依如何发送get和post请求,发送数据请求的写法,若依请求的API在src的api文件下,建立请求的第一步,在API中新建一个文件,第二步新建JavaScript文件
若依修改,若依如何发送get和post请求,发送数据请求的写法,若依请求的API在src的api文件下,建立请求的第一步,在API中新建一个文件,第二步新建JavaScript文件