游乐游手机版
首页/AI教程/文章详情

策略模式与规则引擎实现国际集运复杂运费计算

时间:2026-06-16 19:28
基于策略模式和Drools规则引擎,实现国际集运计费系统,支持首重续重、体积重及不同国家渠道的差异化计费,可实时计算和批量试算。通过缓存和并行计算优化性能,单机承载每秒500次请求。

摘要:反向海淘运费计算,本质上按照首重续重、体积重以及不同国家与渠道的差异化计费规则执行。本文将深入探讨如何利用 Java 的策略模式与 Drools 规则引擎,构建一套灵活可配置的国际集运计费引擎,既支持实时计算,也能满足批量试算需求。

国际集运计费引擎实现:策略模式+规则引擎处理复杂运费计算

需求建模

我们来看几个典型的运费规则案例:

  • 美国云途专线:首重0.5kg,85元;续重每0.5kg,25元,按实际重量计费。
  • 美国EMS:首重0.5kg,110元;续重每0.5kg,35元,计费依据取实际重量与体积重(长*宽*高/5000)中的较大值。
  • 加拿大专线:首重1kg,120元;续重每0.5kg,30元。

可见,核心变量只有两个:计费方式(实际重量或体积重)与费率结构(首重/续重)。由于业务需求变化频繁,代码必须实现灵活配置。

策略模式实现

计费策略接口定义示例如下:

public interface FreightCalculator {
    BigDecimal calculate(ShippingPackage pkg, FreightRule rule);
}

实际重量策略的实现:

@Component
public class ActualWeightCalculator implements FreightCalculator {
    @Override
    public BigDecimal calculate(ShippingPackage pkg, FreightRule rule) {
        double weight = pkg.getActualWeightKg();
        if (weight <= rule.getFirstWeight()) {
            return rule.getFirstPrice();
        }
        double additional = weight - rule.getFirstWeight();
        int units = (int) Math.ceil(additional / rule.getAdditionalUnit());
        return rule.getFirstPrice().add(
            rule.getAdditionalPrice().multiply(BigDecimal.valueOf(units))
        );
    }
}

体积重策略的实现:

@Component
public class VolumetricWeightCalculator implements FreightCalculator {
    @Override
    public BigDecimal calculate(ShippingPackage pkg, FreightRule rule) {
        double volumetric = pkg.getLengthCm() * pkg.getWidthCm() * pkg.getHeightCm() / 5000.0;
        double weight = Math.max(pkg.getActualWeightKg(), volumetric);
        // 注意:这里复用了实际重量计算逻辑,只是传入了“修正后”的重量
        return actualWeightCalculator.calculate(new ShippingPackage(weight), rule);
    }
}

策略工厂用于根据类型获取对应的计算器:

@Component
public class FreightCalculatorFactory {
    private final Map calculatorMap = new HashMap<>();

    public FreightCalculatorFactory() {
        calculatorMap.put("actual", new ActualWeightCalculator());
        calculatorMap.put("volumetric", new VolumetricWeightCalculator());
        // 更多策略就继续加
    }

    public FreightCalculator getCalculator(String type) {
        return calculatorMap.getOrDefault(type, calculatorMap.get("actual"));
    }
}

此时您可能会问:“运费模板如何配置?总不能每次修改规则都改动代码吧?”
这正是规则引擎发挥作用的场景。

规则引擎配置运费模板

使用Drools,将运费规则编写为 .drl 文件:

// freight.drl
package com.taocarts.freight;

import com.taocarts.domain.ShippingRequest;
import com.taocarts.domain.FreightResult;

rule "US_YunExpress_Rule"
    when
        $req: ShippingRequest(destinationCountry == "US", channel == "YunExpress")
    then
        FreightRule rule = new FreightRule();
        rule.setFirstWeight(0.5);
        rule.setFirstPrice(new BigDecimal("85"));
        rule.setAdditionalUnit(0.5);
        rule.setAdditionalPrice(new BigDecimal("25"));
        rule.setCalculatorType("actual");
        $req.setMatchedRule(rule);
end

rule "US_EMS_Rule"
    when
        $req: ShippingRequest(destinationCountry == "US", channel == "EMS")
    then
        FreightRule rule = new FreightRule();
        rule.setFirstWeight(0.5);
        rule.setFirstPrice(new BigDecimal("110"));
        rule.setAdditionalUnit(0.5);
        rule.setAdditionalPrice(new BigDecimal("35"));
        rule.setCalculatorType("volumetric");
        $req.setMatchedRule(rule);
end

这样一来,新增渠道或调整费率只需修改 DRL 文件,无需重启应用(配合热加载效果更优)。

合并发货与拼单分摊

在实际业务场景中,用户常将多个订单合并发货,并按重量分摊运费。

@Service
public class CombinedFreightService {
    public CombinedFreightResult combineAndCalculate(List orderIds, String channel) {
        // 1. 汇总订单商品
        List orders = orderService.listByIds(orderIds);
        double totalActualWeight = orders.stream()
            .mapToDouble(Order::getTotalWeight).sum();
        double totalVolumetricWeight = orders.stream()
            .mapToDouble(o -> o.getLengthCm() * o.getWidthCm() * o.getHeightCm() / 5000.0)
            .max().orElse(0);
        double finalWeight = Math.max(totalActualWeight, totalVolumetricWeight);

        // 2. 获取运费规则
        FreightRule rule = freightRuleMapper.selectByChannelAndCountry(
            channel, orders.get(0).getCountry());
        FreightCalculator calculator = calculatorFactory.getCalculator(rule.getCalculatorType());
        BigDecimal totalFreight = calculator.calculate(new ShippingPackage(finalWeight), rule);

        // 3. 按重量分摊
        List shares = new ArrayList<>();
        for (Order order : orders) {
            double shareRatio = order.getTotalWeight() / totalActualWeight;
            BigDecimal shareFreight = totalFreight.multiply(BigDecimal.valueOf(shareRatio));
            shares.add(new FreightShare(order.getId(), shareFreight));
        }
        return new CombinedFreightResult(totalFreight, shares);
    }
}

请注意:体积重取各订单中的最大值(代表整箱体积),实际重量累加,最终取较大值。分摊逻辑较为基础,按实际重量比例分配。如有特殊需求(例如大件商品单独计费),需进一步细化。

性能优化

运费计算频率高,性能优化必不可少。以下是几种常用手段:

  • 将运费模板缓存至Redis,每小时刷新一次,避免频繁查询数据库。
  • 体积重计算采用本地缓存,对同一包裹重复计算时直接返回结果。
  • 批量计费时使用 CompletableFuture 并行处理,充分利用多核CPU。

压测结果表明,单机可承受每秒500次运费计算请求,P99延迟低于50ms,满足业务需求。

来源:https://developer.aliyun.com/article/1741560
上一篇最新人工智能与大数据行业应用案例精选 下一篇人工智能与嵌入式AI融合发展模式探究
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
Windows Docker Desktop RabbitMQ生产级部署完整指南
AI教程 · 2026-06-29

Windows Docker Desktop RabbitMQ生产级部署完整指南

前言 在 Windows 本地开发环境中,直接安装 RabbitMQ 确实颇为周折:需要单独配置 Erlang 运行环境、手动管理环境变量、服务启停全凭手工操作。更令人困扰的是,版本兼容冲突、端口占用、环境不一致等问题层出不穷。笔者见过不少开发者为搭建环境就得耗费整整半天时间。 相比之下,借助 Do

AI搜索重构制造业采购逻辑的阿里云企业级GEOCMS优化实践
AI教程 · 2026-06-29

AI搜索重构制造业采购逻辑的阿里云企业级GEOCMS优化实践

先分享一个切实感受。过去两年,我们与福建制造企业合作较为频繁,发现一个非常突出的现象:超过80%的企业官网,产品参数仍然存放在PDF或图片中。AI爬虫?根本无法抓取。这些企业技术实力不弱、资质证照齐全、应用案例也丰富,但在AI搜索这一全新战场上,它们几乎处于隐身状态。 一、一个正在发生的行业变化 A

阿里云Token Plan团队版功能价格与省钱购买指南
AI教程 · 2026-06-29

阿里云Token Plan团队版功能价格与省钱购买指南

阿里云百炼近期推出了名为“Token Plan 团队版”的全新服务,这一服务专为企业与开发者量身打造,定位为AI大模型订阅平台。通过引入Credits作为统一计量单位,将文本生成、图像生成等多模态AI能力纳入单一计费体系,同时无缝兼容主流AI编程工具及智能体(Agent)生态系统。其核心亮点包括:全

阿里云物联网.NET Core客户端位置信息上报
AI教程 · 2026-06-29

阿里云物联网.NET Core客户端位置信息上报

阿里云物联网平台的位置服务并非一个完全独立的功能模块。位置信息可包含二维坐标与三维坐标,而位置数据的来源本质上是借助设备属性进行上传。换言之,若要让设备上报位置,您需先将其视为一个普通属性进行处理。 1)添加二维位置数据 操作过程十分简洁。进入数据分析 → 空间数据可视化 → 二维数据,点击添加,将

年阿里云服务器选型配置与网站部署全攻略
AI教程 · 2026-06-29

年阿里云服务器选型配置与网站部署全攻略

2026年,阿里云服务器生态已高度成熟,形成了清晰的轻量应用服务器与ECS云服务器两大产品阵营。无论你是计划搭建个人博客、企业官网,还是运营电商平台、进行应用开发,基本都能找到理想的解决方案。本指南将从服务器选型、配置选择、部署流程到安全运维,系统梳理2026年最实用的操作要点,帮助你少走弯路,让网