velocity 实现嵌套变量解析

velocity Implementing nested variable resolution

我想通过velocity生成controller层代码。 我生成一个映射方法:

@ResponseBody
@PostMapping(value = "\${peacetrue.${moduleName}.urls.add}")
public ${ModuleName}VO add(${ModuleName}Add params) {
    logger.info("add record[{}]", params);
    return ${moduleName}Service.add(params);
}

然后我遇到异常:

{DomainName}Controller.java.vm[line 18, column 39]
Was expecting one of:
    "[" ...
    "|" ...
    "}" ...
    "}" ...

然后我写了一个单元测试:

    @Test
    public void translate() {
        Velocity.init();

        Map<String, Object> singletonMap = Collections.singletonMap("foo", "bar");
        StringWriter stringWriter = new StringWriter();
        Velocity.evaluate(new VelocityContext(singletonMap), stringWriter, "log", "$foo");
        Assert.assertEquals("bar", stringWriter.toString());
        stringWriter = new StringWriter();
        Velocity.evaluate(new VelocityContext(singletonMap), stringWriter, "log", "\${com.${foo}.name}");
        Assert.assertEquals("${com.bar.name}", stringWriter.toString());
    }

那我该怎么办?

您可以像这样使用 #evaluate() 指令(至少从 v1.7 开始):

@PostMapping("#evaluate("$peacetrue.${moduleName}.urls.add")")

或(对于以前的版本)像这样:

@PostMapping("#set($d='$')#evaluate("${d}peacetrue.${moduleName}.urls.add")")

或者如果 EscapeTool 出现在上下文中:

@PostMapping("#evaluate("${esc.dollar}peacetrue.${moduleName}.urls.add")")

或者如果 $peacetrue 有标准的 getter 模块(像 .getFoo()get('foo') 作为地图):

@PostMapping("$peacetrue.get($moduleName).urls.add")

可以用implementation 'org.apache.velocity.tools:velocity-tools-generic:3.0'

实现
   @Test
    public void translate() {
        VelocityEngine engine = new VelocityEngine();
        engine.init();

        Map<String, Object> singletonMap = Collections.singletonMap("foo", "bar");
        StringWriter stringWriter = new StringWriter();
        Velocity.evaluate(new VelocityContext(singletonMap), stringWriter, "log", "$foo");
        Assert.assertEquals("bar", stringWriter.toString());

        stringWriter = new StringWriter();
        ToolManager manager = new ToolManager(true, true);
        manager.setVelocityEngine(engine);
        manager.configure(getEasyFactoryConfiguration());
        ToolContext context = manager.createContext();
        context.put("foo","bar");
        Velocity.evaluate(context, stringWriter, "log", "${esc.d}{com.${foo}.name}");
        Assert.assertEquals("${com.bar.name}", stringWriter.toString());
    }

    private EasyFactoryConfiguration getEasyFactoryConfiguration() {
        EasyFactoryConfiguration config = new EasyFactoryConfiguration();
        config.toolbox("application").tool(EscapeTool.class);
        return config;
    }