如何在freemarker模板中调用反射方法?

Posted

技术标签:

【中文标题】如何在freemarker模板中调用反射方法?【英文标题】:How to call reflection methods in freemarker template? 【发布时间】:2018-07-30 00:12:38 【问题描述】:

我们可以在java中使用类似这样的代码来遍历类字段、注解:

Class<?> clazz;
for(Field field : clazz.getDeclaredFields()) 
    for(Annotation annotation : field.getDeclaredAnnotations()) 
        for(Method method : annotation.annotationType().getMethods()) 
            if(method.getName().equals("nullable")) 
                try 
                    // note this line
                    System.out.println(method.invoke(annotation, (Object[])null) );
                
                catch(Exception e) 
                    System.out.println("Ex");
                
            
        
    

上面的代码想要检查字段的注释之一是否有nullable 方法,记录它的值。假设这个字段是某个类:

public class someClass 
    @Column(nullable = false)
    private Long number;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "entity_id", nullable = true)
    private Entity entity;

该类的上述代码记录false,然后将true 记录为字段注释中nullable 属性的值。现在我想遍历freemarker模板中的类字段和注释,但问题是我不能调用method.invoke(annotation, (Object[])null)

<#list fields as field>
    <#list field.annotations as annotation>
        <#if annotation??>
            <#if annotation.annotationType().getSimpleName() == "Column" || annotation.annotationType().getSimpleName() == "JoinColumn">
                <#list annotation.annotationType().getMethods() as annotationMethod>
                    <#attempt>
                        <#if annotationMethod.getName() == "nullable">
                            // this line get error 
                            $annotationMethod.invoke(annotation, (Object[])null)
                        </#if>
                        <#recover>
                    </#attempt>
                </#list>
                <#break>
            </#if>
        </#if>
    </#list>
</#list>

在 freemarker 模板中是否有另一种方法可以实现这一目标? 我想将这些代码用于代码生成器。

UDPATE

这是我给出的例外:

Syntax error in template "entity-detail.ftl" in line 32, column 111:
Encountered "]", but was expecting one of:
    <STRING_LITERAL>
    <RAW_STRING>
    "false"
    "true"
    <INTEGER>
    <DECIMAL>
    "."
    "+"
    "-"
    "!"
    "["
    "("
    ""
    <ID>
freemarker.core.ParseException: Syntax error in template "entity-detail.ftl" in line 32, column 111:
Encountered "]", but was expecting one of:
    <STRING_LITERAL>
    <RAW_STRING>
    "false"
    "true"
    <INTEGER>
    <DECIMAL>
    "."
    "+"
    "-"
    "!"
    "["
    "("
    ""
    <ID>
    at freemarker.core.FMParser.generateParseException(FMParser.java:5749)
    at freemarker.core.FMParser.jj_consume_token(FMParser.java:5608)
    at freemarker.core.FMParser.UnaryExpression(FMParser.java:658)
    at freemarker.core.FMParser.MultiplicativeExpression(FMParser.java:768)
    at freemarker.core.FMParser.AdditiveExpression(FMParser.java:720)
    at freemarker.core.FMParser.RangeExpression(FMParser.java:900)
    at freemarker.core.FMParser.RelationalExpression(FMParser.java:848)
    at freemarker.core.FMParser.EqualityExpression(FMParser.java:811)
    at freemarker.core.FMParser.AndExpression(FMParser.java:967)
    at freemarker.core.FMParser.OrExpression(FMParser.java:989)
    at freemarker.core.FMParser.Expression(FMParser.java:548)
    at freemarker.core.FMParser.DynamicKey(FMParser.java:1341)
    at freemarker.core.FMParser.AddSubExpression(FMParser.java:1107)
    at freemarker.core.FMParser.PrimaryExpression(FMParser.java:607)
    at freemarker.core.FMParser.UnaryExpression(FMParser.java:653)
    at freemarker.core.FMParser.MultiplicativeExpression(FMParser.java:768)
    at freemarker.core.FMParser.AdditiveExpression(FMParser.java:720)
    at freemarker.core.FMParser.RangeExpression(FMParser.java:900)
    at freemarker.core.FMParser.RelationalExpression(FMParser.java:848)
    at freemarker.core.FMParser.EqualityExpression(FMParser.java:811)
    at freemarker.core.FMParser.AndExpression(FMParser.java:967)
    at freemarker.core.FMParser.OrExpression(FMParser.java:989)
    at freemarker.core.FMParser.Expression(FMParser.java:548)
    at freemarker.core.FMParser.Parenthesis(FMParser.java:616)
    at freemarker.core.FMParser.PrimaryExpression(FMParser.java:588)
    at freemarker.core.FMParser.UnaryExpression(FMParser.java:653)
    at freemarker.core.FMParser.MultiplicativeExpression(FMParser.java:768)
    at freemarker.core.FMParser.AdditiveExpression(FMParser.java:720)
    at freemarker.core.FMParser.RangeExpression(FMParser.java:900)
    at freemarker.core.FMParser.RelationalExpression(FMParser.java:848)
    at freemarker.core.FMParser.EqualityExpression(FMParser.java:811)
    at freemarker.core.FMParser.AndExpression(FMParser.java:967)
    at freemarker.core.FMParser.OrExpression(FMParser.java:989)
    at freemarker.core.FMParser.Expression(FMParser.java:548)
    at freemarker.core.FMParser.PositionalArgs(FMParser.java:2985)
    at freemarker.core.FMParser.MethodArgs(FMParser.java:1357)
    at freemarker.core.FMParser.AddSubExpression(FMParser.java:1111)
    at freemarker.core.FMParser.PrimaryExpression(FMParser.java:607)
    at freemarker.core.FMParser.UnaryExpression(FMParser.java:653)
    at freemarker.core.FMParser.MultiplicativeExpression(FMParser.java:768)
    at freemarker.core.FMParser.AdditiveExpression(FMParser.java:720)
    at freemarker.core.FMParser.RangeExpression(FMParser.java:900)
    at freemarker.core.FMParser.RelationalExpression(FMParser.java:848)
    at freemarker.core.FMParser.EqualityExpression(FMParser.java:811)
    at freemarker.core.FMParser.AndExpression(FMParser.java:967)
    at freemarker.core.FMParser.OrExpression(FMParser.java:989)
    at freemarker.core.FMParser.Expression(FMParser.java:548)
    at freemarker.core.FMParser.StringOutput(FMParser.java:1522)
    at freemarker.core.FMParser.MixedContentElements(FMParser.java:3721)
    at freemarker.core.FMParser.If(FMParser.java:1625)
    at freemarker.core.FMParser.FreemarkerDirective(FMParser.java:3384)
    at freemarker.core.FMParser.MixedContentElements(FMParser.java:3772)
    at freemarker.core.FMParser.Attempt(FMParser.java:1671)
    at freemarker.core.FMParser.FreemarkerDirective(FMParser.java:3511)
    at freemarker.core.FMParser.MixedContentElements(FMParser.java:3772)
    at freemarker.core.FMParser.List(FMParser.java:1746)
    at freemarker.core.FMParser.FreemarkerDirective(FMParser.java:3388)
    at freemarker.core.FMParser.MixedContentElements(FMParser.java:3772)
    at freemarker.core.FMParser.If(FMParser.java:1625)
    at freemarker.core.FMParser.FreemarkerDirective(FMParser.java:3384)
    at freemarker.core.FMParser.MixedContentElements(FMParser.java:3772)
    at freemarker.core.FMParser.If(FMParser.java:1625)
    at freemarker.core.FMParser.FreemarkerDirective(FMParser.java:3384)
    at freemarker.core.FMParser.MixedContentElements(FMParser.java:3772)
    at freemarker.core.FMParser.List(FMParser.java:1746)
    at freemarker.core.FMParser.FreemarkerDirective(FMParser.java:3388)
    at freemarker.core.FMParser.MixedContentElements(FMParser.java:3772)
    at freemarker.core.FMParser.Attempt(FMParser.java:1671)
    at freemarker.core.FMParser.FreemarkerDirective(FMParser.java:3511)
    at freemarker.core.FMParser.MixedContentElements(FMParser.java:3772)
    at freemarker.core.FMParser.List(FMParser.java:1746)
    at freemarker.core.FMParser.FreemarkerDirective(FMParser.java:3388)
    at freemarker.core.FMParser.MixedContentElements(FMParser.java:3772)
    at freemarker.core.FMParser.Root(FMParser.java:4411)
    at freemarker.template.Template.<init>(Template.java:252)
    at freemarker.cache.TemplateCache.loadTemplate(TemplateCache.java:549)
    at freemarker.cache.TemplateCache.getTemplateInternal(TemplateCache.java:439)
    at freemarker.cache.TemplateCache.getTemplate(TemplateCache.java:292)
    at freemarker.template.Configuration.getTemplate(Configuration.java:2654)
    at freemarker.template.Configuration.getTemplate(Configuration.java:2503)
    at com.vira.framework.common.generator.CodeGenerator.generate(CodeGenerator.java:70)
    at com.vira.framework.common.generator.CodeGeneratorTest.main(CodeGeneratorTest.java:7)

【问题讨论】:

为什么不能准确地调用它?错误信息是什么? 亲爱的@ddekany,请检查我的更新 啊...模板语言中没有强制转换或类型名称。 (也不是null...虽然如果没有定义一个这样的变量,它会在这种情况下工作。)无论如何,这是一个可变参数,那么annotationMethod.invoke(annotation)呢? 不,annotationMethod.invoke(annotation) 不能被调用,因为正如你在java代码中看到的,它必须作为输入参数 您还想在方法调用后添加!,否则如果返回null,FreeMarker 会报错。喜欢$method.invoke(annotation)! 【参考方案1】:

如果您只是从注释中获得“可空”值。您不需要此代码

       <#list annotation.annotationType().getMethods() as annotationMethod>
                <#attempt>
                    <#if annotationMethod.getName() == "nullable">
                        // this line get error 
                        $annotationMethod.invoke(annotation, (Object[])null)
                    </#if>
                    <#recover>
                </#attempt>
            </#list>

就写这个吧!!

$annotation.nullable()

【讨论】:

哈哈,hamin khial bash :D,它对我不起作用,我用另一种方式解决了问题 我使用了这段代码,它工作正常。你能解释一下这段代码不适合你吗??

以上是关于如何在freemarker模板中调用反射方法?的主要内容,如果未能解决你的问题,请参考以下文章

FreeMarker里如何调用java代码?

FreeMarker里如何调用java代码?

在 freemarker 模板中处理 struts2 标签

javaEE开发中如何在freemarker模板里使用httpservletrequest的属性

FreeMarker学习

Freemarker 模板加载