编写velocity tool
Those of you who write your own custom tools may want to make a few changes to upgrade your custom tools to do things the "Tools 2 way". Here's a few quick starts for that, though this doesn't cover everything. More details can be found in the instructions for creating tools.
?
Naming: The recommended practice is to give a tool to be used as $foo
the name FooTool
. This is not required but is a convention that keeps things easy follow and learn. If you have to name a tool FooBarUtility but want it to be $foo
in templates, the second best thing is to provide a @DefaultKey("foo") annotation on the class, though this introduces a dependency on VelocityTools. As a last resort, if you are providing tools for a framework or otherwise can influence or control the configuration, you might consider providing a default configuration--perhaps even one automatically discoverable by ConfigurationUtils --to set the tool's key for your users.
Scoping: If your tool is only meant to be used in a particular scope, it's recommended that you give the class a @ValidScope(Scope.REQUEST) annotation as well. If you only want to ban a particular scope and allow all others, you could provide a @InvalidScope(Scope.APPLICATION) annotation on the class. The Scope
class provides constants for REQUEST, SESSION, and APPLICATION. Other scopes are now theoretically possible, but only a little work and no testing has been done there at this point.
Configuration: If you have a configurable tool whose configuration should not changed by the templates which use it, then consider having your tool extend the SafeConfig class (or FormatConfig or LocaleConfig ). These safely standardize configuration of these common configuration properties. Also take note that the configure(Map) and init(Object) methods have been changed into just the configure(Map) and individual setter methods (e.g. setRequest, setSession, etc). Basically, when it's time to instantiate a tool, the tool manager will gather all the "configuration properties" for that tool, its toolbox, etc and combine it into a single map with the "init data" (context, request, session, etc). The manager searches for relevant setter methods that accept that data and also for a configure(Map) method. The setters get what they're asking for (if available) and the configure() method accepts the whole combined Map. The upshot of this approach is that tools no longer need to conform to any interfaces or patterns. In fact, it's possible to write a FooTool that doesn't know anything about any VelocityTools classes whatsoever and yet be fully instantiable and configurable by VelocityTools. Your tools don't need to know about anything except what they need to know about.
?
开发时需要注意
1 Tool Keys/Names
2 scope
3 SafeConfig
4 Be robust. Catch exceptions and return null
on errors.
5 Be flexible. Have methods accept Object
when possible.
6 Be careful. Choose scope carefully and be aware of thread safety issues.
7 Be fluent. Subtools or get(key)
methods can make a clear and flexible API.
?
example
java代码:
import org.apache.velocity.tools.config.DefaultKey;@DefaultKey("myTool")public class VelocityTools { public VelocityTools() { } public String getName(){ return "hello world"; }}
?配置文件
<tools> <toolbox scope="request"> <tool name="code"><DIV>$myTool.getName()</DIV>
?