« | August 2025 | » | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | | | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | | | | | | | |
| 公告 |
关注电子政务、大型企业应用开发、Web、Workflow、MOM、MDA、RCP、GEF email:gmluyang@gmail.com
|
Blog信息 |
blog名称:SixSun的Blog 日志总数:152 评论数量:372 留言数量:13 访问次数:2377601 建立时间:2004年12月13日 |

| |
[Java Open Source]Using Velocity In General Applications 文章收藏, 读书笔记, 软件技术
SixSun 发表于 2005/10/15 16:47:27 |
Using Velocity In General Applications
As Velocity was designed to be a general-use tool, it is just as useful in general application programs as it is servlets. In general, you can use the same programming pattern discussed at the beginning of this guide, but there are a few utility methods provided for application use, just like we provide the VelocityServlet base class for ease of use in servlet programming. The only new responsibility you have as the application programmer is to initialize the Velocity runtime engine, but that is easy. The Velocity Helper Class
Velocity contains an application utility class called Velocity ( org.apache.velocity.app.Velocity ). The purpose of this class is to provide the necessary methods required to initialize Velocity, as well as useful utility routines to make life easier in using Velocity. This class is documented in the project's javadoc, so please look there for definitive details. This documentation is intended to be of a tutorial nature; therefore for compete API information, the Javadoc is the definitive source.
The Velocity runtime engine is a singleton instance that provides resource, logging and other services to all Velocity users running in the same JVM. Therefore, the runtime engine is initialized only once. You can attempt to initialize Velocity more than once, but only the first initialization will apply. The rest of the attempts will be ignored. The Velocity utility class currently provides five methods used in configuration of the runtime engine.
The five configuration methods are :
setProperty( String key, Object o ) Sets the property key with the value o . The value is typically a String, but in special cases can also be a comma-separated list of values (in a single String, ex."foo, bar, woogie") as well as other things that will arise.
Object getProperty( String key ) Returns the value of the property key. Note that you must be aware of the type of the return value, as they can be things other than Strings.
init() Initializes the runtime with the default properties provided in the distribution.(These are listed below in the section pertaining to properties.)
init( Properties p ) Initialize the runtime with the properties contained in the java.util.Properties object passed as an argument.
init( String filename ) initilizes the runtime using the properties found in the properties file filename
Note that in each case, the default properties will be used as a base configuration, and any additional properties specified by the application will replace individual defaults. Any default properties not overwritten will remain in effect. This has the benefit that only the properties you are interested in changing need to be specified, rather than a complete set.
Another thing to note is that the init() calls may be called more than once without harm in an application. However, the first call to any of the init() functions will configure the engine with the configuration properties set at that point, and any further configuration changes or init() calls will be ignored.
The most common approaches to initializing Velocity will be something like :
Setup the configuration values you wish to set in a file in the same format as org/apache/velocity/runtime/defaults/velocity.properties (the default set), or in a java.util.Properties , and then call either init( filename ) or init( Properties )
Set the configuration values individually using setProperty() and then call init() . This method is generally used by more advanced applications that already have their own configuration management system - this allows the application so configure Velocity based upon values it generates at runtime, for example.
Once the runtime is initialized, you can do with it what you wish.. This mostly revolves around rendering templates into an output stream, and the Velocity utility class allows you to do this easily. Currently, here are the methods and a brief description of what they do :
evaluate( Context context, Writer out, String logTag, String instring ) evaluate( Context context, Writer writer, String logTag, InputStream instream ) These methods will render the input, in either the form of String or InputStream to an output Writer, using a Context that you provide. This is a very convenienient method to use for token replacement of strings, or if you keep 'templates' of VTL-containing content in a place like a database or other non-file storage, or simply generate such dynamically.
invokeVelocimacro( String vmName, String namespace, String params[], Context context, Writer writer ) Allows direct access to Velocimacros. This can also be accomplished via the evaluate() method above if you wish. Here you simply name the vm you wish to be called, create an array of args to the VM, a Context of data, and Writer for the output. Note that the VM args must be the 'keys' of the data objects in the Context, rather than literal data to be used as the arg. This will probably change.
mergeTemplate( String templateName, Context context, Writer writer ) Convenient access to the normal template handling and rendering services of Velocity. This method will take care of getting and rendering the template. It will take advantage of loading the template according to the properties setting for the file resource loader, and therefore provides the advantage of file and parsed template caching that Velocity offers. This is the most efficient way to access templates, and is recommended unless you have special needs.
boolean templateExists( String name ) Determines if a template name is able to be found by the currently configured resource loaders.
Once we know about these basic helpers, it is easy to write Java program that uses Velocity. Here it is:
import java.io.StringWriter;import org.apache.velocity.app.Velocity;import org.apache.velocity.VelocityContext;public class Example2{ public static void main( String args[] ) { /* first, we init the runtime engine. Defaults are fine. */ Velocity.init(); /* lets make a Context and put data into it */ VelocityContext context = new VelocityContext(); context.put("name", "Velocity"); context.put("project", "Jakarta"); /* lets render a template */ StringWriter w = new StringWriter(); Velocity.mergeTemplate("testtemplate.vm", context, w ); System.out.println(" template : " + w ); /* lets make our own string to render */ String s = "We are using $project $name to render this."; w = new StringWriter(); Velocity.evaluate( context, w, "mystring", s ); System.out.println(" string : " + w ); }}
When we run this program, and have the template testtemplate.vm in the same directory as our program (because we used the default configuration properties, and the defaul place to load templates from is the current directory...), our output should be :
template : Hi! This Velocity from the Jakarta project.
string : We are using Jakarta Velocity to render this.
where the template we used, testtemplate.vm, is
Hi! This $name from the $project project.
That's all there is to it! Note that we didn't have to use both mergeTemplate() and evaluate() in our program. They are both included there for demonstration purposes. You will probably use only one of the methods, but depending on you application requirements, you are free to do what you wish.
This appears to be a little different from the 'fundamental pattern' that was mentioned at the beginning of this guide, but it really is the same thing. First, you are making a context and filling it with the data needed. Where this examples differs is that in the part of the above example where mergeTemplate() is used, mergeTemplate() is doing the work of getting the template and merging it for you, using the lower-level calls in the Runtime class. In the second example, you are making your template dynamically via the String, so that is analgous to the 'choose template' part of the process, and the evaluate() method does the merging for you using lower level calls.
So the example above sticks to the same simply pattern of using the Velocity template engine, but the utility functions do some of the repeated drudge work, or allow you other options for your template content other than template files. Exceptions
There are three exceptions that Velocity will throw during the parse / merge cycle. This are additional to the exceptions that will come from IO problems, etc. They are found in the package org.apache.velocity.exception and are:
ResourceNotFoundException Thrown when the resource managment system cannot find a resource (template) that was requested.
ParseErrorException Thrown when a VTL syntax error is found when parsing a resource (template).
MethodInvocationException Thrown when a method of object in the context thrown an exception during render time. This exception wraps the thrown exception and propogates it to the application. This allows you to handle problems in your own objects at runtime.
In each case, a message is put into the runtime log. For more information, see the Javadoc API documentation. Miscellaneous Details
While the above example used the default properties, setting your own properties is very simple. All you have to do is make a properties file somewhere and pass the name of that file to the init(String) method of the Velocity utility class, or make a java.util.Properties object, add the desired properties and values, and pass that to the init(Properties) method. The latter method is convenient, because you can either fill it directly from a separate properties file via the load() method, or even better, you can fill it dynamically from your own application / framework's property set at runtime. This gives you the freedom to combine all of the properties for your app into one properties file.
If we wanted to use a different directory than the current directory to load our template from, we could do something like this :
...import java.util.Properties; ...public static void main( String args[] ){ /* first, we init the runtime engine. */ Properties p = new Properties(); p.setProperty("file.resource.loader.path", "/opt/templates"); Velocity.init( p ); /* lets make a Context and put data into it */ ...
And, assuming you have a directory /opt/templates and the template testtemplate.vm is in there, then things would work just fine. If you try this and have a problem, be sure to look at the velocity.log for information - the error messages are pretty good for figuring out what is wrong. |
|
回复:Using Velocity In General Applications 文章收藏, 读书笔记, 软件技术
Matrix(游客)发表评论于2006/1/9 13:51:50 |
|
» 1 »
|