使用“BeanUtils alike”替换的最简单方法
Posted
技术标签:
【中文标题】使用“BeanUtils alike”替换的最简单方法【英文标题】:Simplest way to use "BeanUtils alike" replace 【发布时间】:2010-09-13 18:56:13 【问题描述】:是否有任何库可以让我使用与 BeanUtils 中相同的已知符号来提取 POJO 参数,但可以轻松替换字符串中的占位符?
我知道使用 BeanUtils 本身或具有类似功能的其他库可以自行开发,但我不想重新发明***。
我想取一个字符串如下:
String s = "User $user.name just placed an order. Deliver is to be
made to $user.address.street, $user.address.number - $user.address.city /
$user.address.state";
并在下面传递一个 User 类的实例:
public class User
private String name;
private Address address;
// (...)
public String getName() return name;
public Address getAddress() return address;
public class Address
private String street;
private int number;
private String city;
private String state;
public String getStreet() return street;
public int getNumber() return number;
// other getters...
类似于:
System.out.println(BeanUtilsReplacer.replaceString(s, user));
将每个占位符替换为实际值。
有什么想法吗?
【问题讨论】:
查看关于using Expression Language in a standalone context的类似问题的答案。 【参考方案1】:使用 BeanUtils 滚动您自己不会花费太多的***改造(假设您希望它像要求的那样基本)。此实现采用 Map 替换上下文,其中映射键应对应于为替换给出的变量查找路径的第一部分。
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.beanutils.BeanUtils;
public class BeanUtilsReplacer
private static Pattern lookupPattern = Pattern.compile("\\$\\([^\\]+)\\");
public static String replaceString(String input, Map<String, Object> context)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
int position = 0;
StringBuffer result = new StringBuffer();
Matcher m = lookupPattern.matcher(input);
while (m.find())
result.append(input.substring(position, m.start()));
result.append(BeanUtils.getNestedProperty(context, m.group(1)));
position = m.end();
if (position == 0)
return input;
else
result.append(input.substring(position));
return result.toString();
鉴于您的问题中提供的变量:
Map<String, Object> context = new HashMap<String, Object>();
context.put("user", user);
System.out.println(BeanUtilsReplacer.replaceString(s, context));
【讨论】:
【参考方案2】:Spring Framework 应该具有执行此操作的功能(请参阅下面的 Spring JDBC 示例)。如果您可以使用 groovy(只需添加 groovy.jar 文件),您可以使用 Groovy 的 GString 功能很好地做到这一点。
Groovy 示例
foxtype = 'quick'
foxcolor = ['b', 'r', 'o', 'w', 'n']
println "The $foxtype $foxcolor.join() fox"
Spring JDBC 有一个特性,我用它来支持来自 bean 的命名和嵌套命名绑定变量,如下所示:
public int countOfActors(Actor exampleActor)
// notice how the named parameters match the properties of the above 'Actor' class
String sql = "select count(0) from T_ACTOR where first_name = :firstName and last_name = :lastName";
SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(exampleActor);
return this.namedParameterJdbcTemplate.queryForInt(sql, namedParameters);
【讨论】:
【参考方案3】:您的字符串示例是至少在一些模板引擎中的有效模板,例如 Velocity 或 Freemarker。这些库提供了一种将模板与包含一些对象的上下文合并的方法(例如您的示例中的“用户”)。
见http://velocity.apache.org/ 或http://www.freemarker.org/
一些示例代码(来自 Freemarker 网站):
/* ------------------------------------------------------------------- */
/* You usually do it only once in the whole application life-cycle: */
/* Create and adjust the configuration */
Configuration cfg = new Configuration();
cfg.setDirectoryForTemplateLoading(
new File("/where/you/store/templates"));
cfg.setObjectWrapper(new DefaultObjectWrapper());
/* ------------------------------------------------------------------- */
/* You usually do these for many times in the application life-cycle: */
/* Get or create a template */
Template temp = cfg.getTemplate("test.ftl");
/* Create a data-model */
Map root = new HashMap();
root.put("user", "Big Joe");
Map latest = new HashMap();
root.put("latestProduct", latest);
latest.put("url", "products/greenmouse.html");
latest.put("name", "green mouse");
/* Merge data-model with template */
Writer out = new OutputStreamWriter(System.out);
temp.process(root, out);
out.flush();
【讨论】:
以上是关于使用“BeanUtils alike”替换的最简单方法的主要内容,如果未能解决你的问题,请参考以下文章
在 Swift 中设置自定义 NavigationBar 的最简单方法是啥?
在 Vim 中,将文件中的所有行合并为一行的最简单方法是啥?