天行健,君子以自强不息;地势坤,君子以厚德载物。
每个人都有惰性,但不断学习是好好生活的根本,共勉!
文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。
一键生成代码
- 功能简介
- 开发环境:
- 实现
- 1. 项目包结构预览
- 2. 完整依赖
- 3. 配置文件
- 4. 项目启动类
- 5. jdbc参数读取配置文件
- 6. 代码模板配置文件(文本文件)
- 7. 代码生成工具类代码
- 7.1 文件IO工具
- 7.2 生成代码注释及引入配置
- 7.3 代码生成工具类
- 7.4 对象实体类属性校验工具
- 7.5 结果返回工具
- 8. 请求控制类
- 9. 请求调用
- 9.1 url
- 9.2 postman截图
- 9.3 控制台打印
- 9.4 生成的代码文件截图
- 拓展:
功能简介
想不想一次性生成增删改查所需的所有代码(包括请求类controller)?我也想啊!
最近在学习研究自动生成代码的一些方法,学到了一些新的东西,好不好用自己试过才知道,但自己用着的确还可以,分享一下。
大家都知道mybatis框架中有一个插件可生成代码,但生成的代码比较局限,很多地方需要修改。接下来的内容就是在其基础上通过配置来更简单的实现生成更完善的代码的功能,也就是最少修改甚至不修改即可用的一键生成代码工具。
开发环境:
JDK版本:1.8
maven版本:3.9.0
开发工具:IDEA社区版ideaIC-2018.3
项目框架:spring boot 版本为 2.7.3 springboot搭建传送门
实现
1. 项目包结构预览
包结构需要创建的就是com.code下的config包、controller包、utils包
code_package包是自动创建的,用来存放生成代码的包,可在代码中定义
这里需要注意的是,utils包最好是按照我这个来,且不管你utils包在哪里,都希望你能把utils包里的这几个文件放在utils包里,当然也可以不,只需根据参数进行修改代码或模板即可,具体看自己了。
2. 完整依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.code</groupId>
<artifactId>code_ge_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!--spring boot 父依赖 版本管理-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.3</version>
</parent>
<dependencies>
<!--spring boot web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--spring boot test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!--mysql 连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--jdbc连接 使用jdbc依赖时或者jpa依赖时默认注入事物管理,不需任何配置,可直接使用@Transactional注解进行事物管理-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<!--mybatis plugin-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.2</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--不可用-->
<!-- <dependency>-->
<!-- <groupId>com.github.pagehelper</groupId>-->
<!-- <artifactId>pagehelper-spring-boot</artifactId>-->
<!-- <version>1.3.0</version>-->
<!-- </dependency>-->
<!--分页-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.2</version>
</dependency>
<!--json工具-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.32</version>
</dependency>
</dependencies>
</project>
3. 配置文件
application.yml
spring:
profiles:
active: dev
application:
name: code_ge
application-dev.yml
server:
port: 9001
spring:
datasource:
url: jdbc:mysql://localhost:3306/database_1?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
4. 项目启动类
CodeGeApplication.java
package com.code;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @ClassDescription:
* @Author:李白
* @Date:2023/6/7 13:31
*/
@SpringBootApplication
public class CodeGeApplication {
public static void main(String[] args) {
SpringApplication.run(CodeGeApplication.class, args);
}
}
5. jdbc参数读取配置文件
通过配置文件读取yml中的jdbc连接参数(@Value注解读取)
注解读取参数方法请见文章末尾拓展
JdbcConfig.java
package com.code.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @ClassDescription: jdbc数据库连接参数读取
* @Author:李白
* @Date:2023/6/06 16:54
*/
@Component
public class JdbcConfig {
@Value("${spring.datasource.url}")
public String url;
@Value("${spring.datasource.username}")
public String username;
@Value("${spring.datasource.password}")
public String password;
@Value("${spring.datasource.driver-class-name}")
public String driver_class_name;
}
6. 代码模板配置文件(文本文件)
生成代码的mapper模板,会根据此文件生成对象实体、接口实现类、数据操作映射接口、数据操作映射文件,共四个文件。
CodeGeTemMapper.txt
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="MySqlContext" targetRuntime="MyBatis3" defaultModelType="flat">
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
<plugin type="org.mybatis.generator.plugins.RenameExampleClassPlugin">
<property name="searchString" value="Example$"/>
<property name="replaceString" value="Impl"/>
</plugin>
<commentGenerator type="@CommentGenerator@"/>
<jdbcConnection driverClass="@driverClassName@"
connectionURL="@url@"
userId="@username@"
password="@password@">
<property name="nullCatalogMeansCurrent" value="true" />
</jdbcConnection>
<javaModelGenerator targetPackage="@codePackage@" targetProject="src/main/java"/>
<sqlMapGenerator targetPackage="@codePackage@" targetProject="src/main/java"/>
<javaClientGenerator type="XMLMAPPER" targetPackage="@codePackage@" targetProject="src/main/java"/>
<table tableName="@tableName@">
<generatedKey column="id" sqlStatement="MySql" identity="true"/>
</table>
</context>
</generatorConfiguration>
生成代码的controller模板,会根据此文件生成controller请求类,共一个文件。
CodeGeTemController.txt
package @codePath@;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import @codePath@.TestJwhGenerateCode;
import @codePath@.TestJwhGenerateCodeImpl;
import @codePath@.TestJwhGenerateCodeMapper;
import @utilPath@.*;
import @utilPath@.ResultJsonObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@EnableAutoConfiguration
@RequestMapping("/test-jwh-url")
public class TestJwhGenerateCodeController {
@Autowired
TestJwhGenerateCodeMapper testJwhGenerateCodeMapper;
/**
* 新增数据
* @param body 数据json
* @return
* @throws Exception
*/
@CrossOrigin
@Transactional(rollbackFor = Exception.class)
@RequestMapping(value = "/insert", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public ResultJsonObject insert(@RequestBody JSONObject body) throws Exception {
if (!body.containsKey("records"))
throw new Exception("请求体中无此key:records");
JSONArray records = body.getJSONArray("records");
for (int n = 0; n < records.size(); n++) {
JSONObject record = records.getJSONObject(n);
JSONObject validateInfo = ClazzValidateUtil.clazzValidate(record,TestJwhGenerateCode.class);
Boolean validateResult = (Boolean) validateInfo.get("clazzValidateResult");
if (!validateResult) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
throw new Exception("数据不符合类的格式,info信息:"+validateInfo.get("info"));
}
TestJwhGenerateCode testJwhGenerateCode = JSON.parseObject(JSON.toJSONString(record), TestJwhGenerateCode.class);
testJwhGenerateCodeMapper.insert(testJwhGenerateCode);
}
return new ResultJsonObject("success:数据插入成功",200);
}
/**
* 根据id查询数据
* @param body 数据json
* @return
* @throws Exception
*/
@CrossOrigin
@Transactional(rollbackFor = Exception.class)
@RequestMapping(value = "/delete", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public ResultJsonObject delete(@RequestBody JSONObject body) throws Exception {
if (!body.containsKey("records"))
throw new Exception("请求体中无此key:records");
JSONArray records = body.getJSONArray("records");
for (int i = 0; i < records.size(); i++) {
JSONObject record = records.getJSONObject(i);
JSONObject validateInfo = ClazzValidateUtil.clazzValidate(record,TestJwhGenerateCode.class);
Boolean validateResult = (Boolean) validateInfo.get("clazzValidateResult");
if (!validateResult) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
throw new Exception("数据不符合类的格式,info信息:"+validateInfo.get("info"));
}
if (!record.containsKey("id")) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
throw new Exception("数据无此查询条件:id");
}
TestJwhGenerateCode testJwhGenerateCode = JSON.parseObject(JSON.toJSONString(record), TestJwhGenerateCode.class);
testJwhGenerateCodeMapper.deleteByPrimaryKey(testJwhGenerateCode.getId());
}
return new ResultJsonObject("success:数据删除成功",200);
}
/**
* 更新数据
* @param body 数据json
* @return
* @throws Exception
*/
@CrossOrigin
@RequestMapping(value = "/update", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public ResultJsonObject update(@RequestBody JSONObject body) throws Exception {
// update record by primary key id
if (!body.containsKey("records"))
throw new Exception("请求体中无此key:records");
JSONArray records = body.getJSONArray("records");
for (int n = 0; n < records.size(); n++) {
JSONObject record = records.getJSONObject(n);
JSONObject validateInfo = ClazzValidateUtil.clazzValidate(record,TestJwhGenerateCode.class);
Boolean validateResult = (Boolean) validateInfo.get("clazzValidateResult");
if (!validateResult) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
throw new Exception("数据不符合类的格式,info信息:"+validateInfo.get("info"));
}
if (!record.containsKey("id")) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
throw new Exception("数据无此查询条件:id");
}
// 修改的数据
TestJwhGenerateCode testJwhGenerateCode = record.toJavaObject(TestJwhGenerateCode.class);
testJwhGenerateCodeMapper.updateByPrimaryKeySelective(testJwhGenerateCode);
}
return new ResultJsonObject("success:数据更新成功",200);
}
/**
* 查询数据
* @param body 数据json
* @return
* @throws Exception
*/
@CrossOrigin
@RequestMapping(value = "/list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public ResultJsonObject list(@RequestBody JSONObject body) throws Exception {
if (!body.containsKey("criteria"))
throw new Exception("无查询条件key:criteria");
if (!body.containsKey("pageNum"))
throw new Exception("无分页页数key:pageNum");
if (!body.containsKey("pageSize"))
throw new Exception("无分页每页数量key:pageSize");
TestJwhGenerateCodeImpl testJwhGenerateCodeImpl = new TestJwhGenerateCodeImpl();
TestJwhGenerateCodeImpl.Criteria criteria = testJwhGenerateCodeImpl.createCriteria();
JSONArray criList = body.getJSONArray("criteria");
for (int i = 0; i < criList.size(); i++) {
JSONObject cri = criList.getJSONObject(i);
Map.Entry<String, String> maps = (Map.Entry<String, String>) cri.entrySet();
//addCriterion的参数有三种情况
// criteria.addCriterion("condition");
// criteria.addCriterion(maps.getKey()+"=");
// criteria.addCriterion(condition,value,property);
criteria.addCriterion(maps.getKey()+"=",maps.getValue(),maps.getKey());
// criteria.addCriterion(condition,value1,value2,property);
// criteria.addCriterion("id not between","3","5","id");
}
PageHelper.startPage(body.getIntValue("pageNum"), body.getIntValue("pageSize"));
PageInfo<TestJwhGenerateCode> pageInfo = new PageInfo<>(testJwhGenerateCodeMapper.selectByExample(testJwhGenerateCodeImpl));
JSONObject retObject = new JSONObject();
retObject.put("pageInfo", pageInfo);
return new ResultJsonObject("success:数据查询成功",200);
}
}
7. 代码生成工具类代码
首先看主要的代码生成工具,也就是除去生成controller之外的代码。有三个工具类:文件输入输出流工具FileUtil.java、生成代码注释工具CommentGenerator.java、生成代码工具CodeUtil.java。
7.1 文件IO工具
在生成代码文件时需读取文本文件内容及生成文件需要用到文件读写工具。
FileIoUtil.java
package com.code.utils;
import java.io.*;
/**
* @ClassDescription: 文件读写流工具 读和写
* @Author:李白
* @Date:2023/6/06 18:22
*/
public class FileIoUtil {
/**
* 将字符串内容写入指定文件中
* @param filePath 文件的绝对路径,如 c:/files/student.text
* @param content
* @throws IOException
*/
public static void writeStringToFile(String filePath, String content) throws IOException {
File file = new File(filePath);
if (!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
Writer out = new FileWriter(file);
out.write(content);
out.close();
}
/**
* 将文件中的内容读取成字符串返回
* @param filePath
* @return
* @throws IOException
*/
public static String readFileAsString(String filePath) throws IOException {
File file = new File(filePath);
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
StringBuilder stringBuilder = new StringBuilder();
String s = "";
while ((s = bufferedReader.readLine()) != null){
stringBuilder.append(s).append("\n");
}
bufferedReader.close();
return stringBuilder.toString();
}
}
7.2 生成代码注释及引入配置
对生成的代码文件中的内容新增注释或关闭多余注释,新增引入的类等。
CommentGenerator.java
package com.code.utils;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.internal.DefaultCommentGenerator;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
/**
* @ClassDescription: 根据数据库表生成代码(注释部分--增加或者取消注释)
* @Author:李白
* @Date:2023/6/06 14:56
*/
public class CommentGenerator extends DefaultCommentGenerator {
private Properties properties;
private boolean suppressDate;
private boolean suppressAllComments;
public CommentGenerator(){
this.properties = new Properties();
this.suppressDate = false;
this.suppressAllComments = false;
}
/**
* 生成代码文件顶端注释以及接口和类注解引入
* @param compilationUnit
*/
public void addJavaFileComment(CompilationUnit compilationUnit){
compilationUnit.addFileCommentLine("/**\n * copyright (c) 2023 HanShan \n */");
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String geTime = simpleDateFormat.format(date);
compilationUnit.addFileCommentLine(String.format("/**\n * version: 1.0.0 \n * generate time: %s \n */", geTime));
if (compilationUnit instanceof Interface){
Interface interfaces = (Interface) compilationUnit;
interfaces.addJavaDocLine("import org.apache.ibatis.annotations.Mapper;");
interfaces.addJavaDocLine("@Mapper");
}else {
TopLevelClass topLevelClass = (TopLevelClass) compilationUnit;
if (topLevelClass.getType().toString().endsWith("Impl")){
topLevelClass.addJavaDocLine("import org.springframework.stereotype.Service;");
topLevelClass.addJavaDocLine("@Service");
}
}
}
/**
* XML file Comment
* @param xmlElement
*/
public void addComment(XmlElement xmlElement){
if (this.suppressAllComments){
return;
}
}
/**
* 时间注释关闭
* @param field
* @param introspectedTable
* @param introspectedColumn
*/
public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn){
if (this.suppressAllComments){
return;
}
if (introspectedColumn.getJdbcTypeName().equals("TIMESTAMP")){
field.addJavaDocLine("@DateTimeFormat(pattern = \"yyyy-MM-dd HH:mm:ss\")");
field.addJavaDocLine("@JsonFormat(shape=JsonFormat.Shape.STRING, pattern = \"yyyy-MM-dd HH:mm:ss\", timezone = \"GMT+8\")");
}
}
/**
* 属性注释关闭 Comment of Example field
* @param field the field
* @param introspectedTable the introspected table
*/
public void addFieldComment(Field field, IntrospectedTable introspectedTable){
if (this.suppressAllComments){
return;
}
}
/**
* java对象注释配置
* @param topLevelClass the top level class
* @param introspectedTable the introspected table
*/
public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable){
if (this.suppressAllComments){
return;
}
topLevelClass.addJavaDocLine("import lombok.Data;");
topLevelClass.addJavaDocLine("import org.springframework.stereotype.Component;");
topLevelClass.addJavaDocLine("@Data");
topLevelClass.addJavaDocLine("@Component");
}
public void addClassComment(InnerInterface innerInterface, IntrospectedTable introspectedTable){
if (this.suppressAllComments){
return;
}
}
/**
* 类注释关闭 Comment of Example inner class(GeneratedCriteria, Criterion)
* @param innerClass the inner class
* @param introspectedTable the introspected table
*/
public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable){
if (this.suppressAllComments){
return;
}
}
/**
* enum注释关闭
* @param innerEnum
* @param introspectedTable
*/
public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable){
if (this.suppressAllComments){
return;
}
}
/**
* 方法注释关闭
* @param method
* @param introspectedTable
*/
public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable){
if (this.suppressAllComments){
return;
}
}
/**
* getter注释关闭
* @param method
* @param introspectedTable
* @param introspectedColumn
*/
public void addGetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn){
if (this.suppressAllComments){
return;
}
}
/**
* setter注释关闭
* @param method
* @param introspectedTable
* @param introspectedColumn
*/
public void addSetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn){
if (this.suppressAllComments){
return;
}
}
}
7.3 代码生成工具类
生成代码需要调用的方法。
CodeUtil.java
package com.code.utils;
import com.code.config.JdbcConfig;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.XMLParserException;
import org.mybatis.generator.internal.DefaultShellCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.*;
import java.sql.SQLException;
import java.util.*;
/**
* @ClassDescription: 代码自动生成工具(entity、mapper.java、impl、mapper.xml)
* @Author:李白
* @Date:2023/6/6 12:44
*/
@Component
public class CodeUtil {
@Autowired
JdbcConfig jdbcConfig;
private static JdbcConfig geJdbcCfg;
@PostConstruct
public void init(){
geJdbcCfg = jdbcConfig;
}
/**
* 代码生成总方法
* @param tablesPackages map形式存放表和包路径(可多个)
* @param utilPackage 工具类包路径(生成代码中的引入参数等相关)
* @throws XMLParserException
* @throws SQLException
* @throws IOException
* @throws InterruptedException
* @throws InvalidConfigurationException
*/
public static void CodeGe(HashMap<String, String> tablesPackages, String utilPackage) throws XMLParserException, SQLException, IOException, InterruptedException, InvalidConfigurationException {
//遍历集合,拿到表名和包路径
for (Map.Entry<String,String> tbPc : tablesPackages.entrySet()){
//获取表名 如 test_jwh_generate_code
String tableName = tbPc.getKey();
//获取代码存放包路径 如 com.code.code_package
String codePackage = tbPc.getValue();
//实体类对象名为表名的首字母大写后续每个短杠后的字母大写 如 TestJwhGenerateCode
String modelName = Arrays.stream(tableName.split("_")).map(el -> {
String elx = el;
return elx.substring(0,1).toUpperCase()+elx.substring(1);
}).reduce((x,y)->x+y).map(Objects::toString).orElse("");
//对象变量名 如 testJwhGenerateCode
String objectName = modelName.substring(0,1).toLowerCase()+modelName.substring(1);
//生成mapper.xml(数据映射文件) mapper.java(映射接口) impl(接口实现类) model(对象实体类)
createMapper(geJdbcCfg, codePackage,utilPackage, tableName);
//生成controller
createController(codePackage, utilPackage, modelName, objectName);
//修改生成文件 新增truncate (接口文件)
modifyJavaMapper(codePackage, modelName);
//修改生成文件 新增truncate (xml mapper)
modifyXmlMapper(codePackage, modelName, tableName);
}
}
/**
* model_service_mapper文件的生成(四个:实体类,xml映射文件,映射文件接口,接口实现类)
* 注意事项:在对应的CodeGenerateConfig_Mapper.txt文件中的jdbcConnection位置,driverClassName和url必须放在前两个为位置,不然会解析报错
* @param jdbcConfig jdbc配置文件参数类
* @param codePackage 代码存储位置
* @param tableName 表名
* @throws IOException
* @throws XMLParserException
* @throws InvalidConfigurationException
* @throws SQLException
* @throws InterruptedException
*/
public static void createMapper(JdbcConfig jdbcConfig, String codePackage, String utilsPackage, String tableName) throws IOException, XMLParserException, InvalidConfigurationException, SQLException, InterruptedException {
//读取文本文件(mapper.xml的模板)
String rawConfig = FileIoUtil.readFileAsString("src/main/resources/CodeGeTemMapper.txt");
//jdbc用户名替换
rawConfig = rawConfig.replace("@username@", jdbcConfig.username);
//jdbc密码替换
rawConfig = rawConfig.replace("@password@", jdbcConfig.password);
//jdbc url替换
rawConfig = rawConfig.replace("@url@", jdbcConfig.url.replace("&","&"));
//jdbc 驱动替换
rawConfig = rawConfig.replace("@driverClassName@", jdbcConfig.driver_class_name);
//存放生成代码的包的路径
rawConfig = rawConfig.replace("@codePackage@", codePackage);
//所生成代码的表名
rawConfig = rawConfig.replace("@tableName@", tableName);
//生成器参数配置文件的位置参数替换,放在工具类里,则和创建controller函数中的参数一致,如果没有放在utils包中,则需要自行修改这个包路径
rawConfig = rawConfig.replace("@CommentGenerator@", utilsPackage+".CommentGenerator");
List<String> warnings = new ArrayList<>();
InputStream inputStream = new ByteArrayInputStream(rawConfig.getBytes());
ConfigurationParser configurationParser = new ConfigurationParser(warnings);
Configuration configuration = configurationParser.parseConfiguration(inputStream);
inputStream.close();
DefaultShellCallback defaultShellCallback = new DefaultShellCallback(true);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(configuration, defaultShellCallback, warnings);
myBatisGenerator.generate(null);
for (String warning : warnings){
System.out.println(warning);
}
}
/**
* Controller.java 文件创建
* @param codePackage 代码存储位置
* @param modelName 对象名
* @param objectName 对象变量名
* @throws IOException
*/
public static void createController(String codePackage, String modelName, String objectName) throws IOException {
String content = FileIoUtil.readFileAsString("src/main/resources/CodeGeTemController.txt");
content = content.replace("@codePath@", codePackage);
content = content.replace("TestJwhGenerateCode", modelName);
content = content.replace("testJwhGenerateCode",objectName);
// content = content.replace("test-jwh-url", UUID.randomUUID().toString());
String controllerPath = String.format("src/main/java/%s/%s", codePackage.replace(".", "/"), modelName+"Controller.java");
FileIoUtil.writeStringToFile(controllerPath, content);
}
/**
* Controller.java 文件创建
* @param codePackage 代码存储位置
* @param utilPackage 工具类所在位置
* @param modelName 对象名
* @param objectName 对象变量名
* @throws IOException
*/
public static void createController(String codePackage, String utilPackage, String modelName, String objectName) throws IOException {
String content = FileIoUtil.readFileAsString("src/main/resources/CodeGeTemController.txt");
content = content.replace("@codePath@", codePackage);
content = content.replace("@utilPath@", utilPackage);
content = content.replace("TestJwhGenerateCode", modelName);
content = content.replace("testJwhGenerateCode",objectName);
// content = content.replace("test-jwh-url", UUID.randomUUID().toString());
String controllerPath = String.format("src/main/java/%s/%s", codePackage.replace(".", "/"), modelName+"Controller.java");
FileIoUtil.writeStringToFile(controllerPath, content);
}
/**
* Mapper.java文件 修改
* @param codePackage 代码存储位置
* @param modelName 对象名
* @throws IOException
*/
public static void modifyJavaMapper(String codePackage, String modelName) throws IOException {
String mapperPath = String.format("scr/main/java/%s/%s", codePackage.replace(".", "/"), modelName+"Mapper.java");
try {
File file = new File(mapperPath);
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
StringBuilder stringBuilder = new StringBuilder();
String line = "";
while((line = bufferedReader.readLine()) != null){
stringBuilder.append(line).append("\n");
if (line.indexOf("updateByPrimaryKey(")>0){
stringBuilder.append("\n void truncate();\n\n");
}
}
bufferedReader.close();
FileIoUtil.writeStringToFile(mapperPath, stringBuilder.toString());
}catch (FileNotFoundException fileNotFoundException){
// fileNotFoundException.printStackTrace();
System.out.println("这里会出现Mapper.java文件的“系统找不到指定的路径“错误,但不影响代码生成的位置,所以抓取错误不打印----->");
}
}
/**
* Mapper.xml文件 修改
* @param codePackage 代码存储位置
* @param modelName 对象名
* @param tableName 表名
* @throws IOException
*/
public static void modifyXmlMapper(String codePackage, String modelName, String tableName) throws IOException {
String mapperPath = String.format("scr/main/java/%s/%s", codePackage.replace(".", "/"), modelName+"Mapper.xml");
try {
File file = new File(mapperPath);
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
StringBuilder stringBuilder = new StringBuilder();
String line = "";
while ((line = bufferedReader.readLine()) != null){
if (line.indexOf("/mapper")>0){
stringBuilder.append(" <update id=\"truncateTable\">TRUNCATE TABLE " + tableName + "</update>\n");
}
stringBuilder.append(line).append("\n");
}
bufferedReader.close();
FileIoUtil.writeStringToFile(mapperPath, stringBuilder.toString());
}catch (FileNotFoundException fileNotFoundException){
System.out.println("这里会出现Mapper.xml文件的“系统找不到指定的路径“错误,但不影响代码生成的位置,所以抓取错误不打印----->");
}
}
}
然后是两个关于controller文件内容引入的工具类,类校验工具ClazzValidateUtil.java,结果返回工具ResultJsonObject.java,当然了,这两个东西也可以不用,特别是结果返回这个,如果觉得没必要,可以自己写,或者干脆不写也可。如果不要这个记得去模板里把controller的模板文件中的对应的内容剔除或修改。
7.4 对象实体类属性校验工具
主要对传入的对象参数进行校验,如果不满足条件则返回对应的提示结果。
ClazzValidateUtil.java
package com.code.utils;
import com.alibaba.fastjson.JSONObject;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @ClassDescription: 对象校验工具
* @Author:李白
* @Date:2023/6/8 10:34
*/
public class ClazzValidateUtil {
/**
* 检验json对象(可包含多个内容)内容是否符合class对象内容
* @param jsonObject 需要校验的json对象
* @param clazz 需要匹配的参照对象
* @return
*/
public static JSONObject clazzValidate(JSONObject jsonObject, Class<?> clazz){
JSONObject result = new JSONObject();
Boolean clazzValidateResult = true;
result.put("clazzValidateResult",clazzValidateResult);
Field[] fields = clazz.getDeclaredFields();
List<String> segments = Arrays.stream(fields).map(s->s.getName()).collect(Collectors.toList());
List<String> errorKeys = new ArrayList<>();
for (Object key : jsonObject.keySet()) {
if (!segments.contains(key)){
result.put("clazzValidateResult",false);
result.put("errorKeys",errorKeys.add((String) key));
}
}
result.put("info",errorKeys.stream().distinct().reduce((x,y)->x+", "+y).map(Object::toString).orElse(""));
return result;
}
}
7.5 结果返回工具
主要是方便返回固定格式的json结果
ResultJsonObject.java
package com.code.utils;
import org.springframework.stereotype.Component;
/**
* @ClassDescription: 结果返回工具类
* @Author:李白
* @Date:2023/6/8 9:58
*/
@Component
public class ResultJsonObject {
private String msg;
private Integer code;
public ResultJsonObject() {
}
public ResultJsonObject(String msg, Integer code) {
this.msg = msg;
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}
8. 请求控制类
将表名和代码存放的包路径以键值形式存入map中作为参数,再将工具类的包路径作为参数参数传入
通过此请求调用函数进行代码生成。
CodeGeTestController.java
package com.code.controller;
import com.code.utils.CodeUtil;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.XMLParserException;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;
/**
* @ClassDescription: 生成代码 请求
* @Author:李白
* @Date:2023/6/6 12:42
*/
@RestController
//@EnableAutoConfiguration
@RequestMapping("/code")
public class CodeGeTestController {
@RequestMapping(value = "/url", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public String code() throws XMLParserException, SQLException, IOException, InterruptedException, InvalidConfigurationException {
//创建集合存储数据
HashMap<String, String> tablePackage = new HashMap<>();
//将表名与代码存储位置路径以键值对形式存入(可多个)
// tablePackage.put("test_jwh_generate_code1","com.code.code_package1");
tablePackage.put("test_jwh_generate_code","com.code.code_package");
//调用函数传入参数,集合与工具类包路径(包路径中的utils里有生成的controller中需要用到的代码)
CodeUtil.CodeGe(tablePackage,"com.code.utils");
//成功则返回
return "code ge!";
}
}
需要注意的是,utils包路径这个参数不仅对controller的生成和文件内容有影响,还对放在utils包中的CommentGeneratejava文件在mapper.txt模板中的位置有影响。具体请看具体文件中对应的参数。
9. 请求调用
启动项目,使用postman调用接口
9.1 url
127.0.0.1:9001/code/url
9.2 postman截图
9.3 控制台打印
9.4 生成的代码文件截图
当然了,如果觉得每次生成都要启动项目然后再调用请求执行方法比较麻烦,可以考虑将方法的调用通过main方法执行或者直接尝试在test中做一个单元测试来直接执行。
以上就是意见生成代码的所有内容。
拓展:
- 参数读取相关文章:
@Value注解读取配置文件中的参数
@ConfigurationProperties注解读取配置文件中的参数 - xml配置自动生成代码相关文章:
springboot集成mybatis【使用generatorConfig.xml配置自动生成代码】
Springboot集成mysql、mybatis、增删改查