Java 如何使用Velocity引擎生成代码
作者:虚怀若谷 发布时间:2023-10-19 23:15:34
标签:Java,Velocity,代码生成
目录
原理
实战
原理
其原理如图:
1.配置数据源信息(包括表名)
2.读取数据表字段信息:列名、类型、字段注释、表注释
3.编写代码模板,并将该模板加载到内存
4.根据模板所需,组装Velocity引擎渲染所需字段Map
5.创建Velocity上下文,将代码模板和替换字段传入
6.velocity上下文创建引擎,执行merge合并替换并将最终代码写入文件
实战
1.通过maven构建项目,引入依赖:
<dependency>
<artifactId>velocity</artifactId>
<groupId>org.apache.velocity</groupId>
<exclusions>
<exclusion>
<artifactId>commons-collections</artifactId>
<groupId>commons-collections</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
</dependency>
2.在resources/templates/codegenerator目录下面编写代码模板:
VO:
package ${basePackage}.module.${modulePackage}.domain.vo;
import lombok.Data;
#foreach ($dtoImport in $dtoImports)
$dtoImport
#end
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
/**
* [ ${tableDesc} ]
*
* @author ${author}
* @version 1.0
* @company ${company}
* @copyright (c) ${company}Inc. All rights reserved.
* @date ${date}
* @since JDK1.8
*/
@Data
public class ${moduleClass}VO {
#foreach ($column in $columnList)
#if($column.fieldType == 'Date')
@ApiModelProperty("${column.columnDesc}")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private $column.fieldType $column.fieldName;
#else
@ApiModelProperty("${column.columnDesc}")
private $column.fieldType $column.fieldName;
#end
#end
}
SERVICE:
package ${basePackage}.module.${modulePackage}.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import ${basePackage}.common.domain.PageResultDTO;
import ${basePackage}.common.domain.ResponseDTO;
import ${basePackage}.module.${modulePackage}.dao.${moduleClass}Dao;
import ${basePackage}.module.${modulePackage}.domain.dto.${moduleClass}AddDTO;
import ${basePackage}.module.${modulePackage}.domain.dto.${moduleClass}UpdateDTO;
import ${basePackage}.module.${modulePackage}.domain.dto.${moduleClass}QueryDTO;
import ${basePackage}.module.${modulePackage}.domain.entity.${moduleClass}Entity;
import ${basePackage}.module.${modulePackage}.domain.vo.${moduleClass}VO;
import ${basePackage}.module.${modulePackage}.domain.vo.${moduleClass}ExcelVO;
import ${basePackage}.util.SmartPageUtil;
import ${basePackage}.util.SmartBeanUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* [ ${tableDesc} ]
*
* @author ${author}
* @version 1.0
* @company ${company}
* @copyright (c) ${company}Inc. All rights reserved.
* @date ${date}
* @since JDK1.8
*/
@Service
public class ${moduleClass}Service {
@Autowired
private ${moduleClass}Dao ${moduleVar}Dao;
/**
* 根据id查询
*/
public ${moduleClass}Entity getById(Long id){
return ${moduleVar}Dao.selectById(id);
}
/**
* 分页查询
* @author ${author}
* @date ${date}
*/
public ResponseDTO<PageResultDTO<${moduleClass}VO>> queryByPage(${moduleClass}QueryDTO queryDTO) {
Page page = SmartPageUtil.convert2QueryPage(queryDTO);
IPage<${moduleClass}VO> voList = ${moduleVar}Dao.queryByPage(page, queryDTO);
PageResultDTO<${moduleClass}VO> pageResultDTO = SmartPageUtil.convert2PageResult(voList);
return ResponseDTO.succData(pageResultDTO);
}
/**
* 添加
* @author ${author}
* @date ${date}
*/
public ResponseDTO<String> add(${moduleClass}AddDTO addDTO) {
${moduleClass}Entity entity = SmartBeanUtil.copy(addDTO, ${moduleClass}Entity.class);
${moduleVar}Dao.insert(entity);
return ResponseDTO.succ();
}
/**
* 编辑
* @author ${author}
* @date ${date}
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> update(${moduleClass}UpdateDTO updateDTO) {
${moduleClass}Entity entity = SmartBeanUtil.copy(updateDTO, ${moduleClass}Entity.class);
${moduleVar}Dao.updateById(entity);
return ResponseDTO.succ();
}
/**
* 删除
* @author ${author}
* @date ${date}
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> deleteByIds(List<Long> idList) {
${moduleVar}Dao.deleteByIdList(idList);
return ResponseDTO.succ();
}
/**
* 查询全部导出对象
* @author ${author}
* @date ${date}
*/
public List<${moduleClass}ExcelVO> queryAllExportData(${moduleClass}QueryDTO queryDTO) {
return ${moduleVar}Dao.queryAllExportData( queryDTO);
}
/**
* 批量查询导出对象
* @author ${author}
* @date ${date}
*/
public List<${moduleClass}ExcelVO> queryBatchExportData(List<Long> idList) {
return ${moduleVar}Dao.queryBatchExportData(idList);
}
}
Mapper:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${basePackage}.module.${modulePackage}.dao.${moduleClass}Dao">
<resultMap id="${moduleClass}VO" type="${basePackage}.module.${modulePackage}.domain.vo.${moduleClass}VO"></resultMap>
<resultMap id="${moduleClass}ExcelVO" type="${basePackage}.module.${modulePackage}.domain.vo.${moduleClass}ExcelVO"></resultMap>
<select id="queryByPage" resultMap="${moduleClass}VO">
select
#foreach($column in $columnList)
#if($velocityCount != $columnList.size())
$column.columnName,
#else
$column.columnName
#end
#end
from ${tableName}
<where>
#foreach($queryField in $queryFieldList)
#if ($queryField.sqlOperate == 'like')
<if test="queryDTO.${queryField.fieldName} != null and queryDTO.${queryField.fieldName} != ''">
AND INSTR($queryField.columnName,#{queryDTO.$queryField.fieldName})
</if>
#end
#if ($queryField.sqlOperate == 'equals')
#if ($queryField.fieldType == 'String')
<if test="queryDTO.${queryField.fieldName} != null and queryDTO.${queryField.fieldName} != ''">
AND $queryField.columnName = #{queryDTO.$queryField.fieldName}
</if>
#else
<if test="queryDTO.${queryField.fieldName} != null">
AND $queryField.columnName = #{queryDTO.$queryField.fieldName}
</if>
#end
#end
#if ($queryField.sqlOperate == 'in')
<if test="queryDTO.${queryField.fieldName}List !=null and queryDTO.${queryField.fieldName}List.size() > 0">
and $queryField.columnName in
<foreach collection="queryDTO.${queryField.fieldName}List" open="(" index="index" separator="," close=")" item="item">
#{item}
</foreach>
</if>
#end
#end
<if test="queryDTO.createTimeBegin != null ">
AND create_time >= #{queryDTO.createTimeBegin}
</if>
<if test="queryDTO.createTimeEnd != null ">
AND create_time <= #{queryDTO.createTimeEnd}
</if>
<if test="queryDTO.updateTimeBegin != null ">
AND update_time >= #{queryDTO.updateTimeBegin}
</if>
<if test="queryDTO.updateTimeEnd != null ">
AND update_time <= #{queryDTO.updateTimeEnd}
</if>
</where>
</select>
<select id="queryAllExportData" resultMap="${moduleClass}ExcelVO">
select
#foreach($column in $columnList)
#if($velocityCount != $columnList.size())
$column.columnName,
#else
$column.columnName
#end
#end
from ${tableName}
<where>
#foreach($queryField in $queryFieldList)
#if ($queryField.sqlOperate == 'like')
<if test="queryDTO.${queryField.fieldName} != null and queryDTO.${queryField.fieldName} != ''">
AND INSTR($queryField.columnName,#{queryDTO.$queryField.fieldName})
</if>
#end
#if ($queryField.sqlOperate == 'equals')
#if ($queryField.fieldType == 'String')
<if test="queryDTO.${queryField.fieldName} != null and queryDTO.${queryField.fieldName} != ''">
AND $queryField.columnName = #{queryDTO.$queryField.fieldName}
</if>
#else
<if test="queryDTO.${queryField.fieldName} != null">
AND $queryField.columnName = #{queryDTO.$queryField.fieldName}
</if>
#end
#end
#if ($queryField.sqlOperate == 'in')
<if test="queryDTO.${queryField.fieldName}List !=null and queryDTO.${queryField.fieldName}List.size() > 0">
and $queryField.columnName in
<foreach collection="queryDTO.${queryField.fieldName}List" open="(" index="index" separator="," close=")" item="item">
#{item}
</foreach>
</if>
#end
#end
<if test="queryDTO.createTimeBegin != null ">
AND create_time >= #{queryDTO.createTimeBegin}
</if>
<if test="queryDTO.createTimeEnd != null ">
AND create_time <= #{queryDTO.createTimeEnd}
</if>
<if test="queryDTO.updateTimeBegin != null ">
AND update_time >= #{queryDTO.updateTimeBegin}
</if>
<if test="queryDTO.updateTimeEnd != null ">
AND update_time <= #{queryDTO.updateTimeEnd}
</if>
</where>
</select>
<select id="queryBatchExportData" resultMap="${moduleClass}ExcelVO">
select
#foreach($column in $columnList)
#if($velocityCount != $columnList.size())
$column.columnName,
#else
$column.columnName
#end
#end
from ${tableName}
where id in
<foreach collection="idList" open="(" close=")" separator="," item="item">
#{item}
</foreach>
</select>
<delete id="deleteById">
delete from ${tableName} where id = #{id}
</delete>
<delete id="deleteByIdList">
delete from ${tableName} where id in
<foreach collection="idList" open="(" close=")" separator="," item="item">
#{item}
</foreach>
</delete>
</mapper>
3.查询表信息:
<select id="selectTableDesc" resultType="String">
select
table_comment
from information_schema.tables
where table_schema = (select database()) and table_name = #{tableName}
</select>
<select id="selectTableColumn" resultMap="ColumnDTO">
select
column_name as columnName,
data_type as columnType,
column_comment as columnDesc
from information_schema.columns
where table_schema = (select database()) AND table_name = #{tableName} order by ordinal_position
</select>
4.加载模板、组装数据
public Map<String, String> codeTemplates(String moduleClass, String basePackage, String modulePackage) {
String basePath = basePackage.replaceAll("\\.", File.separator );
String modulePath = modulePackage.replaceAll("\\.", File.separator );
String javaPackagePath = "java" + File.separator + basePath + File.separator + modulePath + File.separator;
String xmlPackagePath = "mapper" + File.separator + modulePath + File.separator;
String frontPackagePath = "web" + File.separator;
Map<String, String> templateMap = new HashMap<>();
//后端
templateMap.put("templates/codegenerator/java/Controller.java.vm", javaPackagePath + "controller" + File.separator + moduleClass + "Controller.java" );
templateMap.put("templates/codegenerator/java/Dao.java.vm", javaPackagePath + "dao" + File.separator + moduleClass + "Dao.java" );
templateMap.put("templates/codegenerator/java/Dao.xml.vm", xmlPackagePath + moduleClass + "Mapper.xml" );
templateMap.put("templates/codegenerator/java/AddDTO.java.vm", javaPackagePath + "domain" + File.separator + "dto" + File.separator + moduleClass + "AddDTO.java" );
templateMap.put("templates/codegenerator/java/UpdateDTO.java.vm", javaPackagePath + "domain" + File.separator + "dto" + File.separator + moduleClass + "UpdateDTO.java" );
templateMap.put("templates/codegenerator/java/Entity.java.vm", javaPackagePath + "domain" + File.separator + "entity" + File.separator + moduleClass + "Entity.java" );
templateMap.put("templates/codegenerator/java/VO.java.vm", javaPackagePath + "domain" + File.separator + "vo" + File.separator + moduleClass + "VO.java" );
templateMap.put("templates/codegenerator/java/ExcelVO.java.vm", javaPackagePath + "domain" + File.separator + "vo" + File.separator + moduleClass + "ExcelVO.java" );
templateMap.put("templates/codegenerator/java/QueryDTO.java.vm", javaPackagePath + "domain" + File.separator + "dto" + File.separator + moduleClass + "QueryDTO.java" );
templateMap.put("templates/codegenerator/java/Service.java.vm", javaPackagePath + "service" + File.separator + moduleClass + "Service.java" );
//前端
String webPackageName = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, moduleClass).replaceAll("_", "-" );
templateMap.put("templates/codegenerator/web/Api.js.vm", frontPackagePath + "api" + File.separator + webPackageName + ".js" );
templateMap.put("templates/codegenerator/web/Router.js.vm", frontPackagePath + "router" + File.separator + webPackageName + ".js" );
templateMap.put("templates/codegenerator/web/List.vue.vm", frontPackagePath + webPackageName + File.separator + webPackageName + "-list.vue" );
templateMap.put("templates/codegenerator/web/ListForm.vue.vm", frontPackagePath + webPackageName + File.separator + "components" + File.separator + webPackageName + "-list-form.vue" );
return templateMap;
}
Properties p = new Properties();
p.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
p.put("directive.foreach.counter.name", "velocityCount");
p.put("directive.foreach.counter.initial.value", "1");
Velocity.init(p);
Map<String, Object> map = new HashMap<>();
map.put("company", codeGenerator.getCompany());
map.put("tableName", codeGenerator.getTableName());
map.put("basePackage", basePackage);
map.put("modulePackage", modulePackage);
map.put("moduleClass", moduleClass);
map.put("tableDesc", tableDesc);
map.put("author", author);
map.put("date", date);
map.put("moduleVar", moduleVar);
map.put("columnList", columnList);
map.put("queryFieldList", queryFieldList);
map.put("queryImports", queryImports);
map.put("dtoImports", dtoImports);
map.put("entityImports", entityImports);
map.put("webModuleName", CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, moduleClass).replaceAll("_", "-"));
map.put("upperCamel", CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, moduleClass));
//前端的变量
map.put("ViewUIMessage", "$Message");
map.put("VueRefs", "$refs");
5.创建Velocity上下文,生成代码
VelocityContext context = new VelocityContext(map);
private void codeGenerator(VelocityContext context, Map<String, String> codeTemplates) throws Exception {
String projectPath = getOutputDir();
Velocity.setProperty("input.encoding", "UTF-8");
Velocity.setProperty("output.encoding", "UTF-8");
for (Entry<String, String> entry : codeTemplates.entrySet()) {
String template = entry.getKey();
String filePath = projectPath + entry.getValue();
String fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
String fileDir = filePath.replace(fileName, "");
File directory = new File(fileDir);
if (!directory.exists()) {
directory.mkdirs();
}
FileWriter writer;
try {
writer = new FileWriter(filePath);
Template tpl = Velocity.getTemplate(template, "UTF-8");
tpl.merge(context, writer);
writer.flush();
writer.close();
} catch (Exception e) {
log.error("", e);
}
}
}
来源:https://www.zhoujunwen.com/2021/via-velocity-engine-generate-code/
0
投稿
猜你喜欢
- 前两天给同事做 code review,感觉自己对 Java 的 Generics 掌握得不够好,便拿出 《Effective Java》1
- 1.问题产生情况我遇到这个问题是做微信开发的时候有些有用的头像用了微信的emoji表情,然而我的mysql数据库用的编码是utf8_gene
- 引言在上一篇文章中# Android进阶宝典 -- KOOM线上APM监控最全剖析,我详细介绍了对于线上App内存监控的方案策略,其实除了内
- 本文实例为大家分享了java使用字符画一个海绵宝宝的具体代码,供大家参考,具体内容如下用字符画一个海绵宝宝用" &ldqu
- 前言本文主要给大家介绍了关于JDK8新增的原子性操作类LongAdder的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的
- 1.导入 EasyExcel Maven包<!--easyexcel 导出excel依赖--><dependency>
- Flyweight定义:避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类)。为什么使用共享模式/享元模式面向对象语言的
- 前言今天刷个题,遇到一个很有趣的问题,关于Comparator的使用,感觉也是一个关于写代码的一些小细节的问题关于ComparatorCom
- 一、递归的思路一个方法在执行时,调用自身被称为“递归”。递归相当于数学归纳法,有一个起始条件,有一个递推公式。递归可以分为:单路递归和多路递
- 今天,给大家分享一个Java后端利用Phantomjs实现生成图片的功能,同学们使用的时候,可以参考下!PhantomJS简介首先,什么是P
- 本文主要记录JAVA中对象的初始化过程,包括实例变量的初始化和类变量的初始化以及final关键字对初始化的影响。另外,还讨论了由于继承原因,
- 持久化类Hibernate的整个概念是采取从Java类属性的值,并将持久到数据库表。一个映射文件Hibernate的帮助确定如何从拉动类的值
- 首先是网页部分,upload_file.jsp<%@ page language="java" import=&q
- 本文实例讲述了Android获取SD卡及手机ROM容量的方法。分享给大家供大家参考,具体如下:这里通过一个简单的小例子,来获取SD卡的容量和
- 如果 d:\upload\file\ 文件夹不存在,会报错String strPath = "d:\\upload\\file\\
- 最近在做关于PDF文档添加水印的功能,折腾了好久,终于好了。以下做个记录:首先会用到iTextSharp组件,大家可以去官网下载,同时我也会
- 本次内容主要介绍基于Ehcache 3.0来快速实现Spring Boot应用程序的数据缓存功能。在Spring Boot应用程序中,我们可
- 现在软件或者网页的并发量越来越大了,大量请求直接操作数据库会对数据库造成很大的压力,处理大量连接和请求就会需要很长时间,但是实际中百分之80
- 概述Spring针对Java Transaction API (JTA)、JDBC、Hibernate和Java Persistence A
- 接口隔离原则(ISP)定义:使用多个专门的接口比使用单一的总接口要好。即不要把鸡蛋都放到一个篮子里。好处:比较灵活、方便,不想实现的或不用实