Introducción a Apache Velocity

1. Información general

Velocity es un motor de plantillas basado en Java.

Es un marco web de código abierto diseñado para usarse como un componente de vista en la arquitectura MVC y proporciona una alternativa a algunas tecnologías existentes, como JSP.

Velocity se puede utilizar para generar archivos XML, SQL, PostScript y la mayoría de los otros formatos basados ​​en texto.

En este artículo, exploraremos cómo se puede utilizar para crear páginas web dinámicas.

2. Cómo funciona la velocidad

La clase principal de Velocity es VelocityEngine .

Orquesta todo el proceso de lectura, análisis y generación de contenido utilizando el modelo de datos y la plantilla de velocidad.

En pocas palabras, estos son los pasos que debemos seguir para cualquier aplicación de velocidad típica:

  • Inicializar el motor de velocidad
  • Leer la plantilla
  • Pon el modelo de datos en el objeto de contexto
  • Fusionar la plantilla con datos de contexto y renderizar la vista

Veamos un ejemplo siguiendo estos sencillos pasos:

VelocityEngine velocityEngine = new VelocityEngine(); velocityEngine.init(); Template t = velocityEngine.getTemplate("index.vm"); VelocityContext context = new VelocityContext(); context.put("name", "World"); StringWriter writer = new StringWriter(); t.merge( context, writer );

3. Dependencias de Maven

Para trabajar con Velocity, necesitamos agregar las siguientes dependencias a nuestro proyecto Maven:

 org.apache.velocity velocity 1.7   org.apache.velocity velocity-tools 2.0 

La última versión de estas dos dependencias puede estar aquí: velocity y velocity-tools.

4. Lenguaje de plantilla de velocidad

Velocity Template Language (VTL) proporciona la forma más sencilla y limpia de incorporar el contenido dinámico en una página web mediante el uso de referencias VTL.

La referencia de VTL en la plantilla de velocidad comienza con $ y se usa para obtener el valor asociado con esa referencia. VTL proporciona también un conjunto de directivas que se pueden utilizar para manipular la salida del código Java. Esas directivas comienzan con #.

4.1. Referencias

Hay tres tipos de referencias en Velocity, variables, propiedades y métodos:

  • variables : definidas dentro de la página usando la directiva #set o el valor devuelto desde el campo del objeto Java:
    #set ($message="Hello World")
  • propiedades : se refieren a campos dentro de un objeto; también pueden hacer referencia a un método getter de la propiedad:
    $customer.name
  • métodos : consulte el método en el objeto Java:
    $customer.getName()

El valor final resultante de cada referencia se convierte en una cadena cuando se representa en la salida final.

4.2. Directivas

VTL proporciona un amplio conjunto de directivas:

  • set : se puede utilizar para establecer el valor de una referencia; este valor se puede asignar a una variable o referencia de propiedad:
    #set ($message = "Hello World") #set ($customer.name = "Brian Mcdonald")
  • condicionales - #if, #elseif y #Else directivas proporcionan una manera de generar el contenido basado en comprobaciones condicionales:
    #if($employee.designation == "Manager") 

    Manager

    #elseif($employee.designation == "Senior Developer")

    Senior Software Engineer

    #else

    Trainee

    #end
  • bucles : la directiva #foreach permite recorrer una colección de objetos:
    
          
      #foreach($product in $productList)
    • $product
    • #end
  • include : el elemento #include brinda la capacidad de importar archivos a la plantilla:
    #include("one.gif","two.txt","three.html"...)
  • parse - la declaración #parse permite al diseñador de la plantilla importar otro archivo local que contiene VTL; A continuación, Velocity analizará el contenido y lo renderizará:
    #parse (Template)
  • evaluate#evaluate directive can be used to evaluate VTL dynamically; this allows the template to evaluate a String at render time, for example to internationalise the template:
    #set($firstName = "David") #set($lastName = "Johnson") #set($dynamicsource = "$firstName$lastName") #evaluate($dynamicsource)
  • break#break directive stops any further rendering of current execution scope (i.e. #foreach, #parse)
  • stop#stop directive stops any further rendering and execution of the template.
  • velocimacros#macro directive allows the template designer to define a repeated segment of VTL:
    #macro(tablerows)  #end

    This macro now can be put in any place in the template as #tablerows():

    #macro(tablerows $color $productList) #foreach($product in $productList) $product.name #end #end

4.3. Other Features

  • math – a handful built-in mathematical functions, which can be used in templates:
    #set($percent = $number / 100) #set($remainder = $dividend % $divisor)
  • range operator – that can be used in conjunction with #set and #foreach:
    #set($array = [0..10]) #foreach($elem in $arr) $elem #end

5. Velocity Servlet

The primary job of the Velocity Engine is to generate content based on a template.

The Engine doesn't contain any web related functionalities in itself. To implement a web application, we need to use a servlet or servlet-based framework.

Velocity provides one out of the box implementation VelocityViewServlet, which is a part of the velocity-tools subproject.

To make use of the built-in functionality provided by VelocityViewServlet, we can extend our servlet from VelocityViewServlet and override the handleRequest() method:

public class ProductServlet extends VelocityViewServlet { ProductService service = new ProductService(); @Override public Template handleRequest( HttpServletRequest request, HttpServletResponse response, Context context) throws Exception { List products = service.getProducts(); context.put("products", products); return getTemplate("index.vm"); } }

6. Configuration

6.1. Web Configuration

Let's now see how to configure the VelocityViewServlet in the web.xml.

We need to specify the optional initialization parameters which include velocity.properties and toolbox.xml:

 apache-velocity //...  velocity org.apache.velocity.tools.view.VelocityViewServlet  org.apache.velocity.properties /WEB-INF/velocity.properties   //...  

We also need to specify the mapping for this servlet. All the requests for velocity templates (*.vm) need to be served by the velocity servlet:

 velocityLayout *.vm 

6.2. Resource Loader

Velocity provides flexible resource loader system. It allows one or more resource loader to be in operation at the same time:

  • FileResourceLoader
  • JarResourceLoader
  • ClassPathResourceLoader
  • URLResourceLoader
  • DataSourceResourceLoader
  • WebappResourceLoader

These resource loaders are configured in velocity.properties:

resource.loader=webapp webapp.resource.loader.class=org.apache.velocity.tools.view.WebappResourceLoader webapp.resource.loader.path = webapp.resource.loader.cache = true

7. Velocity Template

Velocity template is the place where all the view generation logic is written. These pages are written using Velocity Template Language (VTL):

 ...   ... 

$products.size() Products on Sale!

We are proud to offer these fine products at these amazing prices. ... #set( $count = 1 )

#foreach( $product in $products ) #set( $count = $count + 1 ) #end
Serial # Product Name Price
$count) $product.getName() $product.getPrice()

8. Managing the Page Layout

Velocity provides a simple layout control and customizable error screens for Velocity Tool based application.

VelocityLayoutServlet encapsulates this capability to render the specified layouts. VelocityLayoutServlet is an extension to VelocityViewServlet.

8.1. Web Configuration

Let's see how to configure the VelocityLayoutServlet. The servlet is defined for intercepting the requests for velocity template pages and the layout specific properties are defined in velocity.properties file:

 // ...  velocityLayout org.apache.velocity.tools.view.VelocityLayoutServlet  org.apache.velocity.properties /WEB-INF/velocity.properties   // ...  velocityLayout *.vm  // ... 

8.2. Layout Templates

Layout template defines the typical structure of a velocity page. By default, the VelocityLayoutServlet searches for Default.vm under the layout folder. Overriding few properties can change this location:

tools.view.servlet.layout.directory = layout/ tools.view.servlet.layout.default.template = Default.vm 

The layout file consists of header template, footer template, and a velocity variable $screen_content which renders the contents of requested velocity page:

  Velocity #parse("/fragments/header.vm") $screen_content #parse("/fragments/footer.vm") 

8.3. Layout Specification in the Requested Screen

Layout for a particular screen can be defined as a velocity variable at the beginning of a page. That is done by putting this line in the page:

#set($layout = "MyOtherLayout.vm")

8.4. Layout Specification in the Request Parameter

We can add a request parameter in the query string layout=MyOtherLayout.vm and VLS will find it and render the screen within that layout instead of searching for default layout.

8.5. Error Screens

Customized error screen can be implemented using velocity layout. VelocityLayoutServlet provides two variables $error_cause and $stack_trace to present the exception details.

Error page can be configured in velocity.properties file:

tools.view.servlet.error.template = Error.vm

9. Conclusion

En este artículo, hemos aprendido cómo Velocity es una herramienta útil para representar las páginas web dinámicas. Además, hemos visto diferentes formas de utilizar los servlets proporcionados por velocidad.

También tenemos un artículo centrado en una configuración de Velocity con Spring MVC aquí en Baeldung.

El código completo de este tutorial está disponible en GitHub.