This commit is contained in:
Looly 2023-04-14 00:35:15 +08:00
parent c5e593e5fd
commit a3ae323d3a
18 changed files with 505 additions and 103 deletions

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.core.func;
/**
* 简单包装对象
*
* @param <T> 被包装对象类型
* @author looly
* @since 6.0.0
*/
public class SimpleWrapper<T> implements Wrapper<T> {
protected final T raw;
/**
* 构造
*
* @param raw 原始对象
*/
public SimpleWrapper(final T raw) {
this.raw = raw;
}
@Override
public T getRaw() {
return this.raw;
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.extra.expression;
import java.util.Map;
/**
* 表达式定义用于表示编译后的表达式
*
* @author looly
* @since 6.0.0
*/
public interface Expression {
/**
* 执行表达式
*
* @param context 表达式上下文用于存储表达式中所需的变量值等
* @return 执行结果
*/
Object eval(final Map<String, Object> context);
}

View File

@ -17,16 +17,27 @@ import java.util.Map;
/**
* 表达式引擎API接口通过实现此接口完成表达式的解析和执行
*
* @author looll,independenter
* @author looll, independenter
* @since 5.5.0
*/
public interface ExpressionEngine {
/**
* 执行表达式
* 编译表达式
*
* @param expression 表达式
* @param context 表达式上下文用于存储表达式中所需的变量值等
* @return {@link Expression}
*/
Expression compile(String expression);
/**
* 执行表达式
*
* @param expression 表达式
* @param context 表达式上下文用于存储表达式中所需的变量值等
* @return 执行结果
*/
Object eval(String expression, Map<String, Object> context);
default Object eval(final String expression, final Map<String, Object> context){
return compile(expression).eval(context);
}
}

View File

@ -12,41 +12,30 @@
package org.dromara.hutool.extra.expression.engine.aviator;
import org.dromara.hutool.extra.expression.ExpressionEngine;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.AviatorEvaluatorInstance;
import java.util.Map;
import org.dromara.hutool.core.func.SimpleWrapper;
import org.dromara.hutool.extra.expression.Expression;
import org.dromara.hutool.extra.expression.ExpressionEngine;
/**
* Aviator引擎封装<br>
* <a href="https://github.com/killme2008/aviatorscript">https://github.com/killme2008/aviatorscript</a>
*
* @author looly
* @since 5.5.0
*/
public class AviatorEngine implements ExpressionEngine {
private final AviatorEvaluatorInstance engine;
public class AviatorEngine extends SimpleWrapper<AviatorEvaluatorInstance>
implements ExpressionEngine {
/**
* 构造
*/
public AviatorEngine() {
engine = AviatorEvaluator.getInstance();
super(AviatorEvaluator.getInstance());
}
@Override
public Object eval(final String expression, final Map<String, Object> context) {
return engine.execute(expression, context);
}
/**
* 获取{@link AviatorEvaluatorInstance}
*
* @return {@link AviatorEvaluatorInstance}
*/
public AviatorEvaluatorInstance getEngine() {
return this.engine;
public Expression compile(final String expression) {
return new AviatorExpression(this.raw.compile(expression));
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.extra.expression.engine.aviator;
import org.dromara.hutool.core.func.SimpleWrapper;
import org.dromara.hutool.extra.expression.Expression;
import java.util.Map;
/**
* {@link com.googlecode.aviator.Expression} 包装
*
* @author looly
* @since 6.0.0
*/
public class AviatorExpression extends SimpleWrapper<com.googlecode.aviator.Expression> implements Expression {
/**
* 构造
*
* @param expression {@link com.googlecode.aviator.Expression}
*/
public AviatorExpression(final com.googlecode.aviator.Expression expression) {
super(expression);
}
@Override
public Object eval(final Map<String, Object> context) {
return this.raw.execute(context);
}
}

View File

@ -12,11 +12,10 @@
package org.dromara.hutool.extra.expression.engine.jexl;
import org.dromara.hutool.extra.expression.ExpressionEngine;
import org.apache.commons.jexl3.JexlBuilder;
import org.apache.commons.jexl3.MapContext;
import java.util.Map;
import org.dromara.hutool.core.func.SimpleWrapper;
import org.dromara.hutool.extra.expression.Expression;
import org.dromara.hutool.extra.expression.ExpressionEngine;
/**
* Jexl3引擎封装<br>
@ -25,36 +24,30 @@ import java.util.Map;
* @since 5.5.0
* @author looly
*/
public class JexlEngine implements ExpressionEngine {
private final org.apache.commons.jexl3.JexlEngine engine;
public class JexlEngine extends SimpleWrapper<org.apache.commons.jexl3.JexlEngine>
implements ExpressionEngine {
/**
* 构造
*/
public JexlEngine(){
engine = (new JexlBuilder()).cache(512).strict(true).silent(false).create();
super(
(new JexlBuilder())
.cache(512)
.strict(true)
.silent(false)
.create()
);
}
@Override
public Object eval(final String expression, final Map<String, Object> context) {
final MapContext mapContext = new MapContext(context);
public Expression compile(final String expression) {
try{
return engine.createExpression(expression).evaluate(mapContext);
return new JexlExpression(this.raw.createExpression(expression));
} catch (final Exception ignore){
// https://gitee.com/dromara/hutool/issues/I4B70D
// 支持脚本
return engine.createScript(expression).execute(mapContext);
return new JexlScript(this.raw.createScript(expression));
}
}
/**
* 获取{@link org.apache.commons.jexl3.JexlEngine}
*
* @return {@link org.apache.commons.jexl3.JexlEngine}
*/
public org.apache.commons.jexl3.JexlEngine getEngine() {
return this.engine;
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.extra.expression.engine.jexl;
import org.apache.commons.jexl3.MapContext;
import org.dromara.hutool.core.func.SimpleWrapper;
import org.dromara.hutool.extra.expression.Expression;
import java.util.Map;
/**
* Jexl3引擎的{@link org.apache.commons.jexl3.JexlExpression}包装
*
* @author looly
*/
public class JexlExpression extends SimpleWrapper<org.apache.commons.jexl3.JexlExpression>
implements Expression {
/**
* 构造
*
* @param raw {@link org.apache.commons.jexl3.JexlExpression}
*/
public JexlExpression(final org.apache.commons.jexl3.JexlExpression raw) {
super(raw);
}
@Override
public Object eval(final Map<String, Object> context) {
final MapContext mapContext = new MapContext(context);
return raw.evaluate(mapContext);
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.extra.expression.engine.jexl;
import org.apache.commons.jexl3.MapContext;
import org.dromara.hutool.core.func.Wrapper;
import org.dromara.hutool.extra.expression.Expression;
import java.util.Map;
/**
* Jexl3引擎的{@link org.apache.commons.jexl3.JexlScript}包装
*
* @author looly
*/
public class JexlScript implements Expression, Wrapper<org.apache.commons.jexl3.JexlScript> {
private final org.apache.commons.jexl3.JexlScript raw;
/**
* 构造
*
* @param raw {@link org.apache.commons.jexl3.JexlScript}
*/
public JexlScript(final org.apache.commons.jexl3.JexlScript raw) {
this.raw = raw;
}
@Override
public Object eval(final Map<String, Object> context) {
final MapContext mapContext = new MapContext(context);
return raw.execute(mapContext);
}
@Override
public org.apache.commons.jexl3.JexlScript getRaw() {
return raw;
}
}

View File

@ -12,10 +12,8 @@
package org.dromara.hutool.extra.expression.engine.jfireel;
import org.dromara.hutool.extra.expression.Expression;
import org.dromara.hutool.extra.expression.ExpressionEngine;
import com.jfirer.jfireel.expression.Expression;
import java.util.Map;
/**
* JfireEL引擎封装<br>
@ -26,14 +24,9 @@ import java.util.Map;
*/
public class JfireELEngine implements ExpressionEngine {
/**
* 构造
*/
public JfireELEngine(){
}
@Override
public Object eval(final String expression, final Map<String, Object> context) {
return Expression.parse(expression).calculate(context);
public Expression compile(final String expression) {
return new JfireELExpression(
com.jfirer.jfireel.expression.Expression.parse(expression));
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.extra.expression.engine.jfireel;
import org.dromara.hutool.core.func.SimpleWrapper;
import java.util.Map;
/**
* JfireEL引擎表达式{@link com.jfirer.jfireel.expression.Expression} 封装
*
* @author looly
*/
public class JfireELExpression extends SimpleWrapper<com.jfirer.jfireel.expression.Expression>
implements org.dromara.hutool.extra.expression.Expression {
/**
* 构造
*
* @param expression {@link com.jfirer.jfireel.expression.Expression}
*/
public JfireELExpression(final com.jfirer.jfireel.expression.Expression expression) {
super(expression);
}
@Override
public Object eval(final Map<String, Object> context) {
return this.raw.calculate(context);
}
}

View File

@ -12,10 +12,8 @@
package org.dromara.hutool.extra.expression.engine.mvel;
import org.dromara.hutool.extra.expression.Expression;
import org.dromara.hutool.extra.expression.ExpressionEngine;
import org.mvel2.MVEL;
import java.util.Map;
/**
* MVEL (MVFLEX Expression Language)引擎封装<br>
@ -33,7 +31,7 @@ public class MvelEngine implements ExpressionEngine {
}
@Override
public Object eval(final String expression, final Map<String, Object> context) {
return MVEL.eval(expression, context);
public Expression compile(final String expression) {
return new MvelExpression(expression);
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.extra.expression.engine.mvel;
import org.dromara.hutool.core.func.SimpleWrapper;
import org.dromara.hutool.extra.expression.Expression;
import org.mvel2.MVEL;
import org.mvel2.templates.TemplateCompiler;
import java.util.Map;
/**
* MVEL2的{@link TemplateCompiler}包装
*
* @author looly
*/
public class MvelExpression extends SimpleWrapper<String>
implements Expression {
/**
* 构造
*
* @param expression 表达式字符串
*/
public MvelExpression(final String expression) {
super(expression);
}
@Override
public Object eval(final Map<String, Object> context) {
return MVEL.eval(this.raw, context);
}
}

View File

@ -12,12 +12,9 @@
package org.dromara.hutool.extra.expression.engine.qlexpress;
import org.dromara.hutool.extra.expression.ExpressionEngine;
import org.dromara.hutool.extra.expression.ExpressionException;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import java.util.Map;
import org.dromara.hutool.extra.expression.Expression;
import org.dromara.hutool.extra.expression.ExpressionEngine;
/**
* QLExpress引擎封装<br>
@ -37,14 +34,9 @@ public class QLExpressEngine implements ExpressionEngine {
engine = new ExpressRunner();
}
@Override
public Object eval(final String expression, final Map<String, Object> context) {
final DefaultContext<String, Object> defaultContext = new DefaultContext<>();
defaultContext.putAll(context);
try {
return engine.execute(expression, defaultContext, null, true, false);
} catch (final Exception e) {
throw new ExpressionException(e);
}
public Expression compile(final String expression) {
return new QLExpressExpression(this.engine, expression);
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.extra.expression.engine.qlexpress;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import org.dromara.hutool.core.func.SimpleWrapper;
import org.dromara.hutool.extra.expression.Expression;
import org.dromara.hutool.extra.expression.ExpressionException;
import java.util.Map;
/**
* QLExpress引擎表达式封装<br>
* 由于QLExpress引擎使用字符串缓存方式存储表达式树故此处无需存储表达式对象
*
* @author looly
*/
public class QLExpressExpression extends SimpleWrapper<String>
implements Expression {
private final ExpressRunner engine;
/**
* 构造
*
* @param engine {@link ExpressRunner}
* @param expression 表达式字符串
*/
public QLExpressExpression(final ExpressRunner engine, final String expression) {
super(expression);
this.engine = engine;
}
@Override
public Object eval(final Map<String, Object> context) {
final DefaultContext<String, Object> defaultContext = new DefaultContext<>();
defaultContext.putAll(context);
try {
return engine.execute(this.raw, defaultContext, null, true, false);
} catch (final Exception e) {
throw new ExpressionException(e);
}
}
}

View File

@ -12,13 +12,8 @@
package org.dromara.hutool.extra.expression.engine.rhino;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.extra.expression.Expression;
import org.dromara.hutool.extra.expression.ExpressionEngine;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import java.util.Map;
/**
* rhino引擎封装<br>
@ -30,16 +25,7 @@ import java.util.Map;
public class RhinoEngine implements ExpressionEngine {
@Override
public Object eval(final String expression, final Map<String, Object> context) {
try(final Context ctx = Context.enter()){
final Scriptable scope = ctx.initStandardObjects();
if (MapUtil.isNotEmpty(context)) {
context.forEach((key, value)->{
// 将java对象转为js对象后放置于JS的作用域中
ScriptableObject.putProperty(scope, key, Context.javaToJS(value, scope));
});
}
return ctx.evaluateString(scope, expression, "rhino.js", 1, null);
} // auto close
public Expression compile(final String expression) {
return new RhinoExpression(expression);
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.extra.expression.engine.rhino;
import org.dromara.hutool.core.func.SimpleWrapper;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.extra.expression.Expression;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import java.util.Map;
/**
* rhino引擎表达式包装
*
* @author looly
*/
public class RhinoExpression extends SimpleWrapper<String>
implements Expression {
private static final String SOURCE_RHINO_JS = "rhino.js";
/**
* 构造
*
* @param expression 表达式
*/
public RhinoExpression(final String expression) {
super(expression);
}
@Override
public Object eval(final Map<String, Object> context) {
try (final Context ctx = Context.enter()) {
final Scriptable scope = ctx.initStandardObjects();
if (MapUtil.isNotEmpty(context)) {
context.forEach((key, value) -> {
// 将java对象转为js对象后放置于JS的作用域中
ScriptableObject.putProperty(scope, key, Context.javaToJS(value, scope));
});
}
return ctx.evaluateString(scope, this.raw,
SOURCE_RHINO_JS, 1, null);
} // auto close
}
}

View File

@ -12,13 +12,11 @@
package org.dromara.hutool.extra.expression.engine.spel;
import org.dromara.hutool.core.func.SimpleWrapper;
import org.dromara.hutool.extra.expression.Expression;
import org.dromara.hutool.extra.expression.ExpressionEngine;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import java.util.Map;
/**
* Spring-Expression引擎封装<br>
@ -27,21 +25,17 @@ import java.util.Map;
* @since 5.5.0
* @author looly
*/
public class SpELEngine implements ExpressionEngine {
private final ExpressionParser parser;
public class SpELEngine extends SimpleWrapper<ExpressionParser> implements ExpressionEngine {
/**
* 构造
*/
public SpELEngine(){
parser = new SpelExpressionParser();
super(new SpelExpressionParser());
}
@Override
public Object eval(final String expression, final Map<String, Object> context) {
final EvaluationContext evaluationContext = new StandardEvaluationContext();
context.forEach(evaluationContext::setVariable);
return parser.parseExpression(expression).getValue(evaluationContext);
public Expression compile(final String expression) {
return new SpELExpression(this.raw.parseExpression(expression));
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.extra.expression.engine.spel;
import org.dromara.hutool.core.func.SimpleWrapper;
import org.dromara.hutool.extra.expression.Expression;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import java.util.Map;
/**
* Spring-Expression引擎表达式{@link org.springframework.expression.Expression} 包装
*
* @author looly
*/
public class SpELExpression extends SimpleWrapper<org.springframework.expression.Expression>
implements Expression {
/**
* 构造
*
* @param expression {@link org.springframework.expression.Expression}
*/
public SpELExpression(final org.springframework.expression.Expression expression) {
super(expression);
}
@Override
public Object eval(final Map<String, Object> context) {
final EvaluationContext evaluationContext = new StandardEvaluationContext();
context.forEach(evaluationContext::setVariable);
return this.raw.getValue(evaluationContext);
}
}