【企业级SpringBoot单体项目模板 】——Mybatis-plus自动代码生成
- 😜作 者:是江迪呀
- ✒️本文关键词:
SpringBoot项目模版、企业级、模版- ☀️每日 一言:
我们之所以这样认为,是因为他们这样说。他们之所以那样说,是因为他们想让我们那样认为。所以实践才是检验真理的唯一准则。
文章目录
- 一、使用Velocity模版自动生成代码
- 二、自定义vm模版
- 2.1 MyController.java.vm
- 2.2 MyEntity.java.vm 实体类
- 2.3 MyMapper.java.vm mapper接口
- 2.4 MyMapper.xml.vm mapper.xml
- 2.5 MyService.java.vm 服务层
- 2.6 MyServiceImpl.java.vm 服务实现类
- 三、测试
上回我们说了一些开发规范,其实现在你就可以开始写代码了。但是呢效率会很慢,实体类、mapper、service等等这些你都要手动创建,这样效率太低了,遇到一个表中有几十个字段的情况,你可以一上午都在写实体类,而且还不能保证准确性,所以我们需要一个工具替我们生成。
一、使用Velocity模版自动生成代码
我们以生成t_user表为例,表结构如下:

Generator代码:
package com.shijiangdiya.common;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;import java.util.*;public class Generator {/*** 生成的代码的顶层包名*/private static final String SERVICE_NAME = "code";/*** 最终包路径*/private static final StringBuilder FINAL_PATH = new StringBuilder();/*** 表名前缀*/private static String tablePrefix = "t_";/*** <p>* 读取控制台内容* </p>*/public static String scanner(String tip) {Scanner scanner = new Scanner(System.in);StringBuilder help = new StringBuilder();help.append("请输入" + tip + ":");System.out.println(help);if (scanner.hasNext()) {String ipt = scanner.next();if (StringUtils.isNotEmpty(ipt)) {return ipt;}}throw new MybatisPlusException("请输入正确的" + tip + "!");}/*** 代码生成器*/public static void main(String[] args) {// 目标数据表名String[] tableName = scanner("表名,多个英文逗号分割").split(",");generateByTables(tableName);}private static void generateByTables(String... tableNames) {AutoGenerator mpg = new AutoGenerator();mpg.setTemplateEngine(new VelocityTemplateEngine());// 全局配置GlobalConfig gc = globalGenerate();// 包配置PackageConfig pc = packageGenerate();// 数据库配置DataSourceConfig dsc = dataSourceGenerate();// 自定义模板TemplateConfig tc = templateGenerate();// 策略配置StrategyConfig strategy = strategyGenerate(tableNames);mpg.setGlobalConfig(gc);mpg.setDataSource(dsc);mpg.setPackageInfo(pc);mpg.setTemplate(tc);mpg.setStrategy(strategy);mpg.execute();}/*** 数据库配置** @return 数据源*/private static DataSourceConfig dataSourceGenerate() {YamlPropertiesFactoryBean yamlMapFactoryBean = new YamlPropertiesFactoryBean();yamlMapFactoryBean.setResources(new ClassPathResource("application.yml"));//获取yml里的参数Properties properties = yamlMapFactoryBean.getObject();String url = properties.getProperty("spring.datasource.url");String driver = properties.getProperty("spring.datasource.driver-class-name");String username = properties.getProperty("spring.datasource.username");String password = properties.getProperty("spring.datasource.password");// 数据库配置DataSourceConfig dsc = new DataSourceConfig();//数据类型dsc.setDbType(DbType.MYSQL);dsc.setUrl(url);dsc.setDriverName(driver);dsc.setUsername(username);dsc.setPassword(password);return dsc;}/*** 全局配置** @return 全局配置*/private static GlobalConfig globalGenerate() {// 全局配置GlobalConfig gc = new GlobalConfig();//是否覆盖文件gc.setFileOverride(true);// 获取顶层目录String projectPath = System.getProperty("user.dir");// 获取子项目目录String path = Generator.class.getClassLoader().getResource("").getPath();String levelPath = path.substring(0, path.indexOf("target") - 1);if (!projectPath.equals(levelPath)) {FINAL_PATH.append(levelPath);} else {FINAL_PATH.append(projectPath);}//输出路径gc.setOutputDir(FINAL_PATH + "/src/main/java");//作者名称gc.setAuthor("shijiangdiya");//生成后是否自动打开文件gc.setOpen(true);// XML 二级缓存gc.setEnableCache(false);//是否使用swagger2gc.setSwagger2(true);// 自定义文件命名,注意 %s 会自动填充表实体属性!gc.setControllerName("%sController");gc.setServiceName("%sService");gc.setServiceImplName("%sServiceImpl");gc.setMapperName("%sMapper");gc.setXmlName("%sMapper");//mapper.xml中生成基础resultMapgc.setBaseResultMap(true);//mapper.xml中生成基础columnListgc.setBaseColumnList(true);// 主键类型gc.setIdType(IdType.ID_WORKER);return gc;}/*** 策略配置* 主要的表字段映射** @param tableName 表名* @return 策略配置*/private static StrategyConfig strategyGenerate(String[] tableName) {// 策略配置StrategyConfig strategy = new StrategyConfig();//表名映射到实体策略,带下划线的转成 驼峰strategy.setNaming(NamingStrategy.underline_to_camel);//列名映射到类型属性策略,带下划线的转成驼峰strategy.setColumnNaming(NamingStrategy.underline_to_camel);// 表名和字段名是否大小写strategy.setCapitalMode(false);//实体类使用lombokstrategy.setEntityLombokModel(true);//controller使用rest接口模式strategy.setRestControllerStyle(true);// 继承顶层controller 这里是strategy.setSuperControllerClass("com.shijiangdiya.config.AbstractController");//设置表名strategy.setInclude(tableName);//去掉前缀strategy.setTablePrefix(tablePrefix);strategy.setEntityBooleanColumnRemoveIsPrefix(true);// 驼峰转连字符strategy.setControllerMappingHyphenStyle(true);strategy.setEntityBuilderModel(true);return strategy;}/*** 自定义模板** @return 模板*/private static TemplateConfig templateGenerate() {// 设置自定义的模板TemplateConfig tc = new TemplateConfig();tc.setController("templates/MyController.java.vm").setEntity("templates/MyEntity.java.vm").setService("templates/MyService.java.vm").setServiceImpl("templates/MyServiceImpl.java.vm").setMapper("templates/MyMapper.java.vm").setXml("/templates/MyMapper.xml.vm");// 不要源码包内的mapperreturn tc;}/*** 包配置** @return 包配置*/private static PackageConfig packageGenerate() {// 包配置PackageConfig pc = new PackageConfig();pc.setModuleName(SERVICE_NAME);pc.setParent("com.shijiangdiya");pc.setEntity("entity");pc.setService("service");pc.setServiceImpl("service.impl");pc.setMapper("mapper");pc.setXml("mapper.xml");return pc;}
}
二、自定义vm模版
使用自定义模板你可以生成更加符合你业务场景的代码。
2.1 MyController.java.vm
在控制层中,提供了CRUD的方法,你可以自定义一些通用的东西,比如传入查询的QO、返回的DTO等。
package ${package.Controller};import ${package.Entity}.${entity};
import ${package.Service}.${table.serviceName};
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import com.shijiangdiya.config.Response;#if(${superControllerClassPackage})
import $!{superControllerClassPackage};
#end/*** <p>* $!{table.comment} 前端控制器* </p>** @author ${author}* @since ${date}*/
#set($entityName = ${entity.substring(0,1).toLowerCase()}+${entity.substring(1)})
@RestController
@RequestMapping(value = {"#if(${controllerMappingHyphenStyle})/api/${controllerMappingHyphen}#else /api/${table.entityPath}#end"},produces = MediaType.APPLICATION_JSON_VALUE)
@Api(value = "${table.controllerName}", description = "$!{table.comment}", produces = MediaType.APPLICATION_JSON_VALUE)
public class ${table.controllerName} extends ${superControllerClass} {@Autowiredprivate ${table.serviceName} ${entityName}Service;@ResponseBody@ApiOperation(value = "", notes = "")@GetMapping(value = "/")public Response select(){${entityName}Service.select();return returnSuccess();}@ResponseBody@ApiOperation(value = "", notes = "")@PostMapping(value = "")public Response add(){${entityName}Service.add();return returnSuccess();}@ResponseBody@ApiOperation(value = "", notes = "")@PutMapping(value = "/{id}")public Response update(@PathVariable Long id){${entityName}Service.modifyById();return returnSuccess();}@ApiOperation(value = "$!{table.comment}-删除", notes = "$!{table.comment}-删除")@DeleteMapping(value = "/{id}")public Response delete(@PathVariable Long id){${entityName}Service.deleteById(id);return returnSuccess();}}
2.2 MyEntity.java.vm 实体类
package ${package.Controller};import ${package.Entity}.${entity};
import ${package.Service}.${table.serviceName};
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import com.shijiangdiya.config.Response;#if(${superControllerClassPackage})
import $!{superControllerClassPackage};
#end/*** <p>* $!{table.comment} 前端控制器* </p>** @author ${author}* @since ${date}*/
#set($entityName = ${entity.substring(0,1).toLowerCase()}+${entity.substring(1)})
@RestController
@RequestMapping(value = {"#if(${controllerMappingHyphenStyle})/api/${controllerMappingHyphen}#else /api/${table.entityPath}#end"},produces = MediaType.APPLICATION_JSON_VALUE)
@Api(value = "${table.controllerName}", description = "$!{table.comment}", produces = MediaType.APPLICATION_JSON_VALUE)
public class ${table.controllerName} extends ${superControllerClass} {@Autowiredprivate ${table.serviceName} ${entityName}Service;@ResponseBody@ApiOperation(value = "", notes = "")@GetMapping(value = "/")public Response select(){${entityName}Service.select();return returnSuccess();}@ResponseBody@ApiOperation(value = "", notes = "")@PostMapping(value = "")public Response add(){${entityName}Service.add();return returnSuccess();}@ResponseBody@ApiOperation(value = "", notes = "")@PutMapping(value = "/{id}")public Response update(@PathVariable Long id){${entityName}Service.modifyById();return returnSuccess();}@ApiOperation(value = "$!{table.comment}-删除", notes = "$!{table.comment}-删除")@DeleteMapping(value = "/{id}")public Response delete(@PathVariable Long id){${entityName}Service.deleteById(id);return returnSuccess();}}
2.3 MyMapper.java.vm mapper接口
package ${package.Mapper};import ${package.Entity}.${entity};
import ${superMapperClassPackage};
import org.apache.ibatis.annotations.Mapper;/*** <p>* $!{table.comment} Mapper 接口* </p>** @author ${author}* @since ${date}*/
@Mapper
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {}
2.4 MyMapper.xml.vm mapper.xml
<?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}">
</mapper>
2.5 MyService.java.vm 服务层
package ${package.Service};import ${package.Entity}.${entity};
import ${superServiceClassPackage};
import java.util.List;
/*** <p>* $!{table.comment} 服务类* </p>** @author ${author}* @since ${date}*/
#set($entityName = ${entity.substring(0,1).toLowerCase()}+${entity.substring(1)})
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> {/*** 查询*/List select();/*** 修改*/void add();/*** 删除* @param id*/void deleteById(Long id);/*** 修改*/void modifyById();
}
2.6 MyServiceImpl.java.vm 服务实现类
package ${package.ServiceImpl};import ${package.Entity}.${entity};
import ${package.Mapper}.${table.mapperName};
import ${package.Service}.${table.serviceName};
import ${superServiceImplClassPackage};
import org.springframework.stereotype.Service;
import java.util.List;/*** <p>* $!{table.comment} 服务实现类* </p>** @author ${author}* @since ${date}* @version ${cfg.version}*/
#set($entityName = ${entity.substring(0,1).toLowerCase()}+${entity.substring(1)})
@Service
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}> implements ${table.serviceName} {@Overridepublic List select() {return null;}@Overridepublic void add() {}@Overridepublic void deleteById(Long id) {}@Overridepublic void modifyById() {}
}
三、测试


相关文章:
【企业级SpringBoot单体项目模板 】——Mybatis-plus自动代码生成
😜作 者:是江迪呀✒️本文关键词:SpringBoot项目模版、企业级、模版☀️每日 一言:我们之所以这样认为,是因为他们这样说。他们之所以那样说,是因为他们想让我们那样认为。所以实践才是检验真理…...
怒刷LeetCode的第14天(Java版)
目录 第一题 题目来源 题目内容 解决方法 方法一:动态规划 方法二:栈 方法三:双指针 第二题 题目来源 题目内容 解决方法 方法一:二分查找 方法二:线性扫描 方法三:递归 第三题 题目来源 …...
c语言 static
1、静态局部变量在程序加载时初始化,静态局部变量的初始值写入到了data段: 如下代码test_symbol.c int f() {static int x 0;return x; }int g() {static int x 9;return x; }使用命令gcc -c test_symbol.c -o test_symbol 编译 使用命令 readelf -a …...
java基础3
输入一个班学生的成绩,先显示所有及格的成绩,再显示所有不及格的成绩,最后显示及格人数和不及格人数 import java.util.Scanner; public class Hello{public static void main(String [] args) {int SIZE5;double grade[] new double[SIZE]…...
LeetCode 1194.锦标赛优胜者
数据准备 Create table If Not Exists Players (player_id int, group_id int); Create table If Not Exists Matches (match_id int, first_player int, second_player int, first_score int, second_score int); Truncate table Players; insert into Players (player_id, g…...
多旋翼无人机组合导航系统-多源信息融合算法(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
如何用ArkUI实现一个加入购物车效果?
关键词:ArkUI的动效能力,动效开发,ArkUI动画 我们在购买商品时,往往习惯将商品先加入购物车,然后在购物车里确认后再下订单,这是一个典型的访问者模式。对于这个高频场景,增添一些动效可以增加a…...
ChatGLM GPT原理介绍
图解GPT 除了BERT以外,另一个预训练模型GPT也给NLP领域带来了不少轰动,本节也对GPT做一个详细的讲解。 OpenAI提出的GPT-2模型(https://openai.com/blog/better-language-models/) 能够写出连贯并且高质量的文章,比之前语言模型效果好很多。GPT-2是基于Transformer搭建的,相…...
2015年蓝桥杯省赛C/C++ A组 灾后重建题解(100分)
10. 灾后重建 Pear市一共有N(<50000)个居民点,居民点之间有M(<200000)条双向道路相连。这些居民点两两之间都可以通过双向道路到达。这种情况一直持续到最近,一次严重的地震毁坏了全部M条道路。 震后…...
Elasticsearch(四)深分页Scroll
一、前言 1.1、scroll与fromsize区别 ES对于fromsize的个数是有限制的,二者之和不能超过1w。当所请求的数据总量大于1w时,可用scroll来代替fromsize。 fromsize在ES查询数据的方式步骤如下: 1、先将用户指定的关键字进行分词;…...
JavaWeb后端开发 JWT令牌解析 登录校验 通用模板/SpringBoot整合
目录 实现思路 会话跟踪的三个方案--引出Jwt令牌技术 1.访问cookie的值,在同一会话的不同请求之间共享数据 2.session 3.现代普遍采用的令牌技术--JWT令牌 JWT令牌技术 第一步--生成令牌 1.引入依赖 2.生成令牌 第二步--校验令牌 第三步--登录下发令牌 需要解决的…...
Sparta工具用法描述之信息收集(漏洞分析)
声明:本文仅做学习与交流,任何用于非法用途、行为等造成他人损失的,责任自负。本文不承担任何法律责任。 Sparta是python GUI应用程序,它通过在扫描和枚举阶段协助渗透测试仪来简化网络基础结构渗透测试。 通过点击并单击工具箱并以方便的方式显示所有工具输出,它可以使测…...
Vue复选框批量删除示例
Vue复选框批量删除 通过使用v-model指令绑定单个复选框 例如<input type"checkbox" id"checkbox" v-model"checked"> 而本次我们要做的示例大致是这样的,首先可以增加内容,然后通过勾选来进行单独或者批量删除&…...
Docker自定义镜像
一、镜像结构 镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。 镜像是分层结构,每一层称为一个Layer BaseImage层:包含基本的系统函数库、环境变量、文件系统其它:在BaseImage基础上添加依赖、安装程序、完成整个应用的…...
ardupilot的编译过程
环境 树莓派4b ubuntu20.04 git 2.25.1 python3.8.10 pixhawk2.4.8 下载源码 (已经配置好git环境和ssh) git clone --recurse-submodules gitgithub.com:ArduPilot/ardupilot.gitcd ardupilotgit status使用git status检查是否下载完整 如果不完整&a…...
Unity中Shader实现模板测试Stencil
文章目录 前言一、UI中的遮罩1、Mask ——> 模板测试2、RectMask2D ——> UNITY_UI_CLIP_RECT 二、模板缓冲区Stencil一般是和Pass平行的部分,Pass部分写的是颜色缓冲区Stencil:Comp(比较操作)Pass(模版缓冲区的更新) 三、实际使用1、在…...
多线程与并发
多线程与高并发 线程的创建方式1.继承Thread类 重写run方法2.实现Runnable接口 重写run方法3. 实现Callable 重写call方法,配合FutureTask 线程的使用1.线程的状态1.1. 传统操作系统层面5种状态1.2.Java中给线程准备的6种状态 2.线程的常用方法2.1 获取当前线程2.2 …...
手写call方法
Function.prototype.myCallfunction (context,args) {console.log(arguments)//context 表示call里面的第一个参数也就是需要改变this指向的那个对象。//this表示这个方法//把这个方法挂到需要改变指向的对象身上调用,相当于把this指向了这个对象身上,从…...
基于FPGA的图像直方图统计实现,包括tb测试文件和MATLAB辅助验证
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1、图像数据传输 4.2、直方图统计算法 4.3、时序控制和电路设计 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 vivado2019.2 matlab2022a 3.部分核心程序 timescal…...
数据库:Hive转Presto(一)
本人因为工作原因,经常使用hive以及presto,一般是编写hive完成工作,服务器原因,presto会跑的更快一些,所以工作的时候会使用presto验证结果,所以就要频繁hive转presto,为了方便,我用…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...
C# winform教程(二)----checkbox
一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...
【iOS】 Block再学习
iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...
【51单片机】4. 模块化编程与LCD1602Debug
1. 什么是模块化编程 传统编程会将所有函数放在main.c中,如果使用的模块多,一个文件内会有很多代码,不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数声明,其他.c文…...
Python爬虫实战:研究Restkit库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的有价值数据。如何高效地采集这些数据并将其应用于实际业务中,成为了许多企业和开发者关注的焦点。网络爬虫技术作为一种自动化的数据采集工具,可以帮助我们从网页中提取所需的信息。而 RESTful API …...
