Java SpringBoot實(shí)現(xiàn)帶界面的代碼生成器詳解
更新時(shí)間:2021年09月22日 10:12:50 作者:一只y
這篇文章主要介紹了Java SpringBoot如何實(shí)現(xiàn)帶界面的代碼生成器,幫助大家更好的理解和使用Java SpringBoot編程語言,感興趣的朋友可以了解下
1.項(xiàng)目gitthub地址鏈接: https://github.com/baisul/generateCode.git切換到master分支
2.環(huán)境
2.1 springboot+freemarker+mysql
2.2 要裝node.js,vue文件運(yùn)行依賴node.js
3.以下就只拿生成java實(shí)體類來作為例子
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) { //所有請(qǐng)求都允許跨域 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}實(shí)體類 * @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("數(shù)據(jù)庫連接失敗"); } else { return ResultModel.success("數(shù)據(jù)庫連接成功"); } } @PostMapping("/config") public ResultModel config(@RequestBody Map<String,Object> map) { String packetName = (String)map.get("packetName"); try { //獲取數(shù)據(jù)庫連接 Connection connection = DBUtils.getConnection(); //獲取數(shù)據(jù)庫元數(shù)據(jù) DatabaseMetaData metaData = connection.getMetaData(); //獲取數(shù)據(jù)庫所有的表 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"); //數(shù)據(jù)庫表下劃線的字段轉(zhuǎn)成駝峰,且首字母大寫 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("數(shù)據(jù)庫信息讀取成功",list); } catch (SQLException e) { e.printStackTrace(); return ResultModel.fail("數(shù)據(jù)庫信息讀取失敗"); } } }
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 { //實(shí)體類屬性名 private String propertyName; //實(shí)體類屬性名對(duì)應(yīng)的表的字段名 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(數(shù)據(jù)庫連接生成代碼的界面)
<!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" > <!-- 引入組件庫 --> <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">數(shù)據(jù)庫用戶名:</el-tag></td> <td><el-input size="mini" v-model="db.username"></el-input></td> </tr> <tr> <td><el-tag size="mini">數(shù)據(jù)庫密碼:</el-tag></td> <td><el-input size="mini" v-model="db.password"></el-input></td> </tr> <tr> <td><el-tag size="mini">數(shù)據(jù)庫連接地址:</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">連接數(shù)據(jù)庫</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="實(shí)體類名稱" 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 : "數(shù)據(jù)庫未連接", 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) { //根據(jù)表名獲取該表的所有字段 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)); //指標(biāo)挪到第一 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(); } }
12.圖形化界面
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
您可能感興趣的文章:
- Java SpringBoot高級(jí)用法詳解
- java編程之基于SpringBoot框架實(shí)現(xiàn)掃碼登錄
- java進(jìn)階解析Springboot上傳excel存入數(shù)據(jù)庫步驟
- Java SpringBoot自動(dòng)裝配原理詳解
- Java SpringBoot實(shí)現(xiàn)AOP
- Java SpringBoot整合SpringCloud
- Java Springboot的目的你知道嗎
- Java中Druid連接池連接超時(shí)獲取不到連接的解決
- java操作Apache druid的實(shí)例代碼
- Druid基本配置及內(nèi)置監(jiān)控使用_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- Java之SpringBoot自定義配置與整合Druid
相關(guān)文章
java 數(shù)值類型分秒時(shí)間格式化的實(shí)例代碼
這篇文章主要介紹了java 數(shù)值類型分秒時(shí)間格式化的實(shí)例代碼的相關(guān)資料,將秒或分鐘的值轉(zhuǎn)換為xx天xx小時(shí)xx分鐘xx秒 如果 “xx” 為0 自動(dòng)缺省,需要的朋友可以參考下2017-07-07SpringBoot3 Spring WebFlux簡介(推薦)
SpringWebFlux是Spring Framework 5中引入的響應(yīng)式Web框架,用于支持非阻塞異步通信和響應(yīng)式流處理,與傳統(tǒng)的SpringMVC相比,WebFlux提供了完全異步非阻塞的編程模型,適用高并發(fā)、微服務(wù)架構(gòu)和實(shí)時(shí)數(shù)據(jù)流,本文介紹SpringBoot3 Spring WebFlux簡介,感興趣的朋友一起看看吧2024-10-10SpringBoot實(shí)現(xiàn)版本升級(jí)到2.7.18
這篇文章主要介紹了SpringBoot實(shí)現(xiàn)版本升級(jí)到2.7.18全過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08圖解二叉樹的三種遍歷方式及java實(shí)現(xiàn)代碼
本篇文章主要介紹了圖解二叉樹的三種遍歷方式及java實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,有興趣的可以了解一下2017-07-07Java基于fork/koin類實(shí)現(xiàn)并發(fā)排序
這篇文章主要介紹了Java基于fork/koin類實(shí)現(xiàn)并發(fā)排序,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02