23

我必须从 D/B 中检索一组列值并将其作为条件进行检查。

例如,我将在 D/B 列中有类似"value > 2",的字符串。"4 < value < 6"(值是一直比较的值)。我将在我的代码中声明一个变量值,我应该评估这个条件。

int value = getValue();
if (value > 2)  //(the string retrieved from the D/B)
  doSomething();

我怎样才能做到这一点??任何帮助都非常感谢。谢谢。

4

8 回答 8

35

下面是一个使用标准(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
    }
}
于 2012-06-06T16:09:17.453 回答
1

这不会是微不足道的:您需要一个解析器来解析数据库中使用的表达式语言。如果它是某种标准的、明确指定的语言,那么您可能可以在 Internet 上找到它,但如果它是内部的东西,那么您可能需要编写自己的语言(可能使用像 ANTLR 这样的解析器生成器。)

javax.script包包含一些用于集成外部脚本引擎的工具,例如 Javascript 解释器。另一种想法是引入脚本引擎并将表达式提供给它。

于 2012-06-06T16:05:40.123 回答
1

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)

于 2012-06-06T16:07:01.960 回答
0

为了以最大的灵活性评估条件,请使用为嵌入而设计的脚本语言,例如MVEL可以解析和评估简单的条件表达式,例如问题中的条件表达式。

与在 Java 1.6+ 中使用脚本引擎(特别是使用 JavaScript)相比,使用 MVEL 具有一个巨大的优势:使用 MVEL,您可以将脚本编译为字节码,从而在运行时对它们的评估更加高效。

于 2012-06-06T16:10:11.260 回答
0

这本身并不能回答您的问题;它提供了一种替代解决方案,可能会产生相同的结果。

与其使用定义条件的伪代码存储单个数据库列,不如创建一个表,其中架构定义必须满足的条件类型和这些条件的值。这简化了对这些条件的编程评估,但如果您有多种类型的条件要评估,它可能会变得复杂。

例如,您可能有一个如下所示的表。

CONDITION_ID | MINIMUM | MAXIMUM | IS_PRIME  |   ETC.
______________________________________________________
      1      |    2    |   NULL  |   NULL    |   ...
      2      |    4    |    6    |   NULL    |   ...

这些行条目分别映射到规则value > 26 > value > 4

与您提供的方法相比,这带来了许多好处。

  • 提高性能和清洁度
  • 您的条件可以在数据库级别进行评估,并可用于过滤查询
  • 您不必担心处理伪代码语法被破坏的场景
于 2012-06-06T16:10:55.217 回答
0

您应该尝试通过执行类似的操作来解析 if 语句中的字符串

if(parseMyString(getValue()))
    doSomething();

在 parseMyString 中可以确定您需要为条件评估什么。如果您不知道如何创建解析器,请查看:http ://www.javapractices.com/topic/TopicAction.do?Id=87

于 2012-06-06T16:08:05.213 回答
-1

最新版本的 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();
}
于 2012-06-06T16:07:11.840 回答
-4

除了使用 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 块中以执行条件操作。在上面的代码中,您可以传递任何字符串来代替本示例中传递的内容

于 2012-06-06T17:17:02.200 回答