2010-03-30 37 views
4

我有一类的属性和getter方法:格式化在Java中使用类的字符串的属性

public Class MyClass 
{ 
    private String myValue = "foo"; 

    public String getMyValue(); 
} 

我想能够使用foo的值在一个格式化的字符串作为这样:

String someString = "Your value is {myValue}." 
String result = Formatter.format(someString, new MyClass()); 
// result is now "Your value is foo." 

也就是说,我想有一些像.format这样的函数,它使用一个格式字符串指定某个对象的属性,以及一个具有这些属性的实例,并相应地设置字符串的格式。

是否有可能在Java中完成这项壮举?

回答

3

你可以使用JUEL这个。它是Java表达式语言的一个实现。代码是相当紧凑,看起来像这样:

ExpressionFactory factory = new ExpressionFactoryImpl(); 

// create a context and add a Person object to the context, this variable will be used 
// in the property replacement 
// objects of type Person have two fields: firstName and lastName 

SimpleContext context = new SimpleContext(); 
Person person = new Person("John", "Doe"); 
context.setVariable("person", factory.createValueExpression(person, Person.class)); 

// create the expression 

String expr = "My name is ${person.firstName} ${person.lastName}"; 
ValueExpression e = factory.createValueExpression(context, expr, String.class); 

// evaluate the expression 
System.out.println(e.getValue(context)); 

它打印“我的名字是约翰·多伊”

注意,它也可以使用像这样的表达:“$ {FirstName}您好”,而不是'$ {person.firstName}',但那么你将不得不编写并提供一个自定义解析器(javax.el.E​​LResolver)的变量和财产分辨率

+0

幸运会有它,我们已经在我们的依赖树中有JUEL,所以它就是JUEL。谢谢! – 2010-03-31 20:37:13

0

理论上可以使用基于栈的解析器来确定字符串中的值持有者,并结合使用reflection(或更好的,Javabean检查API,如Commons BeanUtils)来获取bean属性值。

不幸的是,现在还没有现成的第三方API,如果你正在寻找的话。然而,这是一个有趣的问题。

0

您可以创建一个与Struts2的/ XWork的/ OGNL,类似于以下(从an email from Vlad复制)

public static String translateOgnl(String message, Map<Object, Object> args) { 
    OgnlValueStack stack = new OgnlValueStack(); 
    stack.push(args); 
    return TextParseUtil.translateVariables(message, stack); 
} 

TextParseUtil.translateVariables()的javadoc说

的$ {所有实例转换.. 。}表达为对ValueStack.findValue(java.lang.String)的调用返回的值。如果在堆栈中找不到项目(返回null),则不会显示整个变量$ {...},就像该项目位于堆栈上但返回空字符串一样。

2

(我的其他答案可能只有当你已经有用使用支柱。)

与sdb的答案类似,我有s apache JEXL

UnifiedJEXL类提供类似模板的功能,所以你可以写(as shown in javadocs):

JexlEngine jexl = new JexlEngine(); 
UnifiedJEXL ujexl = new UnifiedJEXL(jexl); 
UnifiedJEXL.Expression expr = ujexl.parse("Hello ${user}"); 
String hello = expr.evaluate(context, expr).toString(); 

(该expr不仅长相奇特被作为参数传递给在它自己的方法,但确实不需要作为一个参数)

的上下文设置在同一页前面所示:

// Create a context and add data 
JexlContext jc = new MapContext(); 
jc.set("foo", new Foo()); 

ÿ你还需要commons-logging,或者你可以配置JEXL来使用你自己的记录器。


所以要亲近你问什么,你可以创建:

public class Formatter { 
    public static String format(String format, Object ... inputs) { 
     JexlContext context = new MapContext(); 
     for (int i=0;i<inputs.length;i++) { 
      context.set("_" + (i+1), inputs[i]); 
     } 
     JexlEngine jexl = new JexlEngine(); 
     UnifiedJEXL ujexl = new UnifiedJEXL(jexl); 
     UnifiedJEXL.Expression expr = ujexl.parse(format); 
     return expr.evaluate(context).toString(); 
    } 
} 

String someString = "Your value is ${_1.myValue}."; 
String result = Formatter.format(someString, new MyClass()); 

在这一点称呼它,result"Your value is foo."