How to access an object's public fields from a Velocity template

橙三吉。 提交于 2019-11-29 13:25:43

Not by default. You need to configure a different Uberspect implementation.

The Velocity user guide suggests it's not possible. Quote:

[Velocity] tries out different alternatives based on several established naming conventions. The exact lookup sequence depends on whether or not the property name starts with an upper-case letter. For lower-case names, such as $customer.address, the sequence is

  1. getaddress()
  2. getAddress()
  3. get("address")
  4. isAddress()

For upper-case property names like $customer.Address, it is slightly different:

  1. getAddress()
  2. getaddress()
  3. get("Address")
  4. isAddress()
Vadzim

http://wiki.apache.org/velocity/VelocityFAQ:

Q: How can i access my object's public fields in my templates?

A: Currently, you have three options:

  • Wrap your object with a FieldMethodizer

  • Configure your VelocityEngine to use a custom uberspector like the PublicFieldUberspect

  • Lobby the velocity-dev list to add public field introspection as a default fallback if no matching method is found :)

FieldMethodizer works only with public static fields.

PublicFieldUberspect example code is quite old and it just fails with error on nonexistent fields.

And forget about lobby at dev list. )


Meanwhile, there is good caching implementation of UberspectPublicFields in current velocity trunk. Unfortunately, there was no active development for years and no plans for next release are published. One would have to build it himself and bundle in private repository.


Another altervative is a fork with bonus scala compatibility that is available in central maven repository: http://maven-repository.com/artifact/com.sksamuel.scalocity/scalocity/0.9.

Drop in instead of usual velocity dependency:

<dependency>
  <groupId>com.sksamuel.scalocity</groupId>
  <artifactId>scalocity</artifactId>
  <version>0.9</version>
</dependency>

Then just add to velocity.properties:

runtime.introspector.uberspect = org.apache.velocity.util.introspection.UberspectPublicFields, org.apache.velocity.util.introspection.UberspectImpl

The caveat is that UberspectImpl is patched with additional support for scala properties and requires 8 MB scala jar.


Eventually, I just interned the following classes from velocity trunk into own project:

org.apache.velocity.runtime.parser.node.PublicFieldExecutor org.apache.velocity.runtime.parser.node.SetPublicFieldExecutor org.apache.velocity.util.introspection.ClassFieldMap org.apache.velocity.util.introspection.Introspector org.apache.velocity.util.introspection.IntrospectorBase org.apache.velocity.util.introspection.IntrospectorCache org.apache.velocity.util.introspection.IntrospectorCacheImpl org.apache.velocity.util.introspection.UberspectPublicFields

These work fine with Velocity 1.7.

i do

import org.apache.velocity.util.introspection.UberspectImpl;
import org.apache.velocity.util.introspection.UberspectPublicFields;

....

properties.setProperty("runtime.introspector.uberspect",
  UberspectImpl.class.getName() + ", " +
  UberspectPublicFields.class.getName());

And all works OK!!!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!