如果无法找到绑定,如何使JinJava抛出错误

时间:2017-07-09 12:07:39

标签: java jinjava

我需要使用JinJava来处理可以包含不同标记的小模板。例如:

Hello,{{ user }}...

其中需要绑定user,因为没有它,输出就没有任何意义。

我的类不知道令牌模板使用了什么,它从远程服务获取绑定列表。

因此,可能存在模板中指定的绑定不存在的情况。 JinJava的默认行为是使用在输出字符串中转换为空字符串的null。它在我的情况下不起作用,如果错过任何绑定,我需要抛出异常。

我目前的解决方案是使用自定义Filter

/**
* A filter for JinJava that verifies that a value is not null and if the value is null, writes a fatal error to interpreter's log
*/
public class RequiredFilter implements Filter {
    @Override
    public Object filter(Object var, JinjavaInterpreter interpreter, String... args) {
        if (var == null) {
            interpreter.addError(new TemplateError(TemplateError.ErrorType.FATAL, TemplateError.ErrorReason.MISSING, "Value of a required key is null", "", 1, null));
        }
        return var;
    }

    @Override
    public String getName() {
        return "required";
    }
}

让客户端为模板中的所有令牌显式指定此函数。上面的示例现在看起来像:

Hello, {{ user|required }}...

如果绑定user不存在,我会得到异常。但是,自定义函数的要求看起来很奇怪。

有没有办法设置JinJava来实现类似的行为,并且每次都需要指定过滤器required而不打扰客户?

2 个答案:

答案 0 :(得分:1)

基于带有令牌过滤器的解决方案,我为此目的注册了自定义标签。

//my-template.phtml

<?php 
use MyNamespace\Block\CustomBlocks

/** @var CustomBlocks $block */

class OneRandomClass {

}
?>

输出:

public static String fillTemplateTagsWithProperties(
        String template, Map<String, String> properties) throws IllegalArgumentException
{
    if (template == null) throw new IllegalArgumentException("template is null");

    Jinjava jinjava = new Jinjava();
    properties.forEach((k, v) -> jinjava.getGlobalContext().registerTag(new Tag() {
        @Override
        public String interpret(TagNode tagNode, JinjavaInterpreter interpreter) {
            if (v == null) {
                interpreter.addError(new TemplateError(
                        TemplateError.ErrorType.FATAL,
                        TemplateError.ErrorReason.MISSING,
                        "Value of a required key is null",
                        k, 1, null));
            }
            return v;
        }
        @Override
        public String getEndTagName() {
            return null;
        }
        @Override
        public String getName() {
            return k;
        }
    }));
    RenderResult renderResult = jinjava.renderForResult(template, properties);
    if (renderResult.getErrors().size() == 0) {
        return renderResult.getOutput();
    } else {
        throw new IllegalArgumentException(renderResult.getErrors().stream()
                .map(Object::toString)
                .collect(Collectors.joining(",")));
    }
}

@Test
public void jinjavaWithCustomTags(){
    String template = "Hallo {% hallo %}\n" +
            "I am {% unrendered %}";

    Map<String, String> props = new HashMap<>();
    props.put("hallo", "Welt");
    //props.put("unrendered", "[try null here]");

    System.out.println(fillTemplateTagsWithProperties(template, props));

}

或抛出:

Hallo Welt
I am [try null here]

答案 1 :(得分:1)

你可以这样做,

JinjavaConfig jc = JinjavaConfig.newBuilder().withFailOnUnknownTokens(true).build();
Jinjava jinjava = new Jinjava(jc);

// set context and other processes and then render
RenderResult renderResult = jinjava.renderForResult(template, properties);
if (renderResult.getErrors().isEmpty()) {
    return renderResult.getOutput();
} else {
    throw new IllegalArgumentException(renderResult.getErrors().stream()
            .map(Object::toString)
            .collect(Collectors.joining(",")));
}

您可能还想检查许多其他 JinjavaConfig