【企业级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,为了方便,我用…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...

【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...

Springboot 高校报修与互助平台小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,高校报修与互助平台小程序被用户普遍使用,为…...
Neo4j 完全指南:从入门到精通
第1章:Neo4j简介与图数据库基础 1.1 图数据库概述 传统关系型数据库与图数据库的对比图数据库的核心优势图数据库的应用场景 1.2 Neo4j的发展历史 Neo4j的起源与演进Neo4j的版本迭代Neo4j在图数据库领域的地位 1.3 图数据库的基本概念 节点(Node)与关系(Relat…...

详解ZYNQ中的 RC 和 EP
详解ZYNQ中的 RC 和 EP 一、ZYNQ FPGA 开发板基础( ZC706 ) 1. 核心特点 双核大脑 灵活积木: ZC706 集成了 ARM Cortex-A9 双核处理器(相当于电脑 CPU)和 FPGA 可编程逻辑单元(相当于可自定义的硬件积木…...

【读代码】从预训练到后训练:解锁语言模型推理潜能——Xiaomi MiMo项目深度解析
项目开源地址:https://github.com/XiaomiMiMo/MiMo 一、基本介绍 Xiaomi MiMo是小米公司开源的7B参数规模语言模型系列,专为复杂推理任务设计。项目包含基础模型(MiMo-7B-Base)、监督微调模型(MiMo-7B-SFT)和强化学习模型(MiMo-7B-RL)等多个版本。其核心创新在于通过…...