Speed and Agility: Deciphering the Secrets of Velocity

: Just work hard and leave the rest to time

: Xiaopozhan

Speed and Agility: Deciphering the Secrets of Velocity

  • Preface
  • First: Basics of Velocity template syntax
  • Second: Variables and data rendering
  • Third: Conditional judgment and logical implementation
  • Fourth: Loops and Iterations
  • Fifth: Custom instructions
  • Sixth: Macro
  • Seventh: File introduction
  • Eighth: Error handling
  • Ninth: Advanced variable operations

Foreword

Velocity template syntax plays a key role in dynamic content generation and template rendering. The plug-in EasyCode in the idea is also written using the Velocity template. You can use this plug-in to directly generate the corresponding entity class, service, mapper, vo, do, etc. codes based on the table. This article will take you through the syntactic details of this powerful tool, allowing you to build templates and generate dynamic content more efficiently.

First: Basics of Velocity template syntax

Velocity template syntax is a template engine language for generating text output, typically used to generate dynamic content such as HTML pages or text files. The following are the basic concepts of Velocity template syntax:

  1. Variables: In Velocity, you can use variables to store and access data. Variables start with the $ symbol, such as $variableName. Variables can contain different types of data such as strings and numbers.

    #set($name = "John")
    Hello, $name!
    
  2. Comments: You can add comments to your template to improve readability. Comments starting with ## are treated as comments until the end of the line.

    ## This is a comment
    
  3. Conditional Statements: Velocity supports conditional statements, such as if, else and elseif, for Conditionally execute different blocks of code.

    #if($condition)
        // Do something if the condition is true
    #elseif($anotherCondition)
        // Do something else if another condition is true
    #else
        // Do something if no condition is true
    #end
    
  4. Loops: You can use the #foreach directive to iterate over elements in a collection or array.

    #foreach($item in $list)
        Item: $item
    #end
    
  5. Macros: Velocity allows you to define reusable blocks of code, called macros. Macros can be called multiple times in a template, similar to functions.

    #macro(myMacro $param1 $param2)
        // Macro content with parameters
    #end
    #myMacro($value1, $value2)
    
  6. Including Other Templates: You can use the #include directive to include other Velocity templates into the current template to achieve modularization and reuse.

    #include("header.vm")
    

These are the basic concepts of Velocity’s template syntax, which enable you to generate dynamic content and customize it based on conditions and data. Comments can also be added as per your requirement to improve the readability of the code. If you need more specific examples or have additional questions, please feel free to ask.

Second: Variables and data rendering

In Velocity, you can use variables and render data to generate text output. Here’s an explanation of how to use variables in Velocity and common output methods and filters:

  1. Definition and reference of variables:

    • Define variables: Use the #set directive to define a variable, which can then be referenced in the template.

      #set($name = "John")
      Hello, $name!
      
  2. Output variables:

    • Directly output variables: Variables start with the $ symbol, and their values can be output to the template by directly referencing them.

      $variableName
      
    • Use ${} to clarify variable scope: Sometimes, if the variable name contains special characters or you need to specify the variable scope explicitly, you can use ${}.

      ${customer.name}
      
  3. Filter:

    • Filters are used to process the value of a variable to make it more suitable for output. Here are some common filters:

      • capitalize: Capitalize the first letter of the variable.

        $name.capitalize()
        
      • toLowerCase: Converts variable values to lowercase.

        $text.toLowerCase()
        
      • toUpperCase: Converts variable values to uppercase.

        $text.toUpperCase()
        
      • length: Get the length of the variable value.

        The length of the text is: $text.length()
        
      • substring: Get the substring of the variable value.

        $text.substring(0, 5) // Gets the first 6 characters of $text
        

    By using filters, you can do some processing on the value of the variable to suit your needs before outputting it.

These are the basic ways to use variables and render data in Velocity as well as some common filter examples. You can apply appropriate filters based on your specific needs and data to produce the desired output. If you need more examples or have additional questions, please feel free to ask.

Third: Conditional judgment and logic implementation

In Velocity, conditional statements (such as if, else, elseif) are used to implement logical judgments and control the output of templates. You can create complex logic to execute different blocks of code based on different conditions. The following is a detailed explanation of the in-depth study of conditional statements and complex logical judgments in Velocity:

  1. Basic conditional statements:

    • #if: The #if instruction is used to perform conditional judgment. If the condition is true, the corresponding code block is executed. If the condition is false, an optional #else block can optionally be executed.

      #if($condition)
          // Code to execute if the condition is true
      #end
      
    • #else: The #else directive is used for a block of code that is executed when a condition is not met.

      #if($condition)
          // Code to execute if the condition is true
      #else
          // Code to execute if the condition is false
      #end
      
    • #elseif: The #elseif directive is used to specify multiple conditions to be judged one by one. If the previous condition is not met, the next condition is checked. You can have multiple #elseif conditions.

      #if($condition1)
          // Code to execute if condition1 is true
      #elseif($condition2)
          // Code to execute if condition2 is true
      #elseif($condition3)
          // Code to execute if condition3 is true
      #else
          // Code to execute if no condition is true
      #end
      
  2. Logical operators:

    • In conditional statements, you can use logical operators to combine multiple conditions. Common logical operators include & amp; & amp; (and), || (or), ! (not), etc.

      #if($condition1 & amp; & amp; $condition2)
          // Code to execute if both condition1 and condition2 are true
      #end
      
      #if($condition1 || $condition2)
          // Code to execute if either condition1 or condition2 is true
      #end
      
      #if(!$condition)
          // Code to execute if condition is false
      #end
      
  3. Complex logical judgment:

    • You can use parentheses to combine multiple conditions to achieve more complex logic.

      #if(($condition1 || $condition2) & amp; & amp; $condition3)
          // Code to execute if (condition1 OR condition2) AND condition3 is true
      #end
      
  4. Comparison operators:

    • Comparison operators are used to compare the values of variables. Common comparison operators include == (equal), != (not equal), < (less than), > (greater than), <= (less than or equal to), >= (greater than or equal to), etc.

      #if($number == 5)
          // Code to execute if $number is equal to 5
      #end
      

Fourth: Loops and Iterations

In Velocity, you can use loop structures to process collection data, such as #foreach and #while for iterative operations. This allows you to iterate over the elements in a collection or perform loops based on conditions. The following is a detailed description of these two loop structures:

  1. #foreach loop:

    #foreach A loop is used to iterate over the elements in a collection, such as an array, list, or map. The following is the basic #foreach syntax:

    #foreach($item in $collection)
        // Code to execute for each item in the collection
    #end
    
    • $item: This is a placeholder that represents the current element in the collection.
    • $collection: The collection to be traversed, which can be an array, list, map, etc.

    Example 1: Iterate over an array

    #set($numbers = [1, 2, 3, 4, 5])
    <ul>
    #foreach($number in $numbers)
        <li>$number</li>
    #end
    </ul>
    

    Example 2: Iterate over a list

    #set($fruits = ["apple", "banana", "cherry"])
    <ul>
    #foreach($fruit in $fruits)
        <li>$fruit</li>
    #end
    </ul>
    
  2. #while loop:

    #while Loops are used to perform iterative operations based on conditions. As long as the conditions are true, the loop will continue to execute. The following is the basic #while syntax:

    #set($counter = 0)
    #while($counter < 5)
        // Code to execute while the condition is true
        #set($counter = $counter + 1)
    #end
    

    In this example, the #while loop will execute until the value of $counter is less than 5. On each loop iteration, you need to make sure to update the condition to avoid infinite loops.

    Example: Calculate factorial using #while loop

    #set($n = 5)
    #set($result = 1)
    #set($counter = 1)
    #while($counter <= $n)
        #set($result = $result * $counter)
        #set($counter = $counter + 1)
    #end
    Result: $result
    

    The example above calculates the factorial of 5.

Whether using a #foreach or a #while loop, Velocity allows you to process collection data and perform iterative operations to generate dynamic content. If you have more specific questions or need further examples, please feel free to ask.

Fifth: Custom instructions

Velocity supports custom directives, allowing you to create and use custom directives to meet specific needs. These custom instructions extend Velocity's functionality, enabling you to perform specific operations or generate specific output. Here are the steps on how to create and use a custom Velocity directive:

  1. Create a custom directive class:

    First, you need to create a Java class to implement the custom directive. This class must inherit from the org.apache.velocity.runtime.directive.Directive class, and you need to implement the following methods:

    • getName(): Returns the name of the custom directive, which is the name of the directive referenced in the Velocity template.
    • getType(): Returns the type of instruction, usually LINE or BLOCK, indicating whether the instruction is a line-level instruction or a block-level instruction.
    • render(): The main logic of the instruction, defining the behavior of the instruction.

    Example:

    import org.apache.velocity.runtime.directive.Directive;
    import org.apache.velocity.runtime.parser.node.Node;
    import org.apache.velocity.context.InternalContextAdapter;
    import org.apache.velocity.exception.ParseErrorException;
    import org.apache.velocity.exception.ResourceNotFoundException;
    import org.apache.velocity.exception.MethodInvocationException;
    import org.apache.velocity.runtime.parser.Token;
    import org.apache.velocity.runtime.parser.Parser;
    
    public class MyCustomDirective extends Directive {<!-- -->
        @Override
        public String getName() {<!-- -->
            return "myCustomDirective";
        }
    
        @Override
        public int getType() {<!-- -->
            return LINE;
        }
    
        @Override
        public boolean render(InternalContextAdapter context, Writer writer, Node node)
            throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {<!-- -->
            // Your custom directive logic here
            return true;
        }
    }
    
  2. Register custom directives:

    In a Velocity application, you need to register the custom directive so that Velocity can recognize and use it. This is usually done during Velocity initialization, using the VelocityEngine's addDirective method to add a custom directive class to the engine.

    Example:

    VelocityEngine velocityEngine = new VelocityEngine();
    velocityEngine.addDirective("myCustomDirective", new MyCustomDirective());
    
  3. Use custom directives in templates:

    Once the custom directive is registered, you can use it in Velocity templates. Use the name of the directive, followed by the directive's arguments, like this:

    #myCustomDirective(arg1, arg2)
    

    Here, myCustomDirective is the name of your custom directive, arg1 and arg2 are the parameters of the directive, you can use render method to access them.

  4. Logic of custom directive:

    In the custom directive's render method, you can write your own logic to implement the directive's behavior. You can access template context, output streams, and node information to perform your operations and generate output.

    Example:

    @Override
    public boolean render(InternalContextAdapter context, Writer writer, Node node)
        throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {<!-- -->
        // Access arguments from node
        String arg1 = node.jjtGetChild(0).value(context).toString();
        String arg2 = node.jjtGetChild(1).value(context).toString();
    
        // Perform custom logic
        String result = arg1 + " " + arg2;
    
        // Write the result to the output
        writer.write(result);
    
        return true;
    }
    

By creating custom instructions, you can extend Velocity's functionality to meet specific needs, perform custom actions, or generate specific output. This is useful for performing special tasks in templates. Make sure to handle exceptions in custom directives to ensure application stability. If you need more examples or have additional questions, please feel free to ask.

Sixth: Macros

Macros are powerful tools in Velocity for creating reusable blocks of code. They allow you to define a piece of code, wrap it in a macro, and call it multiple times in a template, just like a function. Here's a detailed look at how to create and use macros in Velocity:

1. Define macro:

To create a macro, you define it using the #macro directive and then write the code blocks you want to reuse inside the macro. Macros can accept parameters, allowing you to pass different values each time they are called. The basic syntax of macros is as follows:

#macro(myMacro $param1 $param2)
    // Code to execute with $param1 and $param2
#end

In the above example, myMacro is the name of the macro, and $param1 and $param2 are the parameters, which you can use in the macro.

2. Call macro:

To call a macro in a template, use the #myMacro directive, followed by the parameter value. For example:

#myMacro("value1", "value2")

Here, #myMacro is the call of the macro, which will execute the code in the macro and pass the parameter values to it.

3. Macro parameters:

You can specify multiple parameters when defining the macro and pass the corresponding number of parameter values when the macro is called. Macro parameters allow you to use the macro in different contexts.

Example:

#macro(addNumbers $num1 $num2)
    The sum of $num1 and $num2 is: $mathTool.add($num1, $num2)
#end

#addNumbers(5, 3)
#addNumbers(10, 20)

In the example above, the addNumbers macro accepts two arguments, adds them, and prints the result. You can call this macro multiple times and pass different parameter values.

4. Local variables of macro:

Macros can also define local variables, which are only visible inside the macro. Local variables can help you store intermediate results or simplify macro logic.

Example:

#macro(calculateAverage $num1 $num2)
    #set($average = ($num1 + $num2) / 2)
    The average of $num1 and $num2 is: $average
#end

#calculateAverage(5, 10)

In the above example, average is a local variable within a macro that calculates and stores the average.

Using macros can improve the maintainability of Velocity templates because you can encapsulate repeated code blocks in macros, reducing code duplication. It also provides greater flexibility as you can pass parameter values as needed. If you need more examples or have additional questions, please feel free to ask.

Seventh: File introduction

In Velocity templates, you can use file imports to extend the functionality of the template, importing external files to reuse code blocks, modules, or content. This improves the maintainability and reusability of templates. Here are detailed instructions on how to do file import:

1. Import external files:

Use the #include directive to include external files so that you can reuse the contents of other files in the main template. The basic #include syntax is as follows:

#include("external_template.vm")

In the above syntax, external_template.vm is the path to the external template file to be imported. This can be a relative or absolute path, depending on your application settings.

2. Contents of external files:

Content in external files can include variables, conditional statements, loops, macros, and other Velocity syntax elements. When you import an external file into the main template, its content will be embedded into the main template and processed together.

3. Example:

Let's look at a simple example, assuming you have an external template file header.vm that contains the header section of your website:

<!DOCTYPE html>
<html>
<head>
    <title>My Website</title>
</head>
<body>
    <header>
        <h1>Welcome to My Website</h1>
    </header>

Then, you can include the header content in the main template by importing this header.vm file:

#include("header.vm")

<p>Here is the content of the main page.</p>

In this example, the main template imports the header.vm file, so the generated output will include the contents of the header.vm file, as well as the rest of the main template.

4. Notes:

  • Make sure the path to the file is correct and that the file exists.
  • Velocity syntax in external files is the same as in the main template, so you can use functions such as variables, conditionals, loops, and macros in external files.
  • File imports make templates easier to maintain because you can split different parts of the page into separate files and import them when needed.

File importing is a powerful technique that can be used to create more structured and maintainable Velocity templates, especially useful for large websites or applications. If you need more examples or have additional questions, please feel free to ask.

Eighth: Error handling

In Velocity templates, the main issues related to error handling and exception situations include template syntax errors, undefined variables, non-existent methods, etc. Here are some ways to handle errors and exceptions to ensure the robustness of Velocity templates:

  1. Catching and handling exceptions:

    Velocity templates can catch and handle exceptions by using try...catch blocks to prevent the template from being interrupted. You can use #try and #catch in templates to catch exceptions and perform appropriate handling.

    #try
        #set($result = $undefinedVariable.someMethod())
    #catch(Exception $e)
        An error occurred: $e.getMessage()
    #end
    

    In the above example, if $undefinedVariable does not exist or there is no someMethod() method, the exception will be caught and an error message will be output.

  2. Check if the variable is defined:

    Use #if statements to check whether a variable has been defined to avoid exceptions when using undefined variables.

    #if($myVariable)
        // Use $myVariable
    #end
    

    If $myVariable is not defined, the #if condition will be false and therefore the code block inside it will not be executed.

  3. Use default values:

    In some cases, you can use the $!variable syntax to use the default value of a variable to prevent an undefined variable from throwing an exception.

    The value is: $!myVariable
    

    If $myVariable is not defined, it will be replaced with the default value.

  4. Use #set to initialize variables:

    Initialize variables via #set before using them to ensure they are defined, even if initialized to null or an empty string.

    #set($myVariable = "")
    

    This can help avoid undefined variable problems.

  5. Control template generation:

    In templates, you can use conditional statements and logic to control whether specific parts of content are generated to prevent inappropriate situations from throwing exceptions.

    #if($condition)
        // Generate content based on condition
    #end
    

    This allows you to conditionally generate or skip specific sections of content.

  6. Customized exception handling:

    If you use Velocity as your template engine, you can set up custom exception handlers at the application level to catch exceptions that may be thrown by the Velocity engine and perform appropriate handling.

    VelocityContext context = new VelocityContext();
    context.addProperty("event_handler.error.class", MyCustomErrorHandler.class.getName());
    VelocityEngine velocityEngine = new VelocityEngine();
    velocityEngine.init();
    

    MyCustomErrorHandler is a class of custom exception handler that can handle exceptions of the Velocity engine.

Handling errors and exceptions is an important part of ensuring the robustness and stability of Velocity templates. Depending on the specific application scenario, you can take appropriate measures to deal with possible problems. If you need more details or examples, please feel free to ask.

Ninth: Advanced variable operations

Performing advanced variable operations and complex data operations in Velocity usually involves in-depth use of Velocity elements such as variables, collections, conditional statements, and macros. Here are some advanced tips and examples to help you perform complex data manipulation and calculations in Velocity templates:

1. Collection operation:

  • Traversing nested collections: If you have nested collections, you can use nested #foreach loops to traverse multiple levels of data.

    Example:

    #set($students = [
        {"name": "Alice", "grades": [90, 95, 88]},
        {"name": "Bob", "grades": [85, 92, 78]}
    ])
    
    <table>
    #foreach($student in $students)
        <tr>
            <td>$student.name</td>
            <td>
                <ul>
                #foreach($grade in $student.grades)
                    <li>$grade</li>
                #end
                </ul>
            </td>
        </tr>
    #end
    </table>
    
  • Use #set to aggregate data: You can use the #set directive to aggregate data, such as calculating sums, averages, etc.

    Example:

    #set($numbers = [5, 10, 15, 20])
    #set($sum = 0)
    
    #foreach($number in $numbers)
        #set($sum = $sum + $number)
    #end
    
    The sum of the numbers is: $sum
    

2. Conditional statement:

  • Complex Conditions: Use multiple #if, #elseif, and #else conditions to perform complex conditional logic.

    Example:

    #if($age < 18)
        You are a minor.
    #elseif($age >= 18 & amp; & amp; $age < 65)
        You are an adult.
    #else
        You are a senior citizen.
    #end
    

3. Macro:

  • Nested macros: Macros can be nested, allowing you to create macros that contain complex logic.

    Example:

    #macro(calculateAverage $numbers)
        #set($sum = 0)
        #set($count = 0)
        #foreach($number in $numbers)
            #set($sum = $sum + $number)
            #set($count = $count + 1)
        #end
        #set($average = $sum / $count)
        The average is: $average
    #end
    
  • Macros with parameters: Macros can accept parameters, allowing you to pass data and conditions to the macro.

    Example:

    #macro(formatDate $date $format)
        $date.toString($format)
    #end
    
    #formatDate($myDate, "yyyy-MM-dd")
    

4. Custom tool class:

If you need to perform more complex calculations and data manipulation, you can create custom tool classes in Java and then bind them to the Velocity engine to access these tool methods in the template. This allows custom methods to be called in Velocity templates to process data and logic.

Example:

public class MyCustomTools {<!-- -->
    public static int calculateSum(List<Integer> numbers) {<!-- -->
        int sum = 0;
        for (int number : numbers) {<!-- -->
            sum + = number;
        }
        return sum;
    }
}

Bind a custom tool class in Velocity:

VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.init();
velocityEngine.getContext().put("myTools", new MyCustomTools());

Then use it in the Velocity template:

The sum is: $myTools.calculateSum($numbers)

These advanced techniques allow you to perform complex data manipulation and calculations in Velocity templates, giving you more flexibility in generating dynamic content. Depending on your specific needs, you may choose to use some or more of these techniques. If you need more examples or have additional questions, please feel free to ask.