我必须从 D/B 中检索一组列值并将其作为条件进行检查。
例如,我将在 D/B 列中有类似"value > 2"
,的字符串。"4 < value < 6"
(值是一直比较的值)。我将在我的代码中声明一个变量值,我应该评估这个条件。
int value = getValue();
if (value > 2) //(the string retrieved from the D/B)
doSomething();
我怎样才能做到这一点??任何帮助都非常感谢。谢谢。
下面是一个使用标准(Java 1.6+)脚本库的例子:
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class Test {
public static void main(String[] args) throws Exception {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");
engine.eval("value = 10");
Boolean greaterThan5 = (Boolean) engine.eval("value > 5");
Boolean lessThan5 = (Boolean) engine.eval("value < 5");
System.out.println("10 > 5? " + greaterThan5); // true
System.out.println("10 < 5? " + lessThan5); // false
}
}
这不会是微不足道的:您需要一个解析器来解析数据库中使用的表达式语言。如果它是某种标准的、明确指定的语言,那么您可能可以在 Internet 上找到它,但如果它是内部的东西,那么您可能需要编写自己的语言(可能使用像 ANTLR 这样的解析器生成器。)
javax.script包包含一些用于集成外部脚本引擎的工具,例如 Javascript 解释器。另一种想法是引入脚本引擎并将表达式提供给它。
You are basically evaluating a scripted expression. Depending what is allowed in that expression, you can get away with something very simple (regular expression identifying the groups) or very complex (embed a javascript engine?).
I'm assuming you're looking at the simple case, where the expression is: [boundary0] [operator] "value" [operator] [boundary1]
Where one, but not both of the [boundary] [operator] groups might be omitted. (And if both are presents, operator should be the same)
I would use a regular expression for that with capturing groups.
Something like: (?:(\d+)\s*([<>])\s*)?value(?:\s*([<>])\s*(\d+))?
And then: boundary1 = group(1); operator1 = group(2); operator2 = group(3); boundary2 = group(4)
为了以最大的灵活性评估条件,请使用为嵌入而设计的脚本语言,例如MVEL可以解析和评估简单的条件表达式,例如问题中的条件表达式。
与在 Java 1.6+ 中使用脚本引擎(特别是使用 JavaScript)相比,使用 MVEL 具有一个巨大的优势:使用 MVEL,您可以将脚本编译为字节码,从而在运行时对它们的评估更加高效。
这本身并不能回答您的问题;它提供了一种替代解决方案,可能会产生相同的结果。
与其使用定义条件的伪代码存储单个数据库列,不如创建一个表,其中架构定义必须满足的条件类型和这些条件的值。这简化了对这些条件的编程评估,但如果您有多种类型的条件要评估,它可能会变得复杂。
例如,您可能有一个如下所示的表。
CONDITION_ID | MINIMUM | MAXIMUM | IS_PRIME | ETC.
______________________________________________________
1 | 2 | NULL | NULL | ...
2 | 4 | 6 | NULL | ...
这些行条目分别映射到规则value > 2
和6 > value > 4
。
与您提供的方法相比,这带来了许多好处。
您应该尝试通过执行类似的操作来解析 if 语句中的字符串
if(parseMyString(getValue()))
doSomething();
在 parseMyString 中可以确定您需要为条件评估什么。如果您不知道如何创建解析器,请查看:http ://www.javapractices.com/topic/TopicAction.do?Id=87
最新版本的 java (Java 7) 允许在字符串上使用 Switch Case 语句,如果没有太多可能的变化,您可以这样做或类似:
int value = getValue();
switch(myString) {
case "value > 2" : if (value > 2) { doSomething();} break;
case "4 < value < 6" : if (value > 4 && value < 6) { doSomethingElse();} break;
default : doDefault();
}
除了使用 Java 7 之外,一个非常好的方法是使用枚举。如下所示声明枚举
上面的枚举有一个常量集合,其值设置为您期望从数据库返回的字符串。由于您可以在 switch case 中使用枚举,因此其余代码变得简单
enum MyEnum
{
val1("value < 4"),val2("4<value<6");
private String value;
private MyEnum(String value)
{
this.value = value;
}
}
public static void chooseStrategy(MyEnum enumVal)
{
int value = getValue();
switch(enumVal)
{
case val1:
if(value > 2){}
break;
case val2:
if(4 < value && value < 6) {}
break;
default:
}
}
public static void main(String[] args)
{
String str = "4<value<6";
chooseStrategy(MyEnum.valueOf(str));
}
您所要做的就是将您的字符串传递给 enum.valueof 方法,它将返回适当的枚举,该枚举被放入 switch case 块中以执行条件操作。在上面的代码中,您可以传递任何字符串来代替本示例中传递的内容