# liquor
**Repository Path**: javakf/liquor
## Basic Information
- **Project Name**: liquor
- **Description**: Java 动态编译、表达式、脚本工具(兼容 jar in jar)
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 67
- **Created**: 2024-09-21
- **Last Updated**: 2024-09-21
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
Liquor
Java 动态编译、表达式、脚本工具(兼容 jar in jar)
本工具的编译器代码主要源自 arthas。相关的知识点比较冷门,甚是珍贵。为了复用方便,特整理成一个小工具包进行长期维护。后来又增加了表达式、脚本支持。
| 工件 | 大小 | 功能 | 功能描述 |
|----------------|------|---------------------------------------------------------|-----------------------|
| liquor | 24KB | DynamicCompiler | 编译一个或多个类 |
| liquor-eval | 16KB | ExpressionEvaluator, Exprs
ScriptEvaluator, Scripts | 评估表达式(就是,运行)
评估脚本 |
引用依赖:
```xml
org.noear
liquor-eval
1.3.0
```
性能表现(第三方性能测试,榜首):
* [https://gitee.com/xiandafu/beetl/tree/master/express-benchmark](https://gitee.com/xiandafu/beetl/tree/master/express-benchmark)
## 编译器演示
可以有包名;可以导入类;可相互依赖;可多次不重复编译;跟平常写 java 类一样。
```java
public class DemoApp {
public static void main(String[] args) throws Exception{
//可以复用(不要,不断的新建)
DynamicCompiler compiler = new DynamicCompiler();
String className = "HelloWorld";
String classCode = "import java.util.HashMap;\n\n"+
"public class HelloWorld { " +
" public static void helloWorld() { " +
" System.out.println(\"Hello, world!\"); " +
" } " +
"}";
//添加源码(可多个)并 构建
compiler.addSource(className, classCode).build();
Class> clazz = compiler.getClassLoader().loadClass(className);
clazz.getMethod("helloWorld").invoke(null);
}
}
```
## 评估器演示
内部会把评估代码编译为一个静态方法
### 1) 表达式评估器(只能写一行代码)
* 必须有结果返回
* 表达式中没有 ";" 时,评估器会自动添加 "return" 和 ";"。否则要自己确保语句完整
* 使用 CodeSpec::imports 导入表达式需要的类
```java
public class DemoApp {
public static void main(String[] args) throws Exception {
//基础
System.out.println(Exprs.eval("1+1"));
//进阶
CodeSpec code1 = new CodeSpec("aa + 22").parameters(new ParamSpec("aa", Integer.class));
System.out.println(Exprs.eval(code1, 1)); //=> 23
Map context2 = new HashMap<>();
context2.put("bb", 3);
System.out.println(Exprs.eval("bb + 22", context2)); //=>25
System.out.println(Exprs.eval(new CodeSpec("Math.min(1,2)").imports(Math.class))); //=>1
}
}
```
### 2) 脚本评估器
* 可以导入类;不能有包名
* 使用内部类时不要加 "public" 修饰
* 使用 CodeSpec::imports 导入表达式需要的类;或者在代码里添加 "import" 语句
```java
public class DemoApp {
public static void main(String[] args) throws Exception {
//基础
Scripts.eval("System.out.println(\"hello word\");");
//进阶(如果有内部类,不要加 public)
CodeSpec code1 = new CodeSpec("import java.util.HashMap;\n\n"+
" class Demo {\n" +
" public String hello(String word) {\n" +
" return word;\n" +
" }\n" +
" }\n" +
"\n" +
" Demo demo = new Demo();\n" +
" return demo.hello(name);") //name 为外部参数
.parameters(new ParamSpec("name", String.class))
.returnType(String.class);
System.out.println(Scripts.eval(code1, "noear")); //=>noear
}
}
```