java里面使用groovy案例+详解

news2024/12/28 20:36:22

场景: 最近有一个计算商品运费的,如果商品的数量大于快递公司设置的数量 10
那么超出部分也需要计算额外运费,那么这些计算过程代码我能不能不在java里面写呢,用一种可配置化的方式来根据不同的传参计算出运费?

页面传参

[{“key”:“起订量(大单位)”,“isRequired”:true,“isNumber”:true},{“key”:“运费(元)”,“isRequired”:true,“isNumber”:true},{“key”:“续件(大单位)”,“isRequired”:false,“isFixed”:true,“value”:“1”},{“key”:“续件费(元)”,“isRequired”:true},{“key”:“订单金额满
¥ 免运费”,“isRequired”:false,“isFixed”:true,“value”:“800”}]

我需要拿到json里面的value值,然后计算运费

groovy介绍

Groovy是一种动态语言,它运行在Java虚拟机(JVM)上,并且与Java语言兼容。以下是Groovy的一些关键特点和优势:

  1. JVM兼容性:Groovy可以无缝地与Java代码集成,允许开发者在同一个项目中混合使用Groovy和Java代码。这意味着任何Java库都可以在Groovy中使用,反之亦然。

  2. 动态类型:Groovy是一种动态类型语言,这意味着变量的类型在运行时确定,而不是在编译时。这使得Groovy代码更加灵活和简洁。

  3. 简洁的语法:Groovy的语法设计得更加简洁和易于阅读,它提供了许多快捷方式来减少代码量,比如省略类型声明、使用GString(Groovy字符串)等。

  4. 元编程:Groovy支持强大的元编程特性,包括Groovy的闭包(类似于Java 8的Lambda表达式)和动态代理,这使得函数式编程和AOP(面向切面编程)更加容易实现。

  5. 构建工具:Groovy被广泛用于构建工具,特别是Apache Maven和Gradle,后者甚至使用Groovy作为其构建脚本的默认语言。

  6. 测试框架:Groovy与Spock框架(一种基于Groovy的测试框架)紧密集成,使得编写测试用例更加简洁和表达力强。

  7. 并发编程:Groovy提供了对并发编程的支持,包括对Java并发API的封装,以及GPars库,后者提供了对并发和并行编程的高级抽象。

  8. Web开发:Groovy支持多种Web开发框架,如Grails(一个基于Groovy的全栈Web应用框架)和Ratpack(一个用于构建现代HTTP应用的工具包)。

  9. 脚本编写:Groovy的简洁性和强大的标准库使其成为编写脚本的理想选择,尤其是在需要与Java系统集成时。

  10. 社区和生态系统:Groovy有一个活跃的社区和不断增长的生态系统,提供了大量的插件和库来扩展其功能。

Groovy的设计哲学是“让事情更简单”,它旨在提供一种更加简洁和愉快的编程体验,同时保持与Java生态系统的兼容性。这使得Groovy在许多领域,尤其是在企业级应用开发中,成为一种受欢迎的选择。

依赖

<!--    groovy    -->
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.5.11</version>
            <type>pom</type>
        </dependency>

计算结果数据解析

/**
 * @author sunpeiyang
 * @date 2024/11/6 13:35
 */
@Slf4j
@Component
public class CspGroovyCodeVerification {

    public Map<String, Object> getFreightAmount(Object value) {
        Map<String, Object> resultMap = new HashMap<>();
        // 检查传入的 value 是否为数组
        if (value != null) {
            List<Object> resultList = (List<Object>) value;
            resultMap.put("isFreeFreightAmount", resultList.get(0));
            resultMap.put("freightAmount", resultList.get(1));
        }
        return resultMap;
    }

}

计算结果工具类

@Slf4j
public class CspGroovyUtil {
    private ScriptEngineManager factory = null;

    private ScriptEngine engine = null;

    public CspGroovyUtil() {
        factory = new ScriptEngineManager();
        engine = factory.getEngineByName("groovy");
        engine.getContext().setAttribute("out", new PrintStreamWrapper(), ScriptContext.ENGINE_SCOPE);
    }

    public synchronized Object invoke(String script, String name, Object... args) throws ScriptException, NoSuchMethodException {
        engine.eval(script);
        return ((Invocable) engine).invokeFunction(name, args);
    }

    private static class PrintStreamWrapper {
        public void println(String x) {
            log.info("scriptInfoOut={}", x);
        }
    }

    public Object invokeExtra(String script, String name, Object... args) throws ScriptException, NoSuchMethodException {
        engine.eval(script);
        return ((Invocable) engine).invokeFunction(name, args);
    }
}

运费计算

Map<String, Object> resultMap = resultMap = groovyCodeVerification.getFreightAmount(groovyUtil.invoke("def calculationFormula(rule,orderAmount,goodsNumberTotal){  " + cspQuoteRule.getTemplateCalculationFormulaCode() + "  }", "calculationFormula", unitList, freightQuotationSetDetail.getOrderAmount(), freightQuotationSetDetail.getGoodsNumberTotal()));

计算公式

// 满件数(大单位)
    def fullNum = 0
// 运费()
    def freight = 0
// 续件(大单位)
    def continueNum = 0
// 续运费单价(元)
    def continueFreight = 0
// 免运费的条件金额
    def freeFreightAmount = 0
// 获取数组的大小
    def ruleSize = rule.size()
// 运费的结果
    def resultFreightAmount = 0

    if(ruleSize > 0){
        fullNum = rule[0].toInteger()
    }
    if(ruleSize > 1){
        freight = rule[1].toBigDecimal()
    }
    if(ruleSize > 2){
        continueNum = rule[2].toInteger()
    }
    if(ruleSize > 3){
        continueFreight = rule[3].toBigDecimal()
    }
    if(ruleSize > 4){
        freeFreightAmount = rule[4] ? rule[4].toBigDecimal() : BigDecimal.ZERO
    }
    if(goodsNumberTotal <= fullNum){
        resultFreightAmount = freight
    }else if(goodsNumberTotal > fullNum){
        // 商品数量大于满件数(大单位),那么 运费 = freight + continueNumBer*continueFreight;
        def resultGoodsNumberTotal = goodsNumberTotal - fullNum
        if(resultGoodsNumberTotal > 0){
            // 续件(大单位)数量计算,不足一进一
            def continueNumBer = Math.ceil(resultGoodsNumberTotal / continueNum)
            resultFreightAmount = freight + (continueNumBer * continueFreight)
        }
    }
// 如果订单的金额大于门店设置的免运费条件,则免运费
    def orderAmountResult = orderAmount - freeFreightAmount
    if(freeFreightAmount > 0 && orderAmountResult >= 0){
        return [0,resultFreightAmount]
    }else{
        return [1,resultFreightAmount]
    }

简单的案例

在这里插入图片描述

csp_order_freight_expression_debug.groovy

def matchingConditions(rule, orderAmount, goodsNumberTotal) {
    // 满件数(大单位)
    def fullNum = 0
// 运费()
    def freight = 0
// 续件(大单位)
    def continueNum = 0
// 续运费单价(元)
    def continueFreight = 0
// 免运费的条件金额
    def freeFreightAmount = 0
// 获取数组的大小
    def ruleSize = rule.size()
// 运费的结果
    def resultFreightAmount = 0

    if(ruleSize > 0){
        fullNum = rule[0].toInteger()
    }
    if(ruleSize > 1){
        freight = rule[1].toBigDecimal()
    }
    if(ruleSize > 2){
        continueNum = rule[2].toInteger()
    }
    if(ruleSize > 3){
        continueFreight = rule[3].toBigDecimal()
    }
    if(ruleSize > 4){
        freeFreightAmount = rule[4] ? rule[4].toBigDecimal() : BigDecimal.ZERO
    }
    if(goodsNumberTotal <= fullNum){
        resultFreightAmount = freight
    }else if(goodsNumberTotal > fullNum){
        // 商品数量大于满件数(大单位),那么 运费 = freight + continueNumBer*continueFreight;
        def resultGoodsNumberTotal = goodsNumberTotal - fullNum
        if(resultGoodsNumberTotal > 0){
            // 续件(大单位)数量计算,不足一进一
            def continueNumBer = Math.ceil(resultGoodsNumberTotal / continueNum)
            resultFreightAmount = freight + (continueNumBer * continueFreight)
        }
    }
// 如果订单的金额大于门店设置的免运费条件,则免运费
    def orderAmountResult = orderAmount - freeFreightAmount
    if(freeFreightAmount > 0 && orderAmountResult >= 0){
        return [0,resultFreightAmount]
    }else{
        return [1,resultFreightAmount]
    }
}

// 销售单商品运费的计算公式
List<String> unitList = ['2', '200', '1', '7', '30']

BigDecimal orderAmount = 30

BigDecimal goodsNumberTotal = 3

matchingConditions(unitList, orderAmount, goodsNumberTotal);

🤔 Groovy和Java的主要区别是什么?

Groovy和Java都是运行在Java虚拟机(JVM)上的编程语言,但它们之间存在一些关键的区别:

  1. 静态类型与动态类型

    • Java:是一种静态类型语言,变量的类型在编译时确定,必须显式声明变量的类型。
    • Groovy:是一种动态类型语言,变量的类型在运行时确定,不需要显式声明变量的类型。
  2. 语法简洁性

    • Java:语法较为严格和冗长,需要编写更多的样板代码。
    • Groovy:提供了更简洁的语法,支持多种编程范式,包括面向对象、函数式和命令式编程,减少了代码量。
  3. 元编程能力

    • Java:虽然Java 8引入了Lambda表达式和方法引用,但元编程能力有限。
    • Groovy:提供了强大的元编程能力,包括闭包、Groovy对象(GString)、动态方法调用和属性访问等。
  4. 集成和兼容性

    • Java:虽然可以调用Groovy代码,但需要一些额外的配置。
    • Groovy:可以无缝集成Java代码,不需要任何额外的配置,Groovy代码可以作为Java代码的直接替代。
  5. 构建工具和脚本

    • Java:通常使用Ant或Maven等构建工具,这些工具使用XML配置文件。
    • Groovy:Groovy被广泛用于构建工具,如Gradle,它使用Groovy作为构建脚本语言,提供了更灵活和强大的构建配置。
  6. 测试框架

    • Java:通常使用JUnit等测试框架。
    • Groovy:除了JUnit,还支持Spock框架,这是一个基于Groovy的测试框架,提供了更简洁和强大的测试DSL。
  7. 并发编程

    • Java:提供了丰富的并发API,如java.util.concurrent包。
    • Groovy:除了Java的并发API,还提供了GPars库,这是一个Groovy的并发编程库,提供了更高级的并发和并行编程抽象。
  8. Web框架

    • Java:有Spring、JavaServer Faces (JSF)、Struts等Web框架。
    • Groovy:有Grails(一个全栈Web应用框架)和Ratpack(一个用于构建现代HTTP应用的工具包)。
  9. 社区和生态系统

    • Java:拥有庞大的社区和成熟的生态系统。
    • Groovy:社区相对较小,但生态系统在不断增长,特别是在企业级应用和自动化脚本领域。

总的来说,Groovy提供了一种更加灵活和简洁的方式来编写JVM上的代码,而Java则提供了更严格的类型检查和广泛的社区支持。选择哪种语言取决于具体的项目需求和团队偏好。

🤓 Groovy是否适合大型企业级应用开发?

Groovy作为一种运行在JVM上的动态语言,非常适合大型企业级应用开发,主要原因如下:

  1. 与Java的无缝集成:Groovy可以直接使用Java的类库和API,同时Java代码也可以轻松调用Groovy脚本,这使得Groovy在Java生态系统中具有很高的兼容性。

  2. 动态语言特性:Groovy支持动态类型、元编程和闭包等特性,使得代码编写更加灵活和简洁。它提供了更简洁的语法和更少的样板代码,提高了开发效率。

  3. 丰富的库和扩展:Groovy提供了许多库和扩展,涵盖了数据库访问、JSON处理、并发编程等领域,这些库使得Groovy在企业级应用开发中更加强大和灵活。

  4. 性能表现:尽管Groovy是一种动态语言,但其性能表现非常出色。在JVM的支持下,Groovy代码的运行速度接近原生Java代码。

  5. 领域特定语言(DSL)开发:Groovy的DSL支持使得开发者可以为特定领域创建定制化的语言,如配置文件解析、SQL查询生成等,进一步提高开发效率。

  6. Web开发:Groovy可以与各种Web框架(如Grails)结合使用,实现快速、高效的Web开发。

  7. 并发编程支持:Groovy提供了对并发编程的支持,包括Groovyx.gpars.actor库中的Actor模型,使得编写多线程应用程序变得更加简单和安全。

  8. AST转换:Groovy的AST转换允许在编译时修改程序的抽象语法树,这可以用来实现自定义注解、创建DSL或者改变程序的行为。

  9. 企业级应用案例:Groovy被广泛用于构建工具,如Gradle,以及在Jira等项目管理工具中,显示了其在企业级应用中的适用性和重要性。

  10. 安全性和稳定性:Groovy提供了一些被动安全手段,比如采用线程池隔离,对脚本执行进行有效的实时监控、统计和封装,或者是手动强杀执行脚本的线程,增强了企业级应用的安全性和稳定性。

综上所述,Groovy以其与Java的高度兼容性、动态语言特性、丰富的库支持、性能优势以及在企业级应用中的广泛使用,非常适合大型企业级应用开发。

🔍 Groovy在构建企业级工具时有哪些优势?

Groovy在构建企业级工具时的优势主要体现在以下几个方面:

  1. 与Java的无缝集成:Groovy可以直接使用Java的类库和API,同时Java代码也可以轻松调用Groovy脚本,这使得Groovy在Java生态系统中具有很高的兼容性。

  2. 动态语言特性:Groovy支持动态类型、元编程和闭包等特性,使得代码编写更加灵活和简洁,提供了更简洁的语法和更少的样板代码,提高了开发效率。

  3. 丰富的生态系统:Groovy有着庞大且活跃的社区,众多的库和框架提供了丰富的解决方案,简化了企业级应用开发的工作。例如,Grails和Spock等框架都有着很高的社区支持,使得开发人员能够更加高效地构建应用和编写测试。

  4. 简化构建流程:Groovy与Gradle构建工具的紧密结合,使得开发人员可以通过编写自定义插件来自动化常见的构建任务和流程,减少手动配置和干预。

  5. 并行编译和增量编译:利用Gradle 3.1的并行编译和增量编译功能,可以显著减少构建时间,提高构建性能。

  6. 领域特定语言(DSL)开发:Groovy的DSL支持使得开发者可以为特定领域创建定制化的语言,如配置文件解析、SQL查询生成等,进一步提高开发效率。

  7. 性能优越:尽管Groovy是一种动态语言,但其性能表现非常出色。在JVM的支持下,Groovy代码的运行速度接近原生Java代码。

  8. 脚本编写:Groovy非常适合用于编写各种脚本,如构建脚本、自动化测试脚本等。其简洁的语法和动态性使得脚本编写更加快速、高效。

  9. 跨平台兼容性:Groovy Eclipse兼容Eclipse 3.2及其以上版本,因此可以在多种操作系统上运行,为企业提供了更大的灵活性。

  10. 丰富的插件生态系统:Groovy Eclipse作为Eclipse的一部分,可以访问庞大的插件生态系统,这些插件能够扩展其功能,满足特定的开发需求。

  11. 社区支持:Groovy和Eclipse社区活跃,为开发者提供了丰富的资源和支持,包括文档、教程和论坛等,有助于解决开发过程中遇到的问题。

这些优势使得Groovy成为企业级工具开发中的一个有力选择,特别是在需要灵活性、简洁性和强大社区支持的场景下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2238762.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

单体架构 IM 系统之核心业务功能实现

在上一篇技术短文&#xff08;单体架构的 IM 系统设计&#xff09;中&#xff0c;我们讨论了在 “用户规模小、开发人员少、开发时间短” 的业务背景下&#xff0c;采取 “怎么简单怎么做&#xff0c;怎么快怎么来” 的研发策略&#xff0c;于是设计了 单体架构的IM系统&#x…

Linux部署nginx访问文件403

问题描述&#xff1a;在linux服务器上通过nginx部署&#xff0c;访问文件403 新配置了一个用户来部署服务&#xff0c;将部署文件更新到原有目录下&#xff0c;结果nginx访问403 原因&#xff1a;没有配置文件的读写权限&#xff0c;默认不可读写&#xff0c;nginx无法访问到文…

解决 C/C++ 中 “invalid use of incomplete type” 编译错误

解决 C/C++ 中 “invalid use of incomplete type” 编译错误 一、错误原因二、常见场景三、解决方法四、最佳实践五、总结在 C 和 C++ 编程中,invalid use of incomplete type 错误通常发生在尝试使用一个未完全定义的类型时。这个错误表明编译器在当前上下文中没有足够的信息…

使用 Python 实现高效网页爬虫——从获取链接到数据保存

前言 在这个时代,网络爬虫已成为数据分析与信息收集不可或缺的技术之一。本文将通过一个具体的Python项目来介绍如何构建一个简单的网络爬虫,它能够自动抓取指定网站的文章链接、标题、正文内容以及图片链接,并将这些信息保存为CSV文件。 目标网站 一、准备工作 在开始编…

C# 有趣的小程序—桌面精灵详细讲解

C# 桌面精灵详细讲解 最近写了一个简化版桌面精灵&#xff0c;效果如图所示&#xff0c;可以实现切换动画&#xff0c;说话、鼠标拖动&#xff0c;等功能。具体如何做&#xff0c;我发布了一个资源里面包含ppt详解、源代码以及动画素材。放心吧&#xff0c;免费的&#xff0c;…

微软日志丢失事件敲响安全警钟

NEWS | 事件回顾 最近&#xff0c;全球最大的软件公司之一——微软&#xff0c;遭遇了一场罕见的日志丢失危机。据报告&#xff0c;从9月2日至9月19日&#xff0c;持续长达两周的时间里&#xff0c;微软的多项核心云服务&#xff0c;包括身份验证平台Microsoft Entra、安全信息…

Mysql ERROR 1451 (23000) 外键处理异常

通过临时设置外键失效&#xff0c;来规避报错 第一步 # 临时设置外键失效 SET FOREIGN_KEY_CHECKS 0; 第二步&#xff1a;执行更新或者删除操作 第三步&#xff1a; # 操作结束后恢复外键 SET FOREIGN_KEY_CHECKS 1;

智慧社区可视化解决方案:科技引领社区服务与管理新篇章

随着社会的发展&#xff0c;智慧社区作为新型城镇化发展目标和社区服务体系建设的重要举措&#xff0c;正逐步改变着我们的生活方式。智慧社区通过综合运用现代科学技术&#xff0c;整合区域资源&#xff0c;提升社区治理和服务水平&#xff0c;为居民提供更为便捷、高效、安全…

基于redis实现API接口访问次数限制

一&#xff0c;概述 日常开发中会有一个常见的需求&#xff0c;需要限制接口在单位时间内的访问次数&#xff0c;比如说某个免费的接口限制单个IP一分钟内只能访问5次。该怎么实现呢&#xff0c;通常大家都会想到用redis&#xff0c;确实通过redis可以实现这个功能&#xff0c…

【go从零单排】Ticker

&#x1f308;Don’t worry , just coding! 内耗与overthinking只会削弱你的精力&#xff0c;虚度你的光阴&#xff0c;每天迈出一小步&#xff0c;回头时发现已经走了很远。 &#x1f4d7;概念 在 Go 语言中&#xff0c;Ticker 是一个用于定期执行某些操作的工具。它属于 tim…

C++《stack与queue》

在之前的章节我们学习了C当中string、vector和list三种容器并且试着模拟实现这三种容器&#xff0c;那么接下来在本篇当中我们将STL当中的stack和queue&#xff0c;并且在学习stack和queue的使用之后和之前一样还会试着模拟实现stck和queue。由于stck和queue的模拟实现较为简单…

网页web无插件播放器EasyPlayer.js点播播放器遇到视频地址播放不了的现象及措施

在数字媒体时代&#xff0c;视频点播已成为用户获取信息和娱乐的重要方式。EasyPlayer.js作为一款流行的点播播放器&#xff0c;以其强大的功能和易用性受到广泛欢迎。然而&#xff0c;在使用过程中&#xff0c;用户可能会遇到视频地址无法播放的问题&#xff0c;这不仅影响用户…

【前端】HTML标签汇总

目录 展示用户信息的标签 1.文本标签 span 2.标题标签 h1~h6 3.竖着布局的标签 div 4.段落标签 p 5.超链接标签 a 5.1跳转至网上的资源 5.2锚点 6.列表标签 6.1有序列表 ol 6.2无序列表 ul 7.图片标签 img 7.1相对路径 7.1.1兄弟关系 7.1.2叔侄关系 7.1.3表兄弟…

xtu oj 加一

样例输入# 2 4 1 2 3 4 4 3 2 4 1样例输出# 3 5 解题思路&#xff1a;最小操作次数一定是把所有数变成数组中最大值max。 1、找最大值&#xff0c;一开始我把max初始值设为0&#xff0c;如果a[i]>max,maxa[i],WA了。又看了一遍题目&#xff0c;发现所有整数的绝对值小于…

Windows10/11开启卓越性能模式 windows开启卓越性能电源模式 工作电脑开启卓越性能模式 电脑开启性能模式

Windows10/11开启卓越性能模式 windows开启卓越性能电源模式 工作电脑开启卓越性能模式 电脑开启性能模式 1、所要用到的激活工具2、开启电脑卓越性能模式Windows11Windows10在电源模式中选择卓越性能模式 3、将系统版本切换为 工作站版本 1、所要用到的激活工具 KMS激活工具(…

人工智能、机器学习与深度学习:层层递进的技术解读

引言 在当今科技快速发展的时代&#xff0c;人工智能&#xff08;AI&#xff09;已经成为一个热门话题&#xff0c;几乎渗透到了我们生活的方方面面。从智能手机的语音助手&#xff0c;到自动驾驶汽车&#xff0c;再到医疗诊断中的图像识别&#xff0c;人工智能的应用正在改变我…

光流法(Optical Flow)

一、简介 光流法&#xff08;Optical Flow&#xff09;是一种用于检测图像序列中像素运动的计算机视觉技术。其基于以下假设&#xff1a; 1.亮度恒定性假设&#xff1a;物体在运动过程中&#xff0c;其像素值在不同帧中保持不变。 2.空间和时间上的连续性&#xff1a;相邻像素之…

OkHttp网络请求框架

添加依赖 在 build.gradle 文件中添加 OkHttp 依赖&#xff1a; dependencies {implementation("com.squareup.okhttp3:okhttp:4.10.0") }使用OkHttp发起GET请求 同步请求 public class MainActivity extends AppCompatActivity {// Used to load the okhttptes…

《XGBoost算法的原理推导》12-14决策树复杂度的正则化项 公式解析

本文是将文章《XGBoost算法的原理推导》中的公式单独拿出来做一个详细的解析&#xff0c;便于初学者更好的理解。 我们定义一颗树的复杂度 Ω Ω Ω&#xff0c;它由两部分组成&#xff1a; 叶子结点的数量&#xff1b;叶子结点权重向量的 L 2 L2 L2范数&#xff1b; 公式(…

使用postmain 测试下载文件接口

文章目录 前言使用postmain 测试下载文件接口 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实在白嫖的话&#xff0c;那欢迎常来啊!!…