代码生成器
- 1.项目gitthub地址链接: [https://github.com/baisul/generateCode.git](https://github.com/baisul/generateCode.git)切换到master分支
- 2.环境
- 3.以下就只拿生成java实体类来作为例子
- 4.application.xml
- 5.pom.xml
- 6.Utils
- 7.生成模板
- 8.Controller
- 9.Model
- 10.index.html(数据库连接生成代码的界面)
- 11.接口
- 12.图形化界面
1.项目gitthub地址链接: https://github.com/baisul/generateCode.git切换到master分支
2.环境
2.1 springboot+freemarker+mysql
2.2 要装node.js,vue文件运行依赖node.js
3.以下就只拿生成java实体类来作为例子
4.application.xml
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
5.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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.yl</groupId>
<artifactId>generate_code</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>generate_code</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1-jre</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
6.Utils
package com.yl.generate_code.utils;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
public class CORFSConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
//所有请求都允许跨域
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*");
}
}
package com.yl.generate_code.utils;
import com.yl.generate_code.model.Db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBUtils {
private static Connection connection;
public static Connection getConnection() {
return connection;
}
public static Connection init(Db db) {
if (connection == null) {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
connection = DriverManager.getConnection( db.getUrl(),db.getUsername(), db.getPassword());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
return connection;
}
}
7.生成模板
package ${packetName}.model;
import java.util.Date;
/**
* @Description: ${modelName}实体类
* @Author: wfj
* @CreateDate ${createDate}
* @Version: 1.0V
*/
public class ${modelName} {
<#if columns??>
<#list columns as column>
<#if column.type='VARCHAR' || column.type='TEXT' || column.type='CHAR'>
/**
* ${column.remark}
*/
private String ${column.propertyName?uncap_first};
</#if>
<#if column.type='INT'>
/**
* ${column.remark}
*/
private Integer ${column.propertyName?uncap_first};
</#if>
<#if column.type='DATETIME'>
/**
* ${column.remark}
*/
private Date ${column.propertyName?uncap_first};
</#if>
<#if column.type='BIGINT'>
/**
* ${column.remark}
*/
private Long ${column.propertyName?uncap_first};
</#if>
<#if column.type='DOUBLE'>
/**
* ${column.remark}
*/
private Double ${column.propertyName?uncap_first};
</#if>
<#if column.type='BIT'>
/**
* ${column.remark}
*/
private Boolean ${column.propertyName?uncap_first};
</#if>
</#list>
<#list columns as column>
<#if column.type='VARCHAR' || column.type='TEXT' || column.type='CHAR'>
public String get${column.propertyName}() {
return ${column.propertyName?uncap_first};
}
public void set${column.propertyName}(String ${column.propertyName?uncap_first}) {
this.${column.propertyName?uncap_first} = ${column.propertyName?uncap_first};
}
</#if>
<#if column.type='INT'>
public Integer get${column.propertyName}() {
return ${column.propertyName?uncap_first};
}
public void set${column.propertyName}(Integer ${column.propertyName?uncap_first}) {
this.${column.propertyName?uncap_first} = ${column.propertyName?uncap_first};
}
</#if>
<#if column.type='DATETIME'>
public Date get${column.propertyName}() {
return ${column.propertyName?uncap_first};
}
public void set${column.propertyName}(Date ${column.propertyName?uncap_first}) {
this.${column.propertyName?uncap_first} = ${column.propertyName?uncap_first};
}
</#if>
<#if column.type='BIGINT'>
public Long get${column.propertyName}() {
return ${column.propertyName?uncap_first};
}
public void set${column.propertyName}(Long ${column.propertyName?uncap_first}) {
this.${column.propertyName?uncap_first} = ${column.propertyName?uncap_first};
}
</#if>
<#if column.type='DOUBLE'>
public Double get${column.propertyName}() {
return ${column.propertyName?uncap_first};
}
public void set${column.propertyName}(Double ${column.propertyName?uncap_first}) {
this.${column.propertyName?uncap_first} = ${column.propertyName?uncap_first};
}
</#if>
<#if column.type='BIT'>
public Boolean get${column.propertyName}() {
return ${column.propertyName?uncap_first};
}
public void set${column.propertyName}(Boolean ${column.propertyName?uncap_first}) {
this.${column.propertyName?uncap_first} = ${column.propertyName?uncap_first};
}
</#if>
</#list>
</#if>
}
8.Controller
package com.yl.generate_code.controller;
import com.google.common.base.CaseFormat;
import com.yl.generate_code.model.Db;
import com.yl.generate_code.model.ResultModel;
import com.yl.generate_code.model.TableClass;
import com.yl.generate_code.utils.DBUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@RestController
public class DBController {
@PostMapping("/connect")
public ResultModel connect(@RequestBody Db db) {
Connection connection = DBUtils.init(db);
if (connection == null) {
return ResultModel.fail("数据库连接失败");
} else {
return ResultModel.success("数据库连接成功");
}
}
@PostMapping("/config")
public ResultModel config(@RequestBody Map<String,Object> map) {
String packetName = (String)map.get("packetName");
try {
//获取数据库连接
Connection connection = DBUtils.getConnection();
//获取数据库元数据
DatabaseMetaData metaData = connection.getMetaData();
//获取数据库所有的表
ResultSet rs = metaData.getTables(connection.getCatalog(), null, null, null);
List<TableClass> list = new ArrayList<>();
while (rs.next()) {
TableClass tableClass = new TableClass();
tableClass.setPacketName(packetName);
//获取表名
String tableName = rs.getString("TABLE_NAME");
//数据库表下划线的字段转成驼峰,且首字母大写
String modelName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName);
tableClass.setTableName(tableName);
tableClass.setModelName(modelName);
tableClass.setServiceName(modelName + "Service");
tableClass.setMapperName(modelName + "Mapper");
tableClass.setControllerName(modelName + "Controller");
list.add(tableClass);
}
return ResultModel.success("数据库信息读取成功",list);
} catch (SQLException e) {
e.printStackTrace();
return ResultModel.fail("数据库信息读取失败");
}
}
}
package com.yl.generate_code.controller;
import com.yl.generate_code.model.ResultModel;
import com.yl.generate_code.model.TableClass;
import com.yl.generate_code.service.GenerateCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@RestController
public class GenerateCodeController {
@Autowired
private GenerateCodeService generateCodeService;
@PostMapping("/generateCode")
public ResultModel generateCode(@RequestBody List<TableClass> list, HttpServletRequest request) {
return generateCodeService.generateCode(list,request.getServletContext().getRealPath("/"));
}
}
9.Model
package com.yl.generate_code.model;
import java.io.Serializable;
public class ColumnClass implements Serializable {
//实体类属性名
private String propertyName;
//实体类属性名对应的表的字段名
private String columnName;
//字段类型
private String type;
//备注
private String remark;
//该字段是否为主键
private Boolean isPrimary;
public String getPropertyName() {
return propertyName;
}
public void setPropertyName(String propertyName) {
this.propertyName = propertyName;
}
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Boolean getPrimary() {
return isPrimary;
}
public void setPrimary(Boolean primary) {
isPrimary = primary;
}
@Override
public String toString() {
return "ColumnClass{" +
"propertyName='" + propertyName + '\'' +
", columnName='" + columnName + '\'' +
", type='" + type + '\'' +
", remark='" + remark + '\'' +
", isPrimary=" + isPrimary +
'}';
}
}
package com.yl.generate_code.model;
import java.io.Serializable;
public class Db implements Serializable {
private String username;
private String password;
private String url;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
package com.yl.generate_code.model;
import java.io.Serializable;
public class ResultModel implements Serializable {
private Integer code;
private String msg;
private Object obj;
public static ResultModel success(String msg,Object obj) {
return new ResultModel(200,msg,obj);
}
public static ResultModel success(String msg) {
return new ResultModel(200,msg,null);
}
public static ResultModel fail(String msg,Object obj) {
return new ResultModel(500,msg,obj);
}
public static ResultModel fail(String msg) {
return new ResultModel(500,msg,null);
}
private ResultModel() {
}
public ResultModel(Integer code, String msg, Object obj) {
this.code = code;
this.msg = msg;
this.obj = obj;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
}
package com.yl.generate_code.model;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class TableClass implements Serializable {
private String tableName;
private String modelName;
private String serviceName;
private String mapperName;
private String controllerName;
private String packetName;
private String createDate;
private List<ColumnClass> columns = new ArrayList<>();
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getModelName() {
return modelName;
}
public void setModelName(String modelName) {
this.modelName = modelName;
}
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public String getMapperName() {
return mapperName;
}
public void setMapperName(String mapperName) {
this.mapperName = mapperName;
}
public String getControllerName() {
return controllerName;
}
public void setControllerName(String controllerName) {
this.controllerName = controllerName;
}
public String getPacketName() {
return packetName;
}
public void setPacketName(String packetName) {
this.packetName = packetName;
}
public List<ColumnClass> getColumns() {
return columns;
}
public void setColumns(List<ColumnClass> columns) {
this.columns = columns;
}
public String getCreateDate() {
return createDate;
}
public void setCreateDate(String createDate) {
this.createDate = createDate;
}
}
10.index.html(数据库连接生成代码的界面)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--引入vue.js,elementui和axios-->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<table>
<tr>
<td><el-tag size="mini">数据库用户名:</el-tag></td>
<td><el-input size="mini" v-model="db.username"></el-input></td>
</tr>
<tr>
<td><el-tag size="mini">数据库密码:</el-tag></td>
<td><el-input size="mini" v-model="db.password"></el-input></td>
</tr>
<tr>
<td><el-tag size="mini">数据库连接地址:</el-tag></td>
<td><el-input size="mini" v-model="db.url">
<template slot="prepend">jdbc:mysql://</template>
<template slot="append">?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai</template>
</el-input></td>
</tr>
</table>
<div style="display: flex">
<el-button type="primary" size="mini" @click="connect" :disabled="!enableButton">连接数据库</el-button>
<div style="color: red;font-weight: bold" >{{msg}}</div>
<el-input v-model="packetName" size="mini" style="width:300px"></el-input>
<el-button size="mini" type="primary" @click="config">配置</el-button>
</div>
<el-table
:data="tableData"
stripe
border
style="width: 100%">
<el-table-column
prop="tableName"
label="表名称"
width="180">
</el-table-column>
<el-table-column
label="实体类名称"
width="180">
<template slot-scope="scope">
<el-input v-model="scope.row.modelName"></el-input>
</template>
</el-table-column>
<el-table-column
label="mapper名称">
<template slot-scope="scope">
<el-input v-model="scope.row.mapperName"></el-input>
</template>
</el-table-column>
<el-table-column
label="service名称">
<template slot-scope="scope">
<el-input v-model="scope.row.serviceName"></el-input>
</template>
</el-table-column>
<el-table-column
label="controller名称">
<template slot-scope="scope">
<el-input v-model="scope.row.controllerName"></el-input>
</template>
</el-table-column>
</el-table>
<div>
<el-button type="success" size="mini" @click="generateCode">生成代码</el-button>
<div style="color: green;font-weight: bold">{{result}}</div>
<div>{{codePath}}</div>
</div>
</div>
<script>
new Vue({
el:"#app",
data() {
return{
result: '',
codePath: '',
tableData:[],
packetName: 'com.yl',
msg : "数据库未连接",
enableButton: true,
db: {
username: "root",
password: "root",
url : "localhost:3306/demo"
}
}
},
methods: {
connect() {
let _this = this
this.db.url = "jdbc:mysql://" + this.db.url + "?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai"
axios.post("/connect",this.db).then(res => {
console.log(res.data)
_this.db = {
username: "root",
password: "root",
url : "localhost:3306/demo"
}
_this.msg = res.data.msg
_this.enableButton = false
}).catch(err => {
console.log(err)
})
},
config() {
let _this = this
axios.post("/config",{packetName: _this.packetName}).then(res => {
console.log(res.data)
_this.msg = res.data.msg
_this.tableData = res.data.obj
}).catch(err => {
console.log(err)
})
},
generateCode() {
let _this = this
axios.post("/generateCode",_this.tableData).then(res => {
console.log(res.data)
_this.result = res.data.msg
_this.codePath = res.data.obj
}).catch(err => {
console.log(err)
})
}
}
})
</script>
</body>
</html>
11.接口
package com.yl.generate_code.service;
import com.yl.generate_code.model.ResultModel;
import com.yl.generate_code.model.TableClass;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
public interface GenerateCodeService {
ResultModel generateCode(List<TableClass> list, String realpath);
}
package com.yl.generate_code.service.impl;
import com.google.common.base.CaseFormat;
import com.yl.generate_code.model.ColumnClass;
import com.yl.generate_code.model.ResultModel;
import com.yl.generate_code.model.TableClass;
import com.yl.generate_code.service.GenerateCodeService;
import com.yl.generate_code.utils.DBUtils;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Service
public class GenerateCodeServiceImpl implements GenerateCodeService {
Configuration cfg = null;
{
cfg = new Configuration(Configuration.VERSION_2_3_31);
cfg.setTemplateLoader(new ClassTemplateLoader(GenerateCodeServiceImpl.class,"/templates"));
cfg.setDefaultEncoding("utf-8");
}
@Override
public ResultModel generateCode(List<TableClass> list, String realpath) {
try {
Template modelTemplate = cfg.getTemplate("Model.java.ftl");
Template serviceTemplate = cfg.getTemplate("Service.java.ftl");
Template serviceImplTemplate = cfg.getTemplate("ServiceImpl.java.ftl");
Template mapperTemplate = cfg.getTemplate("Mapper.java.ftl");
Template mapperXmlTemplate = cfg.getTemplate("Mapper.xml.java.ftl");
Template controllerTemplate = cfg.getTemplate("Controller.java.ftl");
Connection connection = DBUtils.getConnection();
DatabaseMetaData metaData = connection.getMetaData();
for (TableClass tableClass : list) {
//根据表名获取该表的所有字段
ResultSet columns = metaData.getColumns(connection.getCatalog(), null, tableClass.getTableName(), null);
//获取该表的所有主键
ResultSet primaryKeys = metaData.getPrimaryKeys(connection.getCatalog(), null, tableClass.getTableName());
List<ColumnClass> columnClasses = new ArrayList<>();
while (columns.next()) {
//获取字段名
String column_name = columns.getString("COLUMN_NAME");
//获取字段类型
String type_name = columns.getString("TYPE_NAME");
//获取字段注释
String remark = columns.getString("REMARKS");
ColumnClass columnClass = new ColumnClass();
columnClass.setColumnName(column_name);
columnClass.setType(type_name);
columnClass.setRemark(remark);
columnClass.setPropertyName(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL,column_name));
//指标挪到第一
primaryKeys.first();
while (primaryKeys.next()) {
String primaryKey = primaryKeys.getString("COLUMN_NAME");
if (column_name.equals(primaryKey)) {
columnClass.setPrimary(true);
}
}
columnClasses.add(columnClass);
}
tableClass.setColumns(columnClasses);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
tableClass.setCreateDate(sdf.format(new Date()));
String path = realpath + "/" + tableClass.getPacketName().replace(".","/");
generate(modelTemplate,tableClass,path+"/model/",1);
generate(serviceTemplate,tableClass,path+"/service/",1);
generate(serviceImplTemplate,tableClass,path+"/service/impl",1);
generate(mapperTemplate,tableClass,path+"/mapper/",1);
generate(mapperXmlTemplate,tableClass,path+"/mapper/",2);
generate(controllerTemplate,tableClass,path+"/controller/",1);
}
return ResultModel.success("代码已生成",realpath);
} catch (Exception e) {
e.printStackTrace();
return ResultModel.fail("代码生成失败");
}
}
private void generate(Template template,TableClass tableClass,String path,Integer flag) throws IOException, TemplateException {
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
String fileName;
if (flag == 1) {
fileName = path + "/" + tableClass.getModelName() + template.getName().replace(".ftl","").replace("Model","");
} else {
fileName = path + "/" + tableClass.getModelName() + template.getName().replace(".ftl","").replace(".java","");
}
FileOutputStream fos = new FileOutputStream(fileName);
OutputStreamWriter out = new OutputStreamWriter(fos);
template.process(tableClass,out);
fos.close();
out.close();
}
}