PebbleTemplates 自定义tag&filter&function 开发简单说明
PebbleTemplates 的扩展能力还是很强大的,开发起来也比较方便,以下是一个简单的说明,更加复杂的推荐查看官方源码学习
filter 开发
- 参考代码
此filter 直接返回rongfengliang
public class LoginFilter implements Filter {
public LoginFilter() {
}
@Override
public Object apply(Object input, Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber) throws PebbleException {
return "rongfengliang";
}
@Override
public List<String> getArgumentNames() {
return null;
}
}
function 开发
- 参考代码
一个输入参数返回
public class MyFunction implements Function {
private final List<String> argumentNames = new ArrayList<>();
public MyFunction() {
this.argumentNames.add("name");
}
@Override
public Object execute(Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber) {
String name = (String) args.get("name");
return name;
}
@Override
public List<String> getArgumentNames() {
return this.argumentNames;
}
}
tag 开发
tag 相对比较复杂,包含了tag 解析树,tag node 处理,tag node 对应业务处理,以下是一个简单的include包装,代码部分服用了现有include 的处理
- 参考代码
token 处理,对应tag 名称为rongfengliang
public class MyTokenParser implements TokenParser {
@Override
public String getTag() {
return "rongfengliang";
}
@Override
public RenderableNode parse(Token token, Parser parser) {
TokenStream stream = parser.getStream();
int lineNumber = token.getLineNumber();
// skip over the 'include' token
stream.next();
Expression<?> includeExpression = parser.getExpressionParser().parseExpression();
stream.expect(Token.Type.EXECUTE_END);
return new MyIncludeNode(lineNumber, includeExpression);
}
}
MyIncludeNode node 处理
public class MyIncludeNode extends AbstractRenderableNode {
private final Expression<?> includeExpression;
public MyIncludeNode(int lineNumber, Expression<?> includeExpression) {
super(lineNumber);
this.includeExpression = includeExpression;
}
@Override
public void render(PebbleTemplateImpl self, Writer writer, EvaluationContextImpl context)
throws IOException {
String templateName = (String) this.includeExpression.evaluate(self, context);
Map<?, ?> map = Collections.emptyMap();
if (templateName == null) {
throw new PebbleException(
null,
"The template name in an include tag evaluated to NULL. If the template name is static, make sure to wrap it in quotes.",
this.getLineNumber(), self.getName());
}
// 此处代码复用了include 部分的,需要进行include 模版的处理
self.includeTemplate(writer, context, templateName, map);
}
@Override
public void accept(NodeVisitor visitor) {
visitor.visit(this);
}
public Expression<?> getIncludeExpression() {
return this.includeExpression;
}
}
扩展开发
PebbleTemplates 提供了一个方便的扩展点,可以方便进行扩展的注册,实现AbstractExtension 就可以了
- 参考代码
public class MyExtension extends AbstractExtension {
@Override
public Map<String, Filter> getFilters() {
Map<String, Filter> filters = new HashMap<>();
filters.put("rongfengliang",new LoginFilter());
return filters;
}
@Override
public List<TokenParser> getTokenParsers() {
List<TokenParser> parsers = new ArrayList<>();
parsers.add(new MyTokenParser());
return parsers;
}
@Override
public Map<String, Function> getFunctions() {
Map<String, Function> functionMap = new HashMap<>();
functionMap.put("rongfengliang",new MyFunction());
return functionMap;
}
}
注册扩展
PebbleTemplates 提供了比较方便的扩展注册方法,很简洁
- 参考代码
MinioClient minioClient =
MinioClient.builder()
.endpoint("http://127.0.0.1:9000")
.credentials("minio", "minio123")
.build();
DelegatingLoader delegatingLoader = new DelegatingLoader(Arrays.asList(new S3Loader(minioClient,"demoapp")));
// 初始化PebbleEngine, 并进行扩展的注册
PebbleEngine engine = new PebbleEngine.Builder().loader(delegatingLoader).extension(new MyExtension()).build();
PebbleTemplate compiledTemplate = engine.getTemplate("home.html");
Map<String, Object> context = new HashMap<>();
context.put("name", "Mitchell");
Writer writer = new StringWriter();
compiledTemplate.evaluate(writer, context);
String output = writer.toString();
System.out.println(output);
使用
- 参考模版
// rongfengliang tag 使用
{% rongfengliang "100/footer.html" %}
// rongfengliang 函数使用
this is demo {{ rongfengliang('dalongdemoapp') }}
// filter 使用
<div> {{ "demoapp" | rongfengliang }} <div>
说明
以上代码都放GitHub 上了,具体可以参考github ,PebbleTemplate实现提供的一些能力参考如下类图
参考资料
https://github.com/PebbleTemplates/pebble
https://pebbletemplates.io/
https://github.com/rongfengliang/pebbletemplates-learning.git