欢迎光临
我们一直在努力

XML规则代理实战:JQuick-Java接口绑定XML业务规则配置教程

XML规则代理实战:JQuick-Java接口绑定XML业务规则配置教程

前言

规则引擎落地时最常用的形态是:Java 接口声明契约、XML 文件承载规则、运行时自动生成动态代理——业务代码只依赖接口,规则内容完全外置。JQuick-Java 的 XML 规则代理正是这种形态的标准实现:接口方法名对应 XML 规则名,@Param 注解绑定脚本参数,createApi 一行生成代理。本文给出完整的 XML 规则代理配置教程与底层原理拆解。

核心技术原理

XML 规则代理的装配链路(源码位于 xml 包):

  • JQuickJavaXmlParseFactory 创建 XML 解析工厂;
  • JQuickXmlParser.parse(xmlPath) 解析 XML 文件,javas namespace 对应接口全限定名,每个 <java name="方法名" returnClass="返回类型"> 成为一个 JQuickXmlMethod;
  • JQuickXmlFactory.createApi(apiInterface) 基于 namespace 集合生成接口动态代理;
  • 调用代理方法时,JQuickJavaXmlInvocationHandler.loadResult 依次完成:ParamUtil.bindParams 按 @Param 绑定方法参数 → functionDefinition 用 ANTLR 解析 CDATA 函数定义 → JQuickJavaActionExecutor 执行函数体 → JQuickValueTransformer 按接口返回类型转换结果。
  • 实战代码演示

    1. 定义规则接口

    public interface RulesMapper {
    int scoreReportTime(@Param("eventType") String eventType,
    @Param("reportMinutes") int reportMinutes);

    double scoreCoordination(@Param("eventType") String eventType,
    @Param("replyMinutes") int replyMinutes);

    double calculateSingleEventScore(@Param("eventType") String eventType,
    @Param("reportMinutes") int reportMinutes,
    @Param("replyMinutes") int replyMinutes,
    @Param("closureDays") int closureDays,
    @Param("dispatchScore") int dispatchScore,
    @Param("qualityScore") int qualityScore);
    }

    2. 编写 XML 规则文件(rules.xml)

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE javas PUBLIC "-//PAOHAIJIAO//DTD API JAVA 1.0//EN"
    "classpath:paohaijiao/dtd/Jquick-java.dtd">

    <javas namespace="com.github.paohaijiao.xml.RulesMapper">

    <java name="scoreReportTime" returnClass="int">
    <![CDATA[
    int def scoreReportTime(str:eventType, int:reportMinutes) {
    int score = 0;
    int maxScore = 40;
    int bonusScore = 10;
    if (eventType == "A") {
    if (reportMinutes <= 60) {
    score = maxScore + (60 – reportMinutes) * bonusScore / 60;
    } else if (reportMinutes <= 120) {
    score = maxScore – (reportMinutes – 60) * 40 / 60;
    } else {
    score = 0;
    }
    }
    if (score > 50) { score = 50; }
    if (score < 0) { score = 0; }
    return score;
    }
    ]]>

    </java>

    <java name="calculateSingleEventScore" returnClass="double">
    <![CDATA[
    double def calculateSingleEventScore(str:eventType, int:reportMinutes,
    int:replyMinutes, int:closureDays,
    int:dispatchScore, int:qualityScore) {
    int reportScore = this.scoreReportTime(eventType, reportMinutes);
    double coordinationScore = this.scoreCoordination(eventType, replyMinutes);
    int closureScore = this.scoreClosure(closureDays);
    double totalScore = reportScore + coordinationScore + closureScore
    + dispatchScore + qualityScore;
    if (totalScore > 100) { totalScore = 100; }
    return totalScore;
    }
    ]]>

    </java>
    </javas>

    3. 生成代理并调用

    RulesMapper mapper = JQuickJava.create()
    .importPackage("java.lang.String", "str")
    .createApi(RulesMapper.class, "rules.xml");

    int reportScore = mapper.scoreReportTime("A", 20);
    double total = mapper.calculateSingleEventScore("A", 20, 3, 1, 9, 4);

    核心技术细节解析

    • DTD 约束:Jquick-java.dtd 规定 javas 必须有 namespace 属性,java 必须有 name/returnClass 属性;内容可为 #PCDATA 或 if/foreach/choose 等动态标签,为规则拼接预留扩展。
    • 参数类型简写:XML 中可用 str:xxx 简写(前提是接口绑定侧已 importPackage("java.lang.String","str")),也可写全限定名 java.lang.String:xxx。
    • 脚本内调用同接口规则:函数体内用 this.scoreReportTime(eventType, reportMinutes) 调用同 namespace 的其他规则,实现规则编排(无需类型前缀)。
    • 返回值按接口转换:脚本返回 double、接口声明 double,JQuickJavaTypeReference.of(method.getReturnType()) 保证类型一致。

    常见踩坑与解决方案

  • namespace 拼错:必须等于接口全限定名(含包名),JQuickXmlParser 找不到对应 namespace 时代理方法会报空规则。
  • @Param 缺失或改名:脚本 double:actualCapital 依赖参数名绑定,改名后绑定为 null,结果恒为 0。
  • returnClass 与接口不一致:如脚本返回 double 但接口声明 int,转换可能出现截断;请保持两处类型一致。
  • CDATA 内混入非法字符:<、& 在 CDATA 中安全,但在普通文本中需转义;函数定义务必放进 <![CDATA[…]]>。
  • 最佳实践

    • 每个业务域一个 XML 文件、一个 namespace,规则按 name 分类管理,便于维护与版本对比。
    • 阈值类规则写在函数体顶部的变量(如 maxScore/bonusScore)中,集中修改。
    • 代理实例创建成本主要在一次性的 XML 解析,规则不变时复用代理;变更时重新 createApi 即可热更新。

    总结

    JQuick-Java 的 XML 规则代理把「接口契约 + XML 配置 + 动态代理」三者串联,规则即配置、代理即入口,业务代码零规则逻辑。对需要把计分、校验、风控规则交给配置维护的团队,这是最标准的落地形态。

    赞(0)
    未经允许不得转载:171主机测评 » XML规则代理实战:JQuick-Java接口绑定XML业务规则配置教程
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址