脚本包导入实战:JQuick-Java自定义包引入与别名配置教程
前言
规则脚本调用 Java 类型时,写全限定名(java.util.HashMap<java.lang.String,java.lang.String>)不仅冗长还易错。JQuick-Java 提供脚本包导入机制:import 全限定名 as 别名;,一次声明、脚本内短名引用。统一入口 importPackage 更把它变成一行链式调用。本文详解 JQuick-Java 自定义包引入与别名配置的完整用法。
核心技术原理
包导入的语法与解析链路:
- 语法层 :文法
importDeclaration: IMPORT paramType AS importVar SEMICOLON;,paramType支持简单类型、泛型(List<java.lang.String>)、Map/Set/数组等; - 解析层 :
JQuickJavaImportVisitor把 import 语句注册到全局容器JQuickJavaImportContainerModel(别名 → JQuickJavaTypeReference),脚本内以别名引用类型时按容器解析为真实类型; - 入口层 :
importPackage(qualifiedName, alias)生成import 全限定名 as 别名;语句加入包声明列表;importPackage(qualifiedName)自动取最后一段做别名。
幂等注册是关键:同一 JVM 内重复执行脚本时,registerImports() 检测到别名已存在则跳过,避免「already has been imported」异常。
实战代码演示
1. 基础别名导入
java
JQuickJava.create()
.importPackage("java.lang.String", "type1") // import java.lang.String as type1;
.importPackage("java.util.Date", "JDate") // import java.util.Date as JDate;
.createApi(ScoringMapper.class, "scoring-rules.xml");
脚本内即可用别名:
jquick
type1 def mask(str:name) {
return type1::valueOf(name); // 等价 java.lang.String::valueOf
}
2. 自动别名导入
java
// 自动取最后一段:java.lang.String → String
JQuickJava.create().importPackage("java.lang.String");
// 批量自动别名
JQuickJava.create().importPackages("java.util.Date", "java.util.Map");
3. 泛型导入(必须显式别名)
jquick
// 脚本级语法
import List<java.lang.String> as StringList;
StringList list=["A","B","C"];
java
// 入口级 API:含 < 必须指定别名
JQuickJava.create()
.importPackage("List<java.lang.String>", "StringList")
.execute("StringList list = [\"A\",\"B\",\"C\"];");
4. 脚本内直接声明 import(JQuickJavaExecutor 路径)
java
String rule = "import java.lang.String as string;\n" +
"import java.lang.System as system;\n" +
"string def getSquare(int:a,int:b){\n" +
" system@out.println(int:a);\n" +
" return a+b;\n" +
"}\n" +
"int a=2; int b=2;\n" +
"string c=this.getSquare(int:a,int:b);";
Object result = JQuickJavaExecutor.getInstance().execute(rule);
核心技术细节解析
- 泛型导入规则 :含
<的全限定名(List<java.lang.String>)无法自动取别名,importPackage(qualifiedName)会抛IllegalArgumentException: generic import requires explicit alias,必须走importPackage(name, alias)。 - 别名作用域 :别名在全局导入容器注册(
JQuickJavaImportContainerModel.getInstance()单例),同一 JVM 内跨脚本共享,同名别名以首次注册为准(幂等)。 - 类型解析 :
JQuickJavaTypeReferenceFactory.fromTypeString优先按类型字符串解析(支持泛型),失败回退fromClassName类名加载。 - 不生成重复 import 行 :
buildScript会检查别名是否已注册,已存在则不生成 import 行,从源头防重复。
常见踩坑与解决方案
- 别名冲突:不同脚本对同一类型声明不同别名没问题,但同一别名指向不同类型时,首次注册生效,后续注册被忽略------避免全局别名与业务语义强绑定。
- 误用未导入的类型:脚本内引用未 import 的短名类型会解析失败,统一使用全限定名或先 import。
- 大小写敏感 :别名与类型名大小写敏感,
import java.lang.string(小写 s)无法解析String。
最佳实践
- 常用类型(String、Date、List、Map)在入口统一
importPackage,脚本保持短名可读。 - 泛型类型固定走显式别名,避免每次手写
List<java.lang.String>。 - 接口级导入集中管理(如
TEmEventScoringServiceTest的setUp中统一导入str、JDate),保证规则脚本风格一致。
总结
JQuick-Java 的脚本包导入机制,用 import Type as Alias; 把全限定类型名收敛为短名:普通类型自动别名、泛型显式别名、全局容器幂等注册,配合入口 importPackage 链式 API,让规则脚本简洁且无重复导入之虞。对规则脚本可读性有要求的团队,这套别名体系值得纳入规范。