• velocity快速入门


    1.velocity简介

      velocity是一个基于Java的模板引擎,可以通过特定的语法获取在Java对象的数据,填充到模板中,从而实现界面和Java代码的分离。这意味着可以使用velocity替代jsp的开发模式了,这使得前端开发人员可以和 Java 程序开发人员同步开发一个遵循 MVC 架构的 web 站点,在实际应用中,velocity还可以应用于很多其他的场景。

    2.应用场景

    web应用程序:作为应用程序的视图,展示数据。

    源代码生成:velocity可用于基于模板生成Java源代码。

    自动电子邮件:网站注册,认证等的电子邮件模板。

    网页静态化:基于velocity模板,生成静态网页。

    3.velocity组成结构

    velocity主要分为app、context、runtime和一些辅助util几个部分

    app模块:主要封装了一些接口,暴露给使用者使用,主要有两个类,分别是Velocity(单例)和VelocityEngine

    context模块:主要封装了模板渲染需要的变量

    runtime模块:整个velocity的核心模块,runtime模块会将加载的模块解析成语法树,velocity调用mergeTemplate方法时会渲染整棵树,并输出最终的渲染结果

    runtimeInstance类为整个velocity渲染提供了一个单例模式,拿到了这个实例就可以完成渲染过程了

    4.快速入门

    4.1 需求分析

    使用velocity定义HTML模板,将动态数据填充到模板中,形成一个完整的HTML页面

    4.2 步骤分析

    (1)创建项目

    (2)引入依赖

    (3)定义模板

    (4)输出html

    4.3 velocity入门程序

    创建maven项目,然后引入如下依赖

            <!--velocity-->
            <dependency>
                <groupId>org.apache.velocity</groupId>
                <artifactId>velocity-engine-core</artifactId>
                <version>2.0</version>
            </dependency>

     在templates目录下新建一个模板文件 demo1.vm,内容如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    hello,${name}!
    </body>
    </html>

    编写测试类,使用velocity生成html文件

        @Test
        public void test1() throws IOException {
            // 1.设置velocity的资源加载器
            Properties properties=new Properties();
            properties.put("file.resource.loader.class","org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
            // 2.初始化velocity引擎
            Velocity.init(properties);
            // 3.创建velocity容器
            VelocityContext context=new VelocityContext();
            context.put("name","张三");
            // 4.加载模板文件
            Template template = Velocity.getTemplate("templates\demo1.vm", "utf-8");
            // 5.合并数据到模板
            FileWriter fw=new FileWriter("D:\idea_code\cat-movie-main\cat-movie-main\movie-server\src\main\resources\static\demo1.html");
            template.merge(context,fw);
            // 6.释放资源
            fw.close();
        }

    执行单元测试,就可以看到static目录下生成了demo1.html,并且数据显示

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    hello,张三!
    </body>
    </html>

    5.基础语法

    5.1 VTL介绍

    Velocity Template Language(VTL),是velocity中提供的一种模板语言,旨在提供最简单和最干净的方法来将动态内容合并到网页中,简单来说VTL可以将程序的动态数展示到网页中。

    VTL语法分为四大类:注释、非解析内容、引用和指令

    5.2 注释

    注释的内容不会被输出

    1.单行注释

    ## 行注释内容

    2.多行注释

    #*
    *多行注释1
    *多行注释2
    *#

    3.文档注释

    #**
    *文档注释
    *
    *#

    5.3 非解析内容

    非解析内容会原样输出

    #[[
    非解析内容${name}
    ]]#

    5.4 引用

    5.4.1 变量引入

    引用语法就是对引擎上下文对象中的属性进行操作,语法方面分为常规语法($属性)和正规语法(${属性})

    $变量名,若上下文中没有对应的变量,则输出字符串$变量名

    ${变量名},若上下文中没有对应的变量,则输出字符串${变量名}

    $!变量名,若上下文中没有对应的变量,则输出空字符串""

    $!{变量名},若上下文中没有对应的变量,则输出空字符串""

    5.4.2 属性引用

    $变量名.属性,若上下文中没有对应的变量,则输出字符串$变量名.属性

    ${变量名.属性},若上下文中没有对应的变量,则输出字符串${变量名.属性}

    $!变量名.属性,若上下文中没有对应的变量,则输出空字符串""

    $!{变量名.属性},若上下文中没有对应的变量,则输出空字符串""

    5.4.3 方法引用

    $变量名.方法([入参1[,入参2]*]?),常规写法

    ${变量名.方法([入参1[,入参2]*]?)},正规写法

    $!变量名.方法([入参1[,入参2]*]?),常规写法

    $!{变量名.方法([入参1[,入参2]*]?)},正规写法

    5.5 指令

    #set

    作用:在页面中声明变量

    语法:#set($变量=值)

    #set($number=10)
    #set($str="hello world $number")
    
    ${str}

    #if/#elseif/#else

    作用:进行逻辑判断

    语法:

    #if(判断条件)
    ……
    #elseif(判断条件)
    ……
    #else
    ……
    #end

    具体实例

    #set($language="java")
    #if($language.equals("java"))
    java开发工程师
    #elseif($language.equals("php"))
    php开发工程师
    #else
    开发工程师
    #end

    #foreach($item in items)

    作用:遍历循环数组或者集合

    #foreach($item in $items)
         ……
        [break]
    #end

    $items:需要遍历的对象或者集合,如果items的类型为map集合,那么遍历的是map的value

    $item:变量名称,代表遍历的每一项

    #break:退出循环

    内置属性:$foreach.index:获取遍历的索引,从0开始,$foreach.count:获取遍历的次数,从1开始

    #foreach($item in $hobbies)
         $item
         #break
    #end

    #evaluate

    作用:动态计算,动态计算可以让我们在字符串中使用变量

    语法:#evaluate("计算语句")

    可以将服务端的代码直接解析

    #include

    作用:引入外部资源,引入的资源不会被引擎解析

    语法:#include(resources)

    resources可以为单引号或者双引号的字符串,也可以为$变量,内容为外部资源路径

    注意:路径如果为相对路径,则以引擎配置的文件加载器加载路径作为参考

    #parse

    作用:引入外部资源,引入的资源将会被引擎解析

    语法:#parse(resources)

    注意:路径如果为相对路径,则以引擎配置的文件加载器加载路径作为参考

    #define

    作用:定义重用模块

    语法:

    #define($模块名称)
       模块内容
    #end

    使用的时候直接  $模块名称

    宏指令

    作用:定义重用模块(可带参数)

    语法:

    定义语法:

    #macro(宏名 [$arg]?)
        ……
    #end

    调用语法:

    #宏名([$arg]?)

    实例:

    #macro(table $hobbies)
        #foreach($item in $hobbies)
             $item
        #end
    #end
    
    #table($hobbies)

    6.生成代码

    6.1 定义模板

    创建controller模板 Controller.java.vm

    package ${package}.controller;
    
    import ${package}.entity.${className};
    import ${package}.entity.ResultData;
    import ${package}.service.${className}Service;
    import org.springframework.web.bind.annotation.*;
    
    import javax.annotation.Resource;
    import javax.servlet.http.HttpServletRequest;
    import java.util.List;
    
    
    @RestController
    @RequestMapping("/${classname}")
    public class ${className}Controller {
    
        @Resource
        private ${className}Service ${classname}Service;
    
        /**
         * 查询列表
         *
         * @param name
         * @param addr
         * @return
         */
        @GetMapping("/list")
        public ResultData getList(String name, String addr, Integer page, Integer limit, HttpServletRequest r ) {
            return ${classname}Service.getList(name, addr, page, limit);
        }
    
        /**
         * 根据电影名称查询影院信息
         *
         * @param name
         * @return
         */
        @GetMapping("/index")
        public ResultData getIndexList(String name) {
            List<${className}> list = ${classname}Service.getIndexList(name);
            return new ResultData(true, "查询成功", list);
        }
    
        /**
         * 修改信息
         *
         * @param ${classname}
         * @return
         */
        @PostMapping("/edit")
        public ResultData updateInfo(@RequestBody ${className} ${classname}) {
            int count = ${classname}Service.updateInfo(${classname});
            if (count == 0) {
                return new ResultData(false, "操作失败");
            } else {
                return new ResultData(true, "操作成功");
            }
        }
    
        /**
         * 添加信息
         *
         * @param pojo
         * @return
         */
        @PostMapping("/add")
        public ResultData addInfo(@RequestBody ${className} ${classname}) {
            int count = ${classname}Service.addInfo(${classname});
            if (count == 0) {
                return new ResultData(false, "操作失败");
            } else {
                return new ResultData(true, "操作成功");
            }
        }
    
        /**
         * 根据id删除信息
         *
         * @param ids
         * @return
         */
        @PostMapping("/del")
        public ResultData deleteById(@RequestParam("ids") List<Integer> ids) {
            ${classname}Service.deleteById(ids);
            return new ResultData(true, "操作成功");
        }
    
    }
    View Code

    创建service模板 Service.java.vm

    package ${package}.service;
    
    import ${package}.entity.${className};
    import ${package}.entity.ResultData;
    
    import java.util.List;
    
    public interface ${className}Service {
        ResultData getList(String name, String addr, Integer page, Integer limit);
    
        int updateInfo(${className} ${classname});
    
        int addInfo(${className} ${classname});
    
        void deleteById(List<Integer> ids);
    
        List<${className}> getIndexList(String name);
    }
    View Code

    创建serviceImpl模板 ServiceImpl.java.vm

    package ${package}.service.impl;
    
    import cn.hutool.core.util.StrUtil;
    import com.github.pagehelper.PageHelper;
    import com.github.pagehelper.PageInfo;
    import ${package}.dao.${className}Dao;
    import ${package}.entity.${className};
    import ${package}.entity.ResultData;
    import ${package}.service.${className}Service;
    import org.springframework.stereotype.Service;
    import tk.mybatis.mapper.entity.Example;
    
    import javax.annotation.Resource;
    import java.util.List;
    
    @Service
    public class ${className}ServiceImpl implements ${className}Service {
    
        @Resource
        private ${className}Dao ${classname}Dao;
    
        @Override
        public ResultData getList(String name, String addr, Integer page, Integer limit) {
            if (page != null && limit != null) {
                PageHelper.startPage(page, limit);
            }
            Example example = new Example(${className}.class);
            Example.Criteria criteria = example.createCriteria();
            if (StrUtil.isNotBlank(name)) {
                criteria.andLike("name", "%" + name + "%");
            }
            if (StrUtil.isNotBlank(addr)) {
                criteria.andLike("addr", "%" + addr + "%");
            }
            List<${className}> list = ${classname}Dao.selectByExample(example);
            // 是否分页查询
            if (page != null && limit != null) {
                PageInfo<${className}> pageInfo = new PageInfo(list);
                return new ResultData(true, "查询成功", pageInfo.getList(), pageInfo.getTotal());
            } else {
                return new ResultData(true, "查询成功", list);
            }
        }
    
        @Override
        public int updateInfo(${className} ${classname}) {
            return ${classname}Dao.updateByPrimaryKeySelective(${classname});
        }
    
        @Override
        public int addInfo(${className} ${classname}) {
            return ${classname}Dao.insertSelective(${classname});
        }
    
        @Override
        public void deleteById(List<Integer> ids) {
            if (ids != null && ids.size() > 0) {
                ids.stream().forEach(item -> ${classname}Dao.deleteByPrimaryKey(item));
            }
        }
    
        @Override
        public List<${className}> getIndexList(String name) {
            return ${classname}Dao.getIndexList(name);
        }
    }
    View Code

    创建dao模板 Dao.java.vm

    package ${package}.dao;
    
    
    import ${package}.entity.${className};
    import tk.mybatis.mapper.common.Mapper;
    
    import java.util.List;
    
    public interface ${className}Dao extends Mapper<${className}> {
        List<${className}> getIndexList(String name);
    }
    View Code

    6.2 编写工具类

    编写生成Java文件工具类

    package com.zxh.movieserver.util;
    
    import org.apache.commons.io.IOUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.velocity.Template;
    import org.apache.velocity.VelocityContext;
    import org.apache.velocity.app.Velocity;
    
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.StringWriter;
    import java.util.List;
    import java.util.Map;
    import java.util.Properties;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipOutputStream;
    
    /**
     * @Author Eric
     * @Date 5/26/2021 5:12 PM
     */
    public class GenUtils {
        /**
         * 生成Java代码
         * @param data 生成到模板中的数据
         * @param templates 模板名称
         * @param
         */
        public static void generatorCode(Map<String,Object> data, List<String> templates, File file){
            // 1.设置velocity的资源加载器
            Properties properties=new Properties();
            properties.put("file.resource.loader.class","org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
            // 2.初始化velocity引擎
            Velocity.init(properties);
            // 3.创建velocity容器
            VelocityContext context=new VelocityContext(data);
            // 4.加载模板文件
            //遍历模板列表,获取每一个模板
            for (String template : templates) {
                Template tpl = Velocity.getTemplate(template, "utf-8");
    //            StringWriter sw=new StringWriter();
    //            // 5.合并数据到模板
    //            tpl.merge(context,sw);
    
                String fileName = genFileName(template, data.get("className").toString(), data.get("package").toString());
                try {
    
                    FileWriter fileWriter=new FileWriter(file+File.separator+fileName);
                    tpl.merge(context,fileWriter);
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
    //            try {
    //                zip.putNextEntry(new ZipEntry(fileName));
    //                IOUtils.write(sw.toString(),zip,"UTF-8");
    //                IOUtils.closeQuietly(sw);
    //                zip.flush();
    //                zip.closeEntry();
    //            } catch (IOException e) {
    //                e.printStackTrace();
    //            }
            }
        }
        /**
         * 根据模板名称,类名称,包名称拼接一个完整的文件路径和名称
         * @param template 模板名称
         * @param className 类名称
         * @param packageName 包名称
         * @return
         */
        public static String genFileName(String template,String className,String packageName){
            String packagePath="main"+ File.separator+"java"+File.separator;
            if(StringUtils.isNotEmpty(packageName)){
                packagePath+=packageName.replace(".",File.separator)+File.separator;
            }
            if(template.contains("Controller.java.vm")){
                return packagePath+"controller"+File.separator+className+"Controller.java";
            }
            if(template.contains("Service.java.vm")){
                return packagePath+"service"+File.separator+className+"Service.java";
            }
            if(template.contains("ServiceImpl.java.vm")){
                return packagePath+"service"+File.separator+"impl"+File.separator+className+"ServiceImpl.java";
            }
            if(template.contains("Dao.java.vm")){
                return packagePath+"dao"+File.separator+className+"Dao.java";
            }
            return null;
        }
    
    }
    View Code

    6.3 单元测试

    运行测试类就可以生成相关代码

    package com.zxh.movieserver;
    
    import com.zxh.movieserver.util.GenUtils;
    import org.junit.jupiter.api.Test;
    
    import java.awt.*;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.zip.ZipOutputStream;
    
    /**
     * @Author Eric
     * @Date 5/26/2021 5:52 PM
     */
    public class Test4 {
    
        @Test
        public void test1() throws FileNotFoundException {
            Map<String,Object> map=new HashMap<>();
            map.put("package","com.zxh.movieserver");
            map.put("className","Account");
            map.put("classname","account");
            //构建模板列表
            List<String> list=new ArrayList<>();
            list.add("templates/Controller.java.vm");
            list.add("templates/Service.java.vm");
            list.add("templates/ServiceImpl.java.vm");
            list.add("templates/Dao.java.vm");
    
            File file=new File("D:\idea_code\cat-movie-main\cat-movie-main\movie-server\src\");
    //        FileOutputStream fileOutputStream=new FileOutputStream(file);
    //        ZipOutputStream zipOutputStream=new ZipOutputStream(fileOutputStream);
            GenUtils.generatorCode(map,list,file);
        }
    }
    View Code

    一点点学习,一丝丝进步。不懈怠,才不会被时代所淘汰!

  • 相关阅读:
    UVA 10003:Cutting Sticks 区间DP
    UVAlive 10154:Dire Wolf 区间DP
    HDU 5071:Chat(2014 Asia AnShan Regional Contest)
    HDU 5074:Hatsune Miku(2014 Asia AnShan Regional Contest)
    android 代码混淆及问题大集锦
    android调试bug集锦 onActivityResult立即返回,并且被CANCEL
    开启g++ 编辑器 c++11特性
    解析最简单的验证码
    将图片文件转换为.py文件
    使用pyinstaller 2.1将python打包并添加版本信息和图标
  • 原文地址:https://www.cnblogs.com/fqh2020/p/14812817.html
Copyright © 2020-2023  润新知