实战:一键生成前后端代码,Mybatis-Plus代码生成器让我舒服了

前言

在日常的软件开发中,程序员往往需要花费大量的时间写CRUD,不仅枯燥效率低,而且每个人的代码风格不统一。MyBatis-Plus 代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块及前端页面的代码,极大的提升了开发效率。

项目介绍

本项目将以springboot用演示,前端使用freemaker,数据库持久层用mybatis(考虑到mybatis的使用还是最普遍的,就没有用jpa和mybatisplus),通过Velocity模板引擎配置各模块的文件模板,通过mybatis-plus代码生成器连接mysql,用商品表为例生成各模块的代码和前端页面。(本项目只演示分页查询和导出功能)。

本项目所有代码和脚本都能都文末找到地址。

实战

数据库脚本

创建一张商品表test_goods

CREATE TABLE `test_goods` (
`id` bigint(20) DEFAULT NULL COMMENT 'id',
`goods_sn` varchar(45) DEFAULT NULL COMMENT '商品编码',
`name` varchar(255) DEFAULT NULL COMMENT '商品名称',
`title` varchar(80) DEFAULT NULL COMMENT '标题',
`price` decimal(10,2) DEFAULT NULL COMMENT '售价',
`status` int(2) DEFAULT NULL COMMENT '商品状态',
`sale_count` int(11) DEFAULT NULL COMMENT '销量',
`create_date` datetime DEFAULT NULL COMMENT '创建时间',
`modify_date` datetime DEFAULT NULL COMMENT '修改时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8

maven依赖

  <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency> <dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>2.1.4</version>
</dependency> <!-- aspectj -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<scope>provided</scope>
</dependency>
<!--es--> <!-- lombok 简化get/set 方法 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
<scope>provided</scope>
</dependency> <dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--csv导出用到-->
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>3.8</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
</dependencies>

配置文件

mybatis:
mapper-locations: classpath:mybatis/*Mapper.xml
type-aliases-package: com.lzn.mybatisplus.codegenerator.entity spring:
datasource:
username: root
password: 123qwe
url: jdbc:mysql://192.168.0.1:3306/myProject?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
driver-class-name: com.mysql.jdbc.Driver
redis:
host: 192.168.0.1
password: 1234qwer
port: 6379
freemarker:
template-loader-path: classpath:/templates/pages/
cache: false
charset: UTF-8
check-template-location: true
content-type: text/html
expose-request-attributes: true
expose-session-attributes: true
suffix: .ftl

模板文件

本项目中,所有模块的文件都是用Velocity模板引擎生成,这里简单介绍下Velocity的语法,在Velocity中用${}表示变量,例如:${table.entityName} 表示实体名,${field.name} 表示字段名,我们在AutoGenerator代码生成器里定义的全局变量 ${author}、${date} 表示作者,日期等。在Velocity中用#表示语法,例如 #foreach($field in ${table.fields}) #end遍历表字段。下面演示几个类、前端文件、xml文件的模板文件

实体类模板(entity.java.vm)

package ${package.Entity};

import java.math.BigDecimal;
import java.util.Date;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString; /**
* 数据库表名 ${table.name}
*
* @author ${author}
* @date ${date}
*/
@Getter
@Setter
@ToString
public class ${table.entityName} { #foreach($field in ${table.fields})
/**
* 数据库字段名 ${field.name} 类型 ${field.type}
*/
private ${field.propertyType} ${field.propertyName}; #end }

Controller模板(controller.java.vm)

package ${package.Controller};

import ${package.Entity}.${entity};
import ${package.Service}.${table.serviceName};
import com.lzn.mybatisplus.codegenerator.export.${table.entityName}VO;
import com.lzn.mybatisplus.codegenerator.export.${table.entityName}ExportService;
import com.lzn.mybatisplus.codegenerator.utils.entity.*;
import com.lzn.mybatisplus.codegenerator.utils.export.*;
import org.apache.commons.beanutils.ConvertUtils;
import com.lzn.mybatisplus.codegenerator.utils.ParameterUtil;
import com.lzn.mybatisplus.codegenerator.utils.entity.GridDataModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map; /**
* <p>
* ${tablecomment} 前端控制器
* </p>
*
* @author ${author}
* @since ${date}
*/
@Controller
@RequestMapping(value="/admin/${table.entityPath}")
public class ${table.controllerName}{
private static Logger logger = LoggerFactory.getLogger(${table.controllerName}.class); @Resource
private ${entity}Service ${table.entityPath}Service; @RequestMapping(value = "list", method = RequestMethod.GET)
public String list(Model model){
return "/admin/${cfg.pageDirName}/list";
} @RequestMapping(value = "searchList", method = RequestMethod.POST)
@ResponseBody
@ExportMethod(serviceClass = ${entity}ExportService.class, memo = "明细导出")
public String searchList(ServletRequest request,@ModelAttribute("page") OmuiPage page){
try {
Map<String,Object> searchParam = ParameterUtil.getParametersStartingWith(request, "filter_");
GridDataModel<${entity}VO> gd =${table.entityPath}Service.findByPage(searchParam, page);
return JsonMapper.nonDefaultMapper().toJson(gd);
} catch (Exception e) {
logger.error("查询出错了",e);
return JsonMapper.nonDefaultMapper().toJson(new Resp("false", e.getMessage()));
}
} }

Service类模板(service.java.vm)

package ${package.Service};

import org.springframework.stereotype.Service;
import com.lzn.mybatisplus.codegenerator.dao.${table.mapperName};
import com.lzn.mybatisplus.codegenerator.utils.entity.GridDataModel;
import com.lzn.mybatisplus.codegenerator.utils.entity.OmuiPage;
import com.lzn.mybatisplus.codegenerator.export.${table.entityName}VO; import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*; /**
* <p>
* $!{tablecomment} 服务类
* </p>
*
* @author ${author}
* @since ${date}
*/
@Service
public class ${table.serviceName} { @Resource
private ${table.mapperName} ${table.entityPath}Dao; /**
* 分页查询
* */
public GridDataModel<${table.entityName}VO> findByPage(Map<String, Object> searchParams, OmuiPage page){
GridDataModel<${table.entityName}VO> gm = new GridDataModel<${table.entityName}VO>();
searchParams.put("start", page.getStart());
searchParams.put("limit", page.getLimit());
long count = ${table.entityPath}Dao.countForPage(searchParams);
List<${table.entityName}VO> list = ${table.entityPath}Dao.listForPage(searchParams);
gm.setTotal(count);
gm.setRows(list);
return gm;
} }

Dao类模板(dao.java.vm)

package ${package.Mapper};

import com.lzn.mybatisplus.codegenerator.entity.${table.entityName};
import com.lzn.mybatisplus.codegenerator.export.${table.entityName}VO;
import java.util.List;
import java.util.Map; public interface ${table.mapperName} {
/**
* 根据主键删除数据库的记录, ${table.name}
*/
int deleteByPrimaryKey(Long id); /**
* 新写入数据库记录, ${table.name}
*/
int insert(${table.entityName} record); /**
* 根据指定主键获取一条数据库记录, ${table.name}
*/
${table.entityName} selectByPrimaryKey(Long id); /**
* 根据主键来更新符合条件的数据库记录, ${table.name}
*/
int updateByPrimaryKey(${table.entityName} record); /**
* 根据条件分页查询
* */
List<${table.entityName}VO> listForPage(Map<String,Object> searchMap); /**
* 根据条件分页查询(计数)
* */
long countForPage(Map<String,Object> searchMap); }

Mapper.xml模板(mapper.xml.vm)

<?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="${package.Mapper}.${table.mapperName}">
#if(${baseResultMap})
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="${package.Entity}.${entity}">
#foreach($field in ${table.fields})
#if(${field.keyFlag})##生成主键排在第一位
<id column="${field.name}" property="${field.propertyName}" />
#end
#end
#foreach($field in ${table.commonFields})##生成公共字段
<result column="${field.name}" property="${field.propertyName}" />
#end
#foreach($field in ${table.fields})
#if(!${field.keyFlag})##生成普通字段
<result column="${field.name}" property="${field.propertyName}" />
#end
#end
</resultMap>
#end #if(${baseColumnList})
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
#foreach($field in ${table.commonFields})
#if(${field.name} == ${field.propertyName})${field.name}#else${field.name} AS ${field.propertyName}#end,
#end
${table.fieldNames}
</sql>
#end <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
<!-- -->
delete from ${table.name}
where
#foreach($field in ${table.fields})
#if(${field.keyFlag})## 主键
${field.name} = #{ ${field.propertyName} }
#end
#end
</delete> <insert id="insert" parameterType="${package.Entity}.${entity}">
<!-- -->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
SELECT LAST_INSERT_ID()
</selectKey>
insert into ${table.name} (
#foreach($field in ${table.fields})
#if(!${field.keyFlag})##生成普通字段
${field.name}#if($foreach.hasNext),#end
#end
#end
)
values (
#foreach($field in ${table.fields})
#if(!${field.keyFlag})##生成普通字段
#{ ${field.propertyName}}#if($foreach.hasNext),#end
#end
#end
)
</insert> <update id="updateByPrimaryKey" parameterType="${package.Entity}.${entity}">
<!-- -->
update ${table.name}
set
#foreach($field in ${table.fields})
#if(!${field.keyFlag})##生成普通字段
${field.name} = #{ ${field.propertyName}} #if($foreach.hasNext),#end
#end
#end
where
#foreach($field in ${table.fields})
#if(${field.keyFlag})
id = #{ ${field.name} }
#end
#end
</update> <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
<!-- -->
select
<include refid="Base_Column_List" />
from ${table.name}
where id = #{ id }
</select> <select id="countForPage" parameterType="map" resultType="Long">
<!-- -->
select
count(*)
from
${table.name}
where 1=1
<if test="beginDate != null and beginDate != ''">
and create_date <![CDATA[>=]]> #{beginDate}
</if>
<if test="endDate != null and endDate != ''">
and create_date <![CDATA[<=]]> #{endDate}
</if>
</select> <select id="listForPage" parameterType="map" resultType="com.lzn.mybatisplus.codegenerator.export.${table.entityName}VO">
<!-- -->
select
<include refid="Base_Column_List" />
from
${table.name}
where 1=1
<if test="beginDate != null and beginDate != ''">
and create_date <![CDATA[>=]]> #{beginDate}
</if>
<if test="endDate != null and endDate != ''">
and create_date <![CDATA[<=]]> #{endDate}
</if>
limit #{start}, #{limit}
</select>
</mapper>

前端页面list.ftl模板(list.ftl.vm)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<#assign base=request.contextPath>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>$!{tablecomment}</title>
<link href="${base}/static/omui/css/elegant/om-all.css" rel="stylesheet" type="text/css" />
<link href="${base}/static/admin/css/admin.css" rel="stylesheet" type="text/css" /> <script type="text/javascript" src="${base}/static/js/jquery-1.7.1.js"></script>
<script type="text/javascript" src="${base}/static/js/HForm.js"></script>
<script type="text/javascript" src="${base}/static/My97DatePicker/WdatePicker.js"></script>
<script type="text/javascript" src="${base}/static/omui/js/operamasks-ui.min.js"></script>
<script type="text/javascript" src="${base}/static/omui/js/common.js"></script>
<script type="text/javascript" src="${base}/static/bui/js/common.js"></script>
<script type="text/javascript" src="${base}/static/admin/js/export.js"></script> <script type="text/javascript"> $().ready(function(){ //初始化控件
$("#search-panel").omPanel({
title : "条件搜索",collapsible:false
}); //搜索
$('#searchButton').bind('click', function(e) {
var data = $("#listForm").HForm('form2json');
$('#listGrid').omGrid({extraData:data});
}); $("#start-time").omCalendar();
$("#time-end").omCalendar(); $('#searchButton').omButton({
icons : {left : '${base}/static/omui/images/search.png'},width : 70
}); $(".input-select").change(function(){
$('#searchButton').click();
}); $('#buttonbar').omButtonbar({
btns : [{label:"导出Excel",
id:"addbutton" ,
icons : {left : '${base}/static/omui/images/export.png'},
onClick:function()
{
exportUtil({
title : "列表导出",
exportUrl : "${base}/admin/${table.entityPath}/searchList",
extraParam : $("#listForm").HForm('form2json')
});
}
}
]
}); //初始化列表
var height=$(document).height() -$('#search-panel').outerHeight()-$('#buttonbar').outerHeight()-40;
$('#listGrid').omGrid({
height:height,
limit:20,
method:'post',
singleSelect:false,
extraData:$("#listForm").HForm('form2json'),
dataSource : '${base}/admin/${table.entityPath}/searchList',
colModel : [
{header : 'ID', name : 'id', width : 30, align : 'left',sort:'serverSide'},
{header : '创建时间', name : 'createDate', width : 150, align : 'left',sort:'serverSide',renderer :dataFormat1},
{header : '修改时间', name : 'modifyDate', width : 150, align : 'left',sort:'serverSide',renderer :dataFormat1},
#foreach($field in ${table.fields}) #set($comment = "")
#set($type = "")
#set($isNullAble = true)
#set($defaultValue = false)
#set($listIsShow = true)
#set($listIsSearch = false) #foreach( $e in $field.comment.split(","))
#if( $foreach.count == 1 )
#set($comment = $e)
#elseif( $foreach.count == 2 )
#set($type = $e)
#elseif( $foreach.count == 3)
#if($e == "YES")
#set($isNullAble = true)
#else
#set($isNullAble = false)
#end
#elseif( $foreach.count == 4)
#if($e == "true")
#set($defaultValue = true)
#else
#set($defaultValue = false)
#end
#elseif( $foreach.count == 5)
#if($e == "true")
#set($listIsShow = true)
#else
#set($listIsShow = false)
#end
#elseif( $foreach.count == 6)
#if($e == "true")
#set($listIsSearch = true)
#else
#set($listIsSearch = false)
#end
#end
#end
{header : '#if("$!comment" != "")${comment}#end', name : '${field.propertyName}',width : 90, align : 'left',sort:'serverSide'#if($type == "timer"),renderer :dataFormat1 #end},
#end
],
rowDetailsProvider:function(rowData){
}
}); //初始化控件 end
function getIds(datas) {
var str = "";
for (var i = 0; i < datas.length; i++) {
str += datas[i].id + ",";
}
//去掉最后一个逗号(如果不需要去掉,就不用写)
if (str.length > 0) {
str = str.substr(0, str.length - 1);
}
return str;
} $('#searchButton').click();
}); </script>
</head>
<body > <div id="search-panel">
<form id="listForm">
<div>
<span class="label">状态:</span>
<select class="js-example-basic-single input-select" name="filter_EQS_status">
<option value="0" selected>待处理</option>
<option value="1">已处理</option>
<option value="">全部</option>
</select>
<span class="label">手机号:</span>
<input type="text" class="input-text" name="filter_LIKES_mobile" />
<span class="label">联系人:</span>
<input type="text" class="input-text" name="filter_LIKES_name" />
<span class="label">创建时间:</span>
<input id="start-time" style="width: 118px" name="filter_GTED_createDate"/>
-
<input id="time-end" style="width: 118px" name="filter_LTED_createDate"/>
<span id="searchButton">查询</span>
</div>
</form>
</div> <div id="buttonbar"></div><!-- 工具栏位置 -->
<table id="listGrid"></table> <!-- 主列表位置 --> </body>
</html>

代码生成器

package com.lzn.mybatisplus.codegenerator;

import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.DbType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; /**
* 辅助生产后台开发相关代码 开发时只在自己本地代码修改,不要提交
* 生成ddao service controller entity java代码 和前端 flt文件。
* 只演示list场景
*/
public class MpGenerator { //注意:开发时只在自己本地代码修改,不要提交、不要提交 不要提交
//第一步修改 javaSrcDir 修改成自己项目存放java源代码的根路径
static String javaSrcDir = "D:/Git_space/lunzijihua/codegenerator/src/main/java";
static String resourceDir = "D:/Git_space/lunzijihua/codegenerator/src/main/resources";
//第二步修改 pageRootDir 修改成你要开发的模块的名称 存放ftl文件的文件夹的根路径
static String pageRootDir ="D:/Git_space/lunzijihua/codegenerator/src/main/resources/templates/pages/"; //第三步修改 packageName 修改成你要开发的模块的名称 包名 要小写 生产的entity service dao action文件夹和java代码会在下面
static String packageName = "user";//模块文件夹包名称
//第四步修改 pageDirName 修改成你要开发的模块的名称 存放ftl文件的文件夹 要小写
static String pageDirName = "user";//模块页面文件夹名
//第五步骤 表的前缀 填写了 生成文件时会去除掉
static String tablePrefix="test_";
//第六步 数据库里面对应的表的全名
static String tableName="test_goods"; /**
* <p>
* 代码自动生成
* </p>
*/
public static void main(String[] args) { AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir(javaSrcDir);
gc.setFileOverride(true);
gc.setActiveRecord(true);// 不需要ActiveRecord特性的请改为false
gc.setEnableCache(false);// XML 二级缓存
gc.setBaseResultMap(true);// XML ResultMap
gc.setBaseColumnList(true);// XML columList
// .setKotlin(true) 是否生成 kotlin 代码
gc.setAuthor("liuzhinan"); // 自定义文件命名,注意 %s 会自动填充表实体属性!
gc.setMapperName("%sMybatisDao");
// gc.setXmlName("%sDao");
gc.setServiceName("%sService");
// gc.setServiceImplName("%sService");
// gc.setControllerName("%sAction");
mpg.setGlobalConfig(gc); // 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.MYSQL); dsc.setTypeConvert(new MySqlTypeConvert(){
// 自定义数据库表字段类型转换【可选】
@Override
public DbColumnType processTypeConvert(String fieldType) {
System.out.println("转换类型:" + fieldType);
// 注意!!processTypeConvert 存在默认类型转换,如果不是你要的效果请自定义返回、非如下直接返回。
return super.processTypeConvert(fieldType);
}
});
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("test");
dsc.setPassword("123456");
dsc.setUrl("jdbc:mysql://192.168.0.1:3306/myProject?useSSL=false");
mpg.setDataSource(dsc); // 策略配置
StrategyConfig strategy = new StrategyConfig();
// strategy.setCapitalMode(true);// 全局大写命名 ORACLE 注意
strategy.setTablePrefix(new String[] { tablePrefix });// 此处可以修改为您的表前缀
strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
strategy.setInclude(new String[] { tableName }); // 需要生成的表
// strategy.setExclude(new String[]{"test"}); // 排除生成的表
// 自定义实体父类
strategy.setSuperEntityClass("com.lzn.mybatisplus.codegenerator.entity.IdEntity");
// 自定义实体,公共字段
// strategy.setSuperEntityColumns(new String[] { "id", "create_date","modify_date" });
// 自定义 mapper 父类
// strategy.setSuperMapperClass("com.baomidou.demo.TestMapper");
// 自定义 service 父类
// strategy.setSuperServiceClass("com.baomidou.demo.TestService");
// 自定义 service 实现类父类
// strategy.setSuperServiceImplClass("com.baomidou.demo.TestServiceImpl");
// 自定义 controller 父类
// strategy.setSuperControllerClass("com.baomidou.demo.TestController");
// 【实体】是否生成字段常量(默认 false)
// public static final String ID = "test_id";
// strategy.setEntityColumnConstant(true);
// 【实体】是否为构建者模型(默认 false)
// public User setName(String name) {this.name = name; return this;}
// strategy.setEntityBuilderModel(true);
mpg.setStrategy(strategy); // 包配置
PackageConfig pc = new PackageConfig();
pc.setParent("com.lzn.mybatisplus.codegenerator");
pc.setModuleName(null);
pc.setMapper("dao");
pc.setEntity("entity");
pc.setService("service");
pc.setServiceImpl("service.impl");
pc.setController("controller");
mpg.setPackageInfo(pc); // 注入自定义配置,可以在 VM 中使用 cfg.abc 【可无】
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
map.put("pageDirName",pageDirName);
map.put("packageName",packageName);
this.setMap(map);
}
}; List<FileOutConfig> focList = new ArrayList<FileOutConfig>(); // cfg.setFileOutConfigList(focList);
// mpg.setCfg(cfg); //生成导出视图对象
focList.add(new FileOutConfig("/templates/vm/vo.java.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return javaSrcDir+"/com/lzn/mybatisplus/codegenerator/export/"+tableInfo.getEntityName()+"VO.java";
}
});
//生成excel导出的服务类,
focList.add(new FileOutConfig("/templates/vm/exportservice.java.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return javaSrcDir+"/com/lzn/mybatisplus/codegenerator/export/"+tableInfo.getEntityName()+"ExportService.java";
}
});
//生成mybatisDao文件到指定目录
focList.add(new FileOutConfig("/templates/vm/mybatisdao.java.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return javaSrcDir+"/com/lzn/mybatisplus/codegenerator/dao/"+tableInfo.getEntityName()+"MybatisDao.java";
}
}); //生成mapper文件到指定目录
focList.add(new FileOutConfig("/templates/vm/mapper.xml.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return resourceDir+"/mybatis/"+tableInfo.getEntityName()+"Mapper.xml";
}
}); // 自定义 xxList.ftl 生成
focList.add(new FileOutConfig("/templates/vm/list.ftl.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输入文件名称
return pageRootDir+pageDirName+"/list.ftl";
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg); // 关闭默认 xml 生成,调整生成 至 根目录
TemplateConfig tc = new TemplateConfig();
tc.setEntity("/templates/vm/entity.java.vm");
tc.setService("/templates/vm/service.java.vm");
tc.setServiceImpl(null);//设成null才会不生产
tc.setController("/templates/vm/controller.java.vm");
tc.setMapper(null);
tc.setXml(null);
mpg.setTemplate(tc); // 自定义模板配置,可以 copy 源码 mybatis-plus/src/main/resources/templates 下面内容修改,
// 放置自己项目的 src/main/resources/templates 目录下, 默认名称一下可以不配置,也可以自定义模板名称
// TemplateConfig tc = new TemplateConfig();
// tc.setController("...");
// tc.setEntity("...");
// tc.setMapper("...");
// tc.setXml("...");
// tc.setService("...");
// tc.setServiceImpl("...");
// 如上任何一个模块如果设置 空 OR Null 将不生成该模块。
// mpg.setTemplate(tc); // 执行生成
mpg.execute(); // 打印注入设置【可无】
System.err.println(mpg.getCfg().getMap().get("abc"));
} }

执行代码生成器的Main方法

执行代码后,在对应的目录自动生成了文件

启动项目

并访问列表页路径 http://localhost:8080/admin/goods/list

点击导出按钮(由于篇幅有限,导出的视图对象,导出service类和aop切面实现本文没有阐述,各位可自行下载代码查看)

总结

本文为项目自动生成前后端代码提供了思路:我们可以为项目的增删改查业务编写一套规范的代码,以此编写代码模板,后续通过代码生成器,通过数据库的一张表可快速生成前后端代码,提高项目组的开发效率。

代码

https://github.com/pengziliu/GitHub-code-practice

实战:一键生成前后端代码,Mybatis-Plus代码生成器让我舒服了的更多相关文章

  1. [Java 开源项目]一款无需写任何代码,即可一键生成前后端代码的工具

    作者:HelloGitHub-小鱼干 JeecgBoot 是一款基于代码生成器的低代码开发平台,零代码开发.JeecgBoot 采用开发模式:Online Coding 模式-> 代码生成器模式 ...

  2. 基于数据库的代码自动生成工具,生成JavaBean、生成数据库文档、生成前后端代码等(v6.0.0版)

    TableGo v6.0.0 版震撼发布,此次版本更新如下: 1.UI界面大改版,组件大调整,提升界面功能的可扩展性. 2.新增BeautyEye主题,界面更加清新美观,也可以通过配置切换到原生Jav ...

  3. 记node前后端代码共用的一次坑

    项目背景 nodejs项目,webpack打包,用axios请求,Promise封装,nunjucks模板引擎: 之前已将nunjucks模板通过webpack打包策略,做成前后端共用: 目前需要将网 ...

  4. SpringCloud微服务实战——搭建企业级开发框架(三十一):自定义MybatisPlus代码生成器实现前后端代码自动生成

      理想的情况下,代码生成可以节省很多重复且没有技术含量的工作量,并且代码生成可以按照统一的代码规范和格式来生成代码,给日常的代码开发提供很大的帮助.但是,代码生成也有其局限性,当牵涉到复杂的业务逻辑 ...

  5. Node+Express+MongoDB + Socket.io搭建实时聊天应用实战教程(三)--前后端环境配置

    前言 之前都是介绍一些基础知识,在这一节,我们就要开始实战coding了.正所谓磨刀不误砍柴工,准备工作显得尤为重要.很多demo只是追求效果的实现,并不注重整个demo的架构性.从我个人的角度看来, ...

  6. layui上传文件组件(前后端代码实现)

    我个人博客系统上传特色图片功能就是用layui上传文件组件做的.另外采用某个生态框架,尽量都统一用该生态框架对应的解决方案,因为这样一来,有这么几个好处?1.统一而不杂糅,有利于制定相应的编码规范,方 ...

  7. 一键生成通用高亮代码块到剪贴板,快捷粘贴兼容 TT/WX/BJ 编辑器

    有些在线图文编辑器不支持直接插入代码块,但可以直接粘贴 HTML 格式的高亮代码块. 花了一点时间研究了一下各家的编辑器,规则却各不相同.有的要求代码块被包含于 <code> ... &l ...

  8. 一套基于SpringBoot+Vue+Shiro 前后端分离 开发的代码生成器

    一.前言 最近花了一个月时间完成了一套基于Spring Boot+Vue+Shiro前后端分离的代码生成器,目前项目代码已基本完成 止步传统CRUD,进阶代码优化: 该项目可根据数据库字段动态生成 c ...

  9. ajax请求, 前后端, 代码示例

    [博客园cnblogs笔者m-yb原创,转载请加本文博客链接,笔者github: https://github.com/mayangbo666,公众号aandb7,QQ群927113708] http ...

随机推荐

  1. finally 关键字

    异常处理的时侯 出现的关键字finally 不论在  try  代码块中是否出现  发生了异常时间,  catch语句是否执行,catch语句是否有异常,catch语句中是否return关键字  ,f ...

  2. 「杂烩」精灵魔法(P1908逆序对弱化版)

    「杂烩」精灵魔法(P1908逆序对弱化版) 题面: 题目描述 \(Tristan\)解决了英灵殿的守卫安排后,便到达了静谧的精灵领地--\(Alfheim\) .由于$ Midgard$ 处在$ Al ...

  3. centos7-修改默认python为3

    安装必要工具 yum-utils: $ sudo yum install yum-utils 使用yum-builddep为Python3构建环境,安装缺失的软件依赖,使用下面的命令会自动处理.$ s ...

  4. 代码注入——c++代码注入

    代码注入之——c++代码注入 0x00  代码注入和DLL注入的区别 DLL注入后DLL会通过线程常驻在某个process中,而代码注入完成之后立即消失. 代码注入体积小,不占内存 0x01  通过c ...

  5. flutter学习01-flutter起步安装配置(window, vscode开发)

    从零开始配置flutter环境,如果直接去看官方文档配置的话,太过复杂,其实正式没有那么多步骤,记录一下: 1.首先,前往下面这个网站,下载flutter sdk  https://flutter.d ...

  6. Java标识符/数据类型,规范等详解

    Java标识符 类名/变量名/方法名都称之为标识符. Java 所有的组成部分都需要名字.类名.变量名以及方法名都被称为标识符. 关于 Java 标识符,有以下几点需要注意: 所有的标识符都应该以字母 ...

  7. Java入门系列之重写

    前言 关于所有Java系列文章面向有一定基础的童鞋,所写每一篇希望有一定含金量,有些内容可能会从Java整个语法全局考虑穿插后续要讲解的内容以成系统,若不理解,请看完后再学习.上一节我们讲解完了fin ...

  8. JavaScript学习 Ⅴ

    十. 一些对象 Date 对象 Date对象用来表示一个时间 创建Date对象 如果直接使用构造函数创建一个Date对象,则会封装为当前代码执行的时间 var d = new Date(); 创建一个 ...

  9. 机器学习实战基础(十二):sklearn中的数据预处理和特征工程(五) 数据预处理 Preprocessing & Impute 之 处理分类特征:处理连续性特征 二值化与分段

    处理连续性特征 二值化与分段 sklearn.preprocessing.Binarizer根据阈值将数据二值化(将特征值设置为0或1),用于处理连续型变量.大于阈值的值映射为1,而小于或等于阈值的值 ...

  10. 数据可视化之PowerQuery篇(一)空值(null)运算的的解决思路

    https://zhuanlan.zhihu.com/p/81535007 星友们在知识星球(PowerBI星球)提出的问题中,关于空值的运算经常被提及.平时接触到的源数据常常有空值,比如Excel数 ...