From 13b3f2484555b69dd25b280806f98d98d53f75fe Mon Sep 17 00:00:00 2001 From: Charles7c Date: Fri, 28 Jun 2024 23:03:56 +0800 Subject: [PATCH] =?UTF-8?q?feat(core):=20=E6=96=B0=E5=A2=9E=E8=A1=A8?= =?UTF-8?q?=E8=BE=BE=E5=BC=8F=E8=A7=A3=E6=9E=90=E5=B7=A5=E5=85=B7=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/expression/ExpressionEvaluator.java | 44 +++++++++++ .../expression/ExpressionInvokeContext.java | 73 +++++++++++++++++++ .../core/util/expression/ExpressionUtils.java | 60 +++++++++++++++ .../core/util/expression/SpelEvaluator.java | 67 +++++++++++++++++ 4 files changed, 244 insertions(+) create mode 100644 continew-starter-core/src/main/java/top/continew/starter/core/util/expression/ExpressionEvaluator.java create mode 100644 continew-starter-core/src/main/java/top/continew/starter/core/util/expression/ExpressionInvokeContext.java create mode 100644 continew-starter-core/src/main/java/top/continew/starter/core/util/expression/ExpressionUtils.java create mode 100644 continew-starter-core/src/main/java/top/continew/starter/core/util/expression/SpelEvaluator.java diff --git a/continew-starter-core/src/main/java/top/continew/starter/core/util/expression/ExpressionEvaluator.java b/continew-starter-core/src/main/java/top/continew/starter/core/util/expression/ExpressionEvaluator.java new file mode 100644 index 00000000..aa77feea --- /dev/null +++ b/continew-starter-core/src/main/java/top/continew/starter/core/util/expression/ExpressionEvaluator.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.continew.starter.core.util.expression; + +import java.lang.reflect.Method; +import java.util.function.Function; + +/** + * 表达式解析器 + * + * @author Charles7c + * @since 2.2.0 + */ +public class ExpressionEvaluator implements Function { + + private final Function evaluator; + + public ExpressionEvaluator(String script, Method defineMethod) { + this.evaluator = new SpelEvaluator(script, defineMethod); + } + + @Override + public Object apply(Object rootObject) { + return evaluator.apply(rootObject); + } + + Function getEvaluator() { + return evaluator; + } +} diff --git a/continew-starter-core/src/main/java/top/continew/starter/core/util/expression/ExpressionInvokeContext.java b/continew-starter-core/src/main/java/top/continew/starter/core/util/expression/ExpressionInvokeContext.java new file mode 100644 index 00000000..0eedf27f --- /dev/null +++ b/continew-starter-core/src/main/java/top/continew/starter/core/util/expression/ExpressionInvokeContext.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.continew.starter.core.util.expression; + +import java.lang.reflect.Method; + +/** + * 表达式上下文 + * + * @author Charles7c + * @since 2.2.0 + */ +public class ExpressionInvokeContext { + + /** + * 目标方法 + */ + private Method method; + + /** + * 方法参数 + */ + private Object[] args; + + /** + * 目标对象 + */ + private Object target; + + public ExpressionInvokeContext(Method method, Object[] args, Object target) { + this.method = method; + this.args = args; + this.target = target; + } + + public Method getMethod() { + return method; + } + + public void setMethod(Method method) { + this.method = method; + } + + public void setArgs(Object[] args) { + this.args = args; + } + + public Object[] getArgs() { + return args; + } + + public Object getTarget() { + return target; + } + + public void setTarget(Object target) { + this.target = target; + } +} diff --git a/continew-starter-core/src/main/java/top/continew/starter/core/util/expression/ExpressionUtils.java b/continew-starter-core/src/main/java/top/continew/starter/core/util/expression/ExpressionUtils.java new file mode 100644 index 00000000..ff4c1383 --- /dev/null +++ b/continew-starter-core/src/main/java/top/continew/starter/core/util/expression/ExpressionUtils.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.continew.starter.core.util.expression; + +import cn.hutool.core.text.CharSequenceUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Method; + +/** + * 表达式解析工具类 + * + * @author Charles7c + * @since 2.2.0 + */ +public class ExpressionUtils { + + private static final Logger log = LoggerFactory.getLogger(ExpressionUtils.class); + + private ExpressionUtils() { + } + + /** + * 解析 + * + * @param script 表达式 + * @param target 目标对象 + * @param method 目标方法 + * @param args 方法参数 + * @return 解析结果 + */ + public static Object eval(String script, Object target, Method method, Object... args) { + try { + if (CharSequenceUtil.isBlank(script)) { + return null; + } + ExpressionEvaluator expressionEvaluator = new ExpressionEvaluator(script, method); + ExpressionInvokeContext invokeContext = new ExpressionInvokeContext(method, args, target); + return expressionEvaluator.apply(invokeContext); + } catch (Exception e) { + log.error("Error occurs when eval script \"{}\" in {} : {}", script, method, e.getMessage(), e); + return null; + } + } +} diff --git a/continew-starter-core/src/main/java/top/continew/starter/core/util/expression/SpelEvaluator.java b/continew-starter-core/src/main/java/top/continew/starter/core/util/expression/SpelEvaluator.java new file mode 100644 index 00000000..f1e08f29 --- /dev/null +++ b/continew-starter-core/src/main/java/top/continew/starter/core/util/expression/SpelEvaluator.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.continew.starter.core.util.expression; + +import org.springframework.core.DefaultParameterNameDiscoverer; +import org.springframework.core.ParameterNameDiscoverer; +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; + +import java.lang.reflect.Method; +import java.util.function.Function; + +/** + * Spring EL 表达式解析器 + * + * @author Charles7c + * @since 2.2.0 + */ +public class SpelEvaluator implements Function { + + private static final ExpressionParser PARSER; + private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER; + + static { + PARSER = new SpelExpressionParser(); + PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer(); + } + + private final Expression expression; + private String[] parameterNames; + + public SpelEvaluator(String script, Method defineMethod) { + expression = PARSER.parseExpression(script); + if (defineMethod.getParameterCount() > 0) { + parameterNames = PARAMETER_NAME_DISCOVERER.getParameterNames(defineMethod); + } + } + + @Override + public Object apply(Object rootObject) { + EvaluationContext context = new StandardEvaluationContext(rootObject); + ExpressionInvokeContext invokeContext = (ExpressionInvokeContext)rootObject; + if (parameterNames != null) { + for (int i = 0; i < parameterNames.length; i++) { + context.setVariable(parameterNames[i], invokeContext.getArgs()[i]); + } + } + return expression.getValue(context); + } +} \ No newline at end of file