场景: 最近有一个计算商品运费的,如果商品的数量大于快递公司设置的数量 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的一些关键特点和优势:
-
JVM兼容性:Groovy可以无缝地与Java代码集成,允许开发者在同一个项目中混合使用Groovy和Java代码。这意味着任何Java库都可以在Groovy中使用,反之亦然。
-
动态类型:Groovy是一种动态类型语言,这意味着变量的类型在运行时确定,而不是在编译时。这使得Groovy代码更加灵活和简洁。
-
简洁的语法:Groovy的语法设计得更加简洁和易于阅读,它提供了许多快捷方式来减少代码量,比如省略类型声明、使用GString(Groovy字符串)等。
-
元编程:Groovy支持强大的元编程特性,包括Groovy的闭包(类似于Java 8的Lambda表达式)和动态代理,这使得函数式编程和AOP(面向切面编程)更加容易实现。
-
构建工具:Groovy被广泛用于构建工具,特别是Apache Maven和Gradle,后者甚至使用Groovy作为其构建脚本的默认语言。
-
测试框架:Groovy与Spock框架(一种基于Groovy的测试框架)紧密集成,使得编写测试用例更加简洁和表达力强。
-
并发编程:Groovy提供了对并发编程的支持,包括对Java并发API的封装,以及GPars库,后者提供了对并发和并行编程的高级抽象。
-
Web开发:Groovy支持多种Web开发框架,如Grails(一个基于Groovy的全栈Web应用框架)和Ratpack(一个用于构建现代HTTP应用的工具包)。
-
脚本编写:Groovy的简洁性和强大的标准库使其成为编写脚本的理想选择,尤其是在需要与Java系统集成时。
-
社区和生态系统: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)上的编程语言,但它们之间存在一些关键的区别:
-
静态类型与动态类型:
- Java:是一种静态类型语言,变量的类型在编译时确定,必须显式声明变量的类型。
- Groovy:是一种动态类型语言,变量的类型在运行时确定,不需要显式声明变量的类型。
-
语法简洁性:
- Java:语法较为严格和冗长,需要编写更多的样板代码。
- Groovy:提供了更简洁的语法,支持多种编程范式,包括面向对象、函数式和命令式编程,减少了代码量。
-
元编程能力:
- Java:虽然Java 8引入了Lambda表达式和方法引用,但元编程能力有限。
- Groovy:提供了强大的元编程能力,包括闭包、Groovy对象(GString)、动态方法调用和属性访问等。
-
集成和兼容性:
- Java:虽然可以调用Groovy代码,但需要一些额外的配置。
- Groovy:可以无缝集成Java代码,不需要任何额外的配置,Groovy代码可以作为Java代码的直接替代。
-
构建工具和脚本:
- Java:通常使用Ant或Maven等构建工具,这些工具使用XML配置文件。
- Groovy:Groovy被广泛用于构建工具,如Gradle,它使用Groovy作为构建脚本语言,提供了更灵活和强大的构建配置。
-
测试框架:
- Java:通常使用JUnit等测试框架。
- Groovy:除了JUnit,还支持Spock框架,这是一个基于Groovy的测试框架,提供了更简洁和强大的测试DSL。
-
并发编程:
- Java:提供了丰富的并发API,如
java.util.concurrent
包。 - Groovy:除了Java的并发API,还提供了GPars库,这是一个Groovy的并发编程库,提供了更高级的并发和并行编程抽象。
- Java:提供了丰富的并发API,如
-
Web框架:
- Java:有Spring、JavaServer Faces (JSF)、Struts等Web框架。
- Groovy:有Grails(一个全栈Web应用框架)和Ratpack(一个用于构建现代HTTP应用的工具包)。
-
社区和生态系统:
- Java:拥有庞大的社区和成熟的生态系统。
- Groovy:社区相对较小,但生态系统在不断增长,特别是在企业级应用和自动化脚本领域。
总的来说,Groovy提供了一种更加灵活和简洁的方式来编写JVM上的代码,而Java则提供了更严格的类型检查和广泛的社区支持。选择哪种语言取决于具体的项目需求和团队偏好。
🤓 Groovy是否适合大型企业级应用开发?
Groovy作为一种运行在JVM上的动态语言,非常适合大型企业级应用开发,主要原因如下:
-
与Java的无缝集成:Groovy可以直接使用Java的类库和API,同时Java代码也可以轻松调用Groovy脚本,这使得Groovy在Java生态系统中具有很高的兼容性。
-
动态语言特性:Groovy支持动态类型、元编程和闭包等特性,使得代码编写更加灵活和简洁。它提供了更简洁的语法和更少的样板代码,提高了开发效率。
-
丰富的库和扩展:Groovy提供了许多库和扩展,涵盖了数据库访问、JSON处理、并发编程等领域,这些库使得Groovy在企业级应用开发中更加强大和灵活。
-
性能表现:尽管Groovy是一种动态语言,但其性能表现非常出色。在JVM的支持下,Groovy代码的运行速度接近原生Java代码。
-
领域特定语言(DSL)开发:Groovy的DSL支持使得开发者可以为特定领域创建定制化的语言,如配置文件解析、SQL查询生成等,进一步提高开发效率。
-
Web开发:Groovy可以与各种Web框架(如Grails)结合使用,实现快速、高效的Web开发。
-
并发编程支持:Groovy提供了对并发编程的支持,包括
Groovyx.gpars.actor
库中的Actor模型,使得编写多线程应用程序变得更加简单和安全。 -
AST转换:Groovy的AST转换允许在编译时修改程序的抽象语法树,这可以用来实现自定义注解、创建DSL或者改变程序的行为。
-
企业级应用案例:Groovy被广泛用于构建工具,如Gradle,以及在Jira等项目管理工具中,显示了其在企业级应用中的适用性和重要性。
-
安全性和稳定性:Groovy提供了一些被动安全手段,比如采用线程池隔离,对脚本执行进行有效的实时监控、统计和封装,或者是手动强杀执行脚本的线程,增强了企业级应用的安全性和稳定性。
综上所述,Groovy以其与Java的高度兼容性、动态语言特性、丰富的库支持、性能优势以及在企业级应用中的广泛使用,非常适合大型企业级应用开发。
🔍 Groovy在构建企业级工具时有哪些优势?
Groovy在构建企业级工具时的优势主要体现在以下几个方面:
-
与Java的无缝集成:Groovy可以直接使用Java的类库和API,同时Java代码也可以轻松调用Groovy脚本,这使得Groovy在Java生态系统中具有很高的兼容性。
-
动态语言特性:Groovy支持动态类型、元编程和闭包等特性,使得代码编写更加灵活和简洁,提供了更简洁的语法和更少的样板代码,提高了开发效率。
-
丰富的生态系统:Groovy有着庞大且活跃的社区,众多的库和框架提供了丰富的解决方案,简化了企业级应用开发的工作。例如,Grails和Spock等框架都有着很高的社区支持,使得开发人员能够更加高效地构建应用和编写测试。
-
简化构建流程:Groovy与Gradle构建工具的紧密结合,使得开发人员可以通过编写自定义插件来自动化常见的构建任务和流程,减少手动配置和干预。
-
并行编译和增量编译:利用Gradle 3.1的并行编译和增量编译功能,可以显著减少构建时间,提高构建性能。
-
领域特定语言(DSL)开发:Groovy的DSL支持使得开发者可以为特定领域创建定制化的语言,如配置文件解析、SQL查询生成等,进一步提高开发效率。
-
性能优越:尽管Groovy是一种动态语言,但其性能表现非常出色。在JVM的支持下,Groovy代码的运行速度接近原生Java代码。
-
脚本编写:Groovy非常适合用于编写各种脚本,如构建脚本、自动化测试脚本等。其简洁的语法和动态性使得脚本编写更加快速、高效。
-
跨平台兼容性:Groovy Eclipse兼容Eclipse 3.2及其以上版本,因此可以在多种操作系统上运行,为企业提供了更大的灵活性。
-
丰富的插件生态系统:Groovy Eclipse作为Eclipse的一部分,可以访问庞大的插件生态系统,这些插件能够扩展其功能,满足特定的开发需求。
-
社区支持:Groovy和Eclipse社区活跃,为开发者提供了丰富的资源和支持,包括文档、教程和论坛等,有助于解决开发过程中遇到的问题。
这些优势使得Groovy成为企业级工具开发中的一个有力选择,特别是在需要灵活性、简洁性和强大社区支持的场景下。