代码之家  ›  专栏  ›  技术社区  ›  matt b

如何访问Velocity模板中的静态成员?

  •  11
  • matt b  · 技术社区  · 16 年前

    我不确定是否有办法在Velocity中做到这一点:

    我有一个用户POJO,它有一个名为Status的属性,看起来像一个枚举(但它不是,因为我被困在Java 1.4上),定义看起来像这样:

    public class User  {
    
        // default status to User
        private Status status = Status.USER;
    
        public void setStatus(Status status) {
            this.status = status;
        }
    
        public Status getStatus() {
            return status;
        }
    

    Status是一个静态内部类:

    public static final class Status {
    
        private String statusString;
    
        private Status(String statusString) {
            this.statusString = statusString;
        }
    
        public final static Status USER = new Status("user");
        public final static Status ADMIN = new Status("admin");
        public final static Status STATUS_X = new Status("blah");
    
        //.equals() and .hashCode() implemented as well
    }
    

    通过这种模式,可以很容易地在条件中测试用户状态,例如

    if(User.Status.ADMIN.equals(user.getStatus())) ...
    

    …而无需引用状态ID的任何常量、任何幻数等。

    但是,我无法弄清楚如何使用VTL在Velocity模板中测试这些条件。我只想根据用户的状态打印一个简单的字符串,例如:

    Welcome <b>${user.name}</b>!
    <br/>
    <br/>
    
    #if($user.status == com.company.blah.User.Status.USER)
        You are a regular user
    #elseif($user.status == com.company.blah.User.Status.ADMIN)
        You are an administrator
    #etc...
    
    #end
    

    但这会抛出一个异常,看起来像 org.apache.velocity.exception.ParseErrorException: Encountered "User" at webpages/include/dashboard.inc[line 10, column 21] Was expecting one of: "[" ...

    来自 the VTL User Guide ,VTL中没有提到直接访问Java类/静态成员,条件的右侧(RHS)似乎只能是数字文字、字符串文字、属性引用或方法引用。

    那么,有什么方法可以访问Velocity模板中的静态Java属性/引用吗?我知道作为一种解决方法,我可以将状态ID或其他标识符作为引用嵌入到我的控制器中(这是一个使用Velocity作为视图技术的web MVC应用程序),但我强烈不想在视图层中嵌入任何神奇的数字或常数。

    3 回复  |  直到 16 年前
        1
  •  8
  •   matt b    16 年前

    我想出了一个解决方法,可以添加每个 User.Status 对象指向Velocity上下文,这避免了对模板中常量或幻数的任何引用。

    在控制器/Java端:

    // put the statuses directly into the model
    Map statusMap = new HashMap();
    statusMap.put("user", User.Status.USER);
    statusMap.put("groupOperator", User.Status.ADMIN);
    ...
    modelAndView.addObject("statusmap", statusMap);
    

    然后在模板中,这些值可以这样引用:

    #if($user.status == $statusmap.user)
       You are a regular user
    #elseif($user.status == $statusmap.admin)
        You are an administrator
    ##etc...
    #end
    
        2
  •  6
  •   Nathan Bubna    16 年前

    是的,Velocity本身并不探索类和包。你可以做你所做的,或者使用FieldMethodizer类来实现自动化。另一种选择是VelocityTools 2.0中的FieldTool。

        3
  •  3
  •   rresino    15 年前

    尝试使用Velocity的FieldMethodizer,这不是最好的解决方案,但你可以做点什么。

    使用此类,您可以调用静态公共常量,请参阅链接:

    FieldMethodizer API