Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update ExpressionUtil #17

Merged
merged 2 commits into from
Sep 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.nebula.web.common.utils;

import com.nebula.base.utils.DataUtils;
import java.lang.reflect.Method;
import java.util.Objects;
import org.apache.commons.lang3.StringUtils;
import java.util.Map;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
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;
Expand All @@ -32,36 +32,127 @@
* @description:
*/
public class ExpressionUtil {


private static final ExpressionParser parser = new SpelExpressionParser();

private static final LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();

/**
* el表达式解析
* 解析EL表达式
*
* @param expressionString 解析值
* @param expressionString 表达式字符串
* @param method 方法
* @param args 参数
* @return
* @return 解析结果
*/
public static Object parse(String expressionString, Method method, Object[] args) {
if (DataUtils.isEmpty(expressionString)) {
if (isEmpty(expressionString)) {
return null;
}
// 获取被拦截方法参数名列表
LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
// SPEL解析
String[] paramNames = discoverer.getParameterNames(method);
if (paramNames == null || args == null || paramNames.length != args.length) {
throw new IllegalArgumentException("Method parameter names and argument values do not match.");
EvaluationContext context = createEvaluationContext(method, args);
return parseExpression(expressionString, context);
}

/**
* 解析EL表达式
*
* @param expressionString 表达式字符串
* @param rootObject 根对象
* @return 解析结果
*/
public static Object parse(String expressionString, Object rootObject) {
if (isEmpty(expressionString)) {
return null;
}
// SPEL解析
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
for (int i = 0; i < Objects.requireNonNull(paramNames).length; i++) {
context.setVariable(paramNames[i], args[i]);
return parseExpression(expressionString, rootObject);
}

/**
* 解析EL表达式
*
* @param expressionString 表达式字符串
* @param variables 变量Map
* @return 解析结果
*/
public static Object parse(String expressionString, Map<String, Object> variables) {
if (isEmpty(expressionString)) {
return null;
}
return parser.parseExpression(expressionString).getValue(context);
EvaluationContext context = createEvaluationContext(variables);
return parseExpression(expressionString, context);
}


/**
* 判断是否为EL表达式
*
* @param param 待判断的字符串
* @return 是否为EL表达式
*/
public static boolean isEl(String param) {
return !StringUtils.isEmpty(param) && param.startsWith("#");
return !isEmpty(param) && param.startsWith("#");
}

/**
* 创建EvaluationContext
*
* @param method 方法
* @param args 参数
* @return EvaluationContext
*/
private static EvaluationContext createEvaluationContext(Method method, Object[] args) {
String[] paramNames = discoverer.getParameterNames(method);
EvaluationContext context = new StandardEvaluationContext();
if (paramNames != null) {
for (int i = 0; i < paramNames.length; i++) {
context.setVariable(paramNames[i], args[i]);
}
}
return context;
}

/**
* 创建EvaluationContext
*
* @param variables 变量Map
* @return EvaluationContext
*/
private static EvaluationContext createEvaluationContext(Map<String, Object> variables) {
EvaluationContext context = new StandardEvaluationContext();
variables.forEach(context::setVariable);
return context;
}

/**
* 解析表达式
*
* @param expressionString 表达式字符串
* @param context EvaluationContext
* @return 解析结果
*/
private static Object parseExpression(String expressionString, EvaluationContext context) {
Expression expression = parser.parseExpression(expressionString);
return expression.getValue(context);
}

/**
* 解析表达式
*
* @param expressionString 表达式字符串
* @param rootObject 根对象
* @return 解析结果
*/
private static Object parseExpression(String expressionString, Object rootObject) {
Expression expression = parser.parseExpression(expressionString);
return expression.getValue(rootObject);
}

/**
* 判断字符串是否为空
*
* @param str 待判断的字符串
* @return 是否为空
*/
private static boolean isEmpty(String str) {
return str == null || str.trim().isEmpty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package com.nebula.web.common.utils;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.springframework.expression.spel.SpelParseException;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
* @author : wh
* @date : 2024/9/13 16:19
* @description:
*/
public class ExpressionUtilTest {

@Test
void testParseWithMethodAndArgs() throws NoSuchMethodException {
Method method = TestClass.class.getDeclaredMethod("testMethod", String.class, int.class);
Object[] args = {"Hello", 5};

assertEquals("Hello", ExpressionUtil.parse("#param1", method, args));
assertEquals(5, ExpressionUtil.parse("#param2", method, args));
assertEquals("Hello5", ExpressionUtil.parse("#param1 + #param2", method, args));
}

@Test
void testParseWithRootObject() {
TestClass testObj = new TestClass("World", 10);

assertEquals("World", ExpressionUtil.parse("name", testObj));
assertEquals(10, ExpressionUtil.parse("age", testObj));
assertEquals("World is 10 years old", ExpressionUtil.parse("name + ' is ' + age + ' years old'", testObj));
}

@Test
void testParseWithVariables() {
Map<String, Object> variables = new HashMap<>();
variables.put("x", 10);
variables.put("y", 20);

assertEquals(30, ExpressionUtil.parse("#x + #y", variables));
assertEquals(200, ExpressionUtil.parse("#x * #y", variables));
}

@Test
void testIsEl() {
assertTrue(ExpressionUtil.isEl("#expression"));
assertFalse(ExpressionUtil.isEl("normalString"));
assertFalse(ExpressionUtil.isEl(""));
assertFalse(ExpressionUtil.isEl(null));
}

@Test
void testParseWithInvalidExpression() {
assertThrows(SpelParseException.class, () -> ExpressionUtil.parse("invalid#expression", new Object()));
}

@Test
void testParseWithEmptyExpression() {
assertNull(ExpressionUtil.parse("", new Object()));
assertNull(ExpressionUtil.parse(null, new Object()));
}

// 用于测试的内部类
private static class TestClass {
private String name;
private int age;

public TestClass(String name, int age) {
this.name = name;
this.age = age;
}

public void testMethod(String param1, int param2) {
// 方法体为空,仅用于测试
}

// Getters and setters
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

}
Loading