springboot整合freemarker代码自动生成器

网友投稿 272 2023-01-12

springboot整合freemarker代码自动生成器

手撸一个代码自动生成器!!

实现功能:MyBatis 逆向工程

技术架构

页面是用 vue ,element-ui开发;网络请求是 Axios。

服务端是 Spring Boot

页面模版是 Freemarker:

开发步骤:

一、创建工程

二、数据库连接操作

1.所需包结构

2.在model包中创建Db类

作用:用于接受前端传来数据库连接相关的值(username,password,url)

package com.example.generate_code.model;

/**

* @author: 王泽

*/

public class Db {

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;

}

}

3.在model中创建RespBean类

自定义响应类,返回数据更方便

package com.example.generate_code.model;

/**

* @author: 王泽

*/

public class RespBean {

private Integer status;

private String msg;

private Object obj;

public static RespBean ok(String msg,Object obj) {

return new RespBean(200, msg, obj);

}

public static RespBean ok(String msg) {

return new RespBean(200, msg, null);

}

public static RespBean error(String msg,Object obj) {

return new RespBean(500, msg, obj);

}

public static RespBean error(String msg) {

return new RespBean(500, msg, null);

}

private RespBean() {

}

private RespBean(Integer status, String msg, Object obj) {

this.status = status;

this.msg = msg;

this.obj = obj;

}

public Integer getStatus() {

return status;

}

public void setStatus(Integer status) {

this.status = status;

}

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;

}

}

4.在Utils中创建DBUtils

JDBC连接工具类

public class DbUtils {

private static Connection connection;

public static Connection getConnection() {

return connection;

}

public static Connection initDb(Db db) {

if (connection == null) {

try {

Class.forName("com.mysql.cj.jdbc.Driver");

connection = DriverManager.getConnection(db.getUrl(), db.getUsername(), db.getPassword());

} catch (ClassNotFoundException | SQLException e) {

e.printStackTrace();

}

}

return connection;

}

}

5.写一个连接接口DbController

连接数据库

@RestController

public class DbController {

@PostMapping("/connect")

public RespBean connect(@RequestBody Db db) {

Connection con = DBUtils.initDb(db);

if (con != null) {

return RespBean.ok("数据库连接成功");

}

return RespBean.error("数据库连接失败");

}

}

6.创建index页面

数据库用户名:

数据库密码:

数据库连接地址:

?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai

连接数据库

配置

三、加载数据表信息

1.服务器端编写

ColumnClass 用来描述表中的每一列

package com.example.generate_code.model;

/**

* @author: 王泽

*/

public class ColumnClass {

private String propertyName; //对应java属性的名字

private String columnName; //数据库中的名字

private String type; //字段类型

private String remark; //备注

private Boolean isPrimary; //字段是不是一个主键

@Override

public String toString() {

return "ColumnClass{" +

"propertyName='" + propertyName + '\'' +

", columnName='" + columnName + '\'' +

", type='" + type + '\'' +

", remark='" + remark + '\'' +

", isPrimary=" + 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;

}

}

描述一个具体的表的信息 TableClass

package com.example.generate_code.model;

import java.util.List;

/**

* @author: 王泽

*/

public class TableClass {

private String tableName; //表名 ,以下是生成的名字

private String modelName;

private String serviceName;

private String mapperName;

private String controllerName;

private String packageName;

private List columns; // 字段

@Override

public String toString() {

return "TableClass{" +

"tableName='" + tableName + '\'' +

", modelName='" + modelName + '\'' +

", serviceName='" + serviceName + '\'' +

", mapperName='" + mapperName + '\'' +

", controllerName='" + controllerName + '\'' +

", packageName='" + packageName + '\'' +

", columns=" + columns +

'}';

}

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 getPackageName() {

return packageName;

}

public void setPackageName(String packageName) {

this.packageName = packageName;

}

public List getColumns() {

return columns;

}

public void setColumns(List columns) {

this.columns = columns;

}

}

创建配置接口Controller

用map来接受前端传来的数据

用到了谷歌提供的工具包guava,需要导入依赖

@PostMapping("/config")

public RespBean config(@RequestBody Map map) {

String packageName = map.get("packageName");

try {

Connection connection = DBUtils.getConnection();

DatabaseMetaData metaData = connection.getMetaData();

ResultSet tables = metaData.getTables(connection.getCatalog(), null, null, null);

List tableClassList = new ArrayList<>();

while (tables.next()) {

TableClass tableClass = new TableClass();

tableClass.setPackageName(packageName);

String table_name = tables.getString("TABLE_NAME");

String modelName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, table_name);

tableClass.setTableName(table_name);

tableClass.setModelName(modelName);

tableClass.setControllerName(modelName + "Controller");

tableClass.setMapperName(modelName + "Mapper");

tableClass.setServiceName(modelName+"Service");

tableClassList.add(tableClass);

}

return RespBean.ok("数据库信息读取成功", tableClassList);

} catch (Exception e) {

e.printStackTrace();

}

return RespBean.error("数据库信息读取失败");

}

com.google.guava

guava

30.1-jre

2.完善index页面

数据库用户名:

数据库密码:

数据库连接地址:

?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai

连接数据库

配置

:data="tableData"

stripe

border

style="width: 100%">

prop="tableName"

label="表名称"

width="180">

label="实体类名称"

width="180">

label="Mapper名称">

label="Service名称">

label="Controller名称">

:data="tableData"

stripe

border

style="width: 100%">

prop="tableName"

label="表名称"

width="180">

prop="tableName"

label="表名称"

width="180">

label="实体类名称"

width="180">

label="实体类名称"

width="180">

label="Mapper名称">

label="Mapper名称">

label="Service名称">

label="Service名称">

label="Controller名称">

label="Controller名称">

生成代码

四、代码生成

1.创建模板 Model.java.ftl

package ${packageName}.model;

import java.util.Date;

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>

#if>

<#if columns??>

<#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>

}

Service.java.ftl

package ${packageName}.service;

import ${packageName}.model.${modelName};

import ${packageName}.mapper.${mapperName};

import org.springframework.stereotype.Service;

import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

@Service

public class ${serviceName}{

@Autowired

${mapperName} ${mapperName?uncap_first};

public List<${modelName}> getAll${modelName}s(){

return ${mapperName?uncap_first}.getAll${modelName}s();

}

}

Controller.java.ftl

package ${packageName}.controller;

import ${packageName}.model.${modelName};

import ${packageName}.service.${serviceName};

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;

@RestController

public class ${controllerName}{

@Autowired

${serviceName} ${serviceName?uncap_first};

@GetMapping("/${modelName?lower_case}s")

public List<${modelName}> getAll${modelName}s(){

return ${serviceName?uncap_first}.getAll${modelName}s();

}

}

Mapper.java.ftl

package ${packageName}.mapper;

import ${packageName}.model.${modelName};

import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper

public interface ${mapperName}{

List<${modelName}> getAll${modelName}s();

}

Mapper.xml.ftl

PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<#list columns as column>

<<#if column.primary??>id<#else>result#if> column="${column.columnName}" property="${column.propertyName?uncap_first}" jdbcType="<#if column.type='INT'>INTEGER<#elseif column.type='DATETIME'>http://TIMESTAMP<#elseif column.type='TEXT'>VARCHAR<#else>${column.type}#if>" />

#list>

select * from ${tableName};

2.代码生成Controller

package com.example.generate_code.controller;

import com.example.generate_code.model.RespBean;

import com.example.generate_code.model.TableClass;

import com.example.generate_code.service.GenerateCodeService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

import java.util.List;

@RestController

public class GenerateCodeController {

@Autowired

GenerateCodeService generateCodeService;

@PostMapping("/generateCode")

public RespBean generateCode(@RequestBody List tableClassList, HttpServletRequest req) {

return generateCodeService.generateCode(tableClassList, req.getServletContext().getRealPath("/"));

}

}

3.编写service

package com.example.generate_code.service;

import com.example.generate_code.model.ColumnClass;

import com.example.generate_code.model.RespBean;

import com.example.generate_code.model.TableClass;

import com.example.generate_code.utils.DBUtils;

import com.google.common.base.CaseFormat;

import freemarker.cache.ClassTemplateLoader;

import freemarker.template.Configuration;

import freemarker.template.Template;

import freemarker.template.TemplateException;

import org.springframework.stereotype.Service;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.OutputStreamWriter;

import java.sql.Connection;

import java.sql.DatabaseMetaData;

import java.sql.ResultSet;

import java.util.ArrayList;

import java.util.List;

@Service

public class GenerateCodeService {

Configuration cfg = null;

{

cfg = new Configuration(Configuration.VERSION_2_3_30);

cfg.setTemplateLoader(new ClassTemplateLoader(GenerateCodeService.class, "/templates"));

cfg.setDefaultEncoding("UTF-8");

}

public RespBean generateCode(List tableClassList, String realPath) {

try {

Template modelTemplate = cfg.getTemplate("Model.java.ftl");

Template mapperJavaTemplate = cfg.getTemplate("Mapper.java.ftl");

Template mapperXmlTemplate = cfg.getTemplate("Mapper.xml.ftl");

Template serviceTemplate = cfg.getTemplate("Service.java.ftl");

Template controllerTemplate = cfg.getTemplate("Controller.java.ftl");

Connection connection = DBUtils.getConnection();

DatabaseMetaData metaData = connection.getMetaData();

for (TableClass tableClass : tableClassList) {

ResultSet columns = metaData.getColumns(connection.getCatalog(), null, tableClass.getTableName(), null);

ResultSet primaryKeys = metaData.getPrimaryKeys(connection.getCatalog(), null, tableClass.getTableName());

List columnClassList = new ArrayList<>();

while (columns.next()) {

String column_name = columns.getString("COLUMN_NAME");

String type_name = columns.getString("TYPE_NAME");

String remarks = columns.getString("REMARKS");

ColumnClass columnClass = new ColumnClass();

columnClass.setRemark(remarks);

columnClass.setColumnName(column_name);

columnClass.setType(type_name);

columnClass.setPropertyName(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, column_name));

primaryKeys.first();

while (primaryKeys.next()) {

String pkName = primaryKeys.getString("COLUMN_NAME");

if (column_name.equals(pkName)) {

columnClass.setPrimary(true);

}

}

columnClassList.add(columnClass);

}

tableClass.setColumns(columnClassList);

String path = realPath + "/" + tableClass.getPackageName().replace(".", "/");

generate(modelTemplate, tableClass, path + "/model/");

generate(mapperJavaTemplate, tableClass, path + "/mapper/");

generate(mapperXmlTemplate, tableClass, path + "/mapper/");

generate(serviceTemplate, tableClass, path + "/service/");

generate(controllerTemplate, tableClass, path + "/controller/");

}

return RespBean.ok("代码已生成", realPath);

} catch (Exception e) {

e.printStackTrace();

}

return RespBean.error("代码生成失败");

}

private void generate(Template template, TableClass tableClass, String path) throws IOException, TemplateException {

File folder = new File(path);

if (!folder.exists()) {

folder.mkdirs();

}

String fileName = path + "/" + tableClass.getModelName() + template.getName().replace(".ftl", "").replace("Model", "");

FileOutputStream fos = new FileOutputStream(fileName);

OutputStreamWriter out = new OutputStreamWriter(fos);

template.process(tableClass,out);

fos.close();

out.close();

}

}

五、测试

这时候已经找到了,我们来验证一下效果!

修改写配置

spring.datasource.name=root

spring.datasource.password=123456

spring.datasource.url=jdbc:mysql://localhost:3306/boot_crm?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai

pom.xml

src/main/java

**/*.xml

src/main/resources

导入生成的代码

运行测试

一个基本的mybatis逆向工程就完成了!

最后附上项目源代码:Gitee

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java 读取网络图片存储到本地并生成缩略图
下一篇:丰翔国际快递物流查询单号(航翔国际物流查询单号)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~